2

所以我对 Lua 中的全局默认样式感到恼火。我正在尝试编写一个程序,该程序将使在它之后运行的所有程序都无法创建全局变量。当他们尝试时,该变量将设置为该程序的功能环境。我想出了这个,它似乎可以工作,但由于某种原因,在 ComputerCraft rom/programs/edit 的 [edit: 9] 中抛出了一个错误。当我运行一个测试程序时,

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
4

2 回答 2

1

Lua 被设计成一种嵌入式语言。这意味着最终的仲裁者是宿主语言 C。

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

但这没关系。为什么?因为就优势而言,C 总是获胜。看,C 不调用 Lualoadfile函数。好吧,它显然可以,但通常不会。相反,它调用 Lua API luaL_loadfile

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

这意味着,一旦您决定在您无法控制的 C 执行环境中运行,您的 Lua 沙箱就毫无意义。C 代码可以并且在许多情况下会加载您无法控制的脚本并为它们提供所需的任何环境。

并且在 Lua 中你无能为力。解决此问题的唯一方法是修改 Lua .dll 本身以建立您的沙箱。

于 2016-02-09T23:35:43.817 回答
0

我找到了解决方案。事实证明,许多 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-10T00:05:15.007 回答