所以我对Lua中的全局默认样式感到恼火。我正在尝试编写一个程序,它将使所有程序在无法创建全局变量之后运行。当他们尝试时,该变量将被设置为该程序的功能环境。我想出了这个,它似乎工作,但由于某种原因在ComputerCraft rom / programs / edit中的[edit:9]中抛出一个错误。当我运行测试程序时,
a = 1
print(a)
它工作正常并且阻止创建全局变量,同时仍然允许该程序访问它,但它不适用于其他程序。我已经尝试过_G.a,本地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
答案 0 :(得分:1)
Lua旨在成为一种嵌入式语言。这意味着最终仲裁者是主语C。
一个Lua脚本可以通过沙盒技术实现对另一个的支配。您没有完全沙箱脚本。您更改了loadfile
,但未更改load
或dofile
。
但这没关系。为什么?因为在支配地位方面, C总是赢得。请参阅,C不会调用Lua loadfile
函数。嗯,显然可以,但通常不会。相反,它调用Lua API luaL_loadfile
。
Lua代码可以为其直接加载的其他Lua代码建立沙箱。但是基于Lua的沙箱对C代码没有影响,除非该代码被故意设计为生活在Lua沙箱中。大多数C库都没有。
这意味着,一旦您决定在无法控制的C执行环境中运行,您的Lua沙箱就意味着什么。 C代码可以(在许多情况下)将脚本加载到您的控件之外,并为它们提供所需的任何环境。
从Lua那里你无能为力。解决此问题的唯一方法是修改Lua .dll本身以建立沙箱。
答案 1 :(得分:0)
我找到了解决方案。事实证明,shell API(许多ComputerCraft程序中使用的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