一个默认启用本地变量的程序

所以我对 Lua 的默认全局变量风格感到烦恼。我正在尝试编写一个程序,它将使所有在其之后运行的程序无法创建全局变量。当他们尝试这样做时,该变量将被设置为该程序的函数环境。我想出了这个方法,它看起来可以工作,但由于某种原因在 [编辑:9] 中,ComputerCraft rom/programs/edit 中会引发错误。当我运行一个测试程序时,

a = 1
print(a)

它可以正常工作,并可以防止创建全局变量,同时仍然允许该程序访问该变量,但对于其他程序它不起作用。我尝试过使用 _G.a、local a 和其他方法,但它们都无效。是否有人有任何关于它可能无法在其他程序中工作的想法?

local oldload = loadfile
function _G.loadfile(str)
  local func = oldload(str)
  local env = {}
  env._G = env
  setmetatable(env, {__index = _G, __newindex =
    function(table, var, val)
      rawset(env, var, val)
    end})
  setfenv(func, env)
  return func
end
点赞
用户734069
用户734069

Lua旨在成为嵌入式语言。 这意味着最终的裁判是宿主语言C。

通过沙箱技术,一个Lua脚本可以支配另一个Lua脚本。你没有完全沙盒化你的脚本。你改变了loadfile,但是你没有改变loaddofile

但这不重要。为什么?因为在支配方面,C总是赢。看,C不会调用Lua的loadfile函数。当然,它显然可以,但通常不会。而是调用Lua API中的luaL_loadfile

Lua代码可以为直接加载的其他Lua代码建立一个沙箱。但除非该代码是有意设计为在Lua沙箱中运行,否则基于Lua的沙箱对C代码没有影响。而大多数C库都不是。

这意味着一旦你决定在一个你不能控制的C执行环境中运行,你的Lua沙箱就无关紧要了。C代码可以,并且在许多情况下会,加载你无法控制的脚本,并赋予它们它想要的任何环境。

从Lua方面来说,你无能为力。解决这个问题的唯一方法是修改Lua.dll本身来建立你的沙箱。

2016-02-09 23:35:43
用户5229421
用户5229421

我找到了解决方案。原来许多 ComputerCraft 程序使用的 shell API 并不在 _G 中,所以在应用沙盒时无法访问。以下是我的新功能代码:

local oldload = load
function _G.load(str, arg1, arg2, arg3)
  local func = oldload(str, arg1, arg2, arg3)
  local env = getfenv(func)
  if (env == _G) then
    env = {}
    env._G = env
  end
  setmetatable(env, {__index = _G, __newindex = function(table, var, val) rawset(env, var, val) end})
  setfenv(func, env)
  return func
end
2016-02-10 00:05:15