Lua 5.2中的沙箱 [英] Sandboxing in Lua 5.2
问题描述
我正在从Roberto Ierusalimschy的在Lua中编程"中学习,我发现在书中,沙箱示例使用功能setfenv()
来更改给定功能的环境,但是在lua 5.2中,此功能是不再可用.
I am learning from "Programing in Lua" by Roberto Ierusalimschy, and I found that in the book, the example of Sandboxing uses the function setfenv()
to change the environment of a given function, but in lua 5.2 this function is no longer available.
我试图将文件(配置文件)中的某些值加载到表中的字段中,但是在lua 5.2中,我不能使用setfenv(因此我可以在给定的环境中加载值).在阅读了有关lua 5.2的一些文章后,我发现每个函数可能具有(或不具有)一个称为_ENV的上值作为环境,因此,我尝试了以下代码:
I tried to load some values from a file (a configuration file) into a field in a table, but, in lua 5.2 I can't use setfenv ( so I can load the values in the given environment). After reading some articles about lua 5.2 I found that each function may have (or not) an upvalue called _ENV which serves as the environment, so, I tried the following code:
function sandbox(sb_func, sb_env)
if not sb_func then return nil, "sandbox function not valid" end
sb_orig_env = _ENV
_ENV = sb_env -- yes, replaces the global _ENV
pcall_res, message = pcall( sb_func )
local modified_env = _ENV -- gets the environment that was used in the pcall( sb_func )
_ENV = sb_orig_env
return true, modified_env
end
function readFile(filename)
code = loadfile(filename)
res, table = sandbox(code, {})
if res then
--[[ Use table (modified_env) ]]--
else
print("Code not valid")
end
在'sandbox'函数中替换_ENV
效果很好(无法访问常规字段),但是,当执行'code'时,它似乎忽略了我替换的_ENV
,它仍然可以访问常规字段(打印,加载文件,文件等).
Replacing _ENV
in the 'sandbox' function works well (can't access the regular fields), but, when the 'code' is executed it seems that it ignores that I replaced _ENV
, it still can access regular fields (print, loadfile, dofile, etc).
多读一点,我发现lua 5.2为此提供了一个功能,该功能是loadin(env, chunk)
,它在给定的环境中运行给定的块,但是,当我尝试将此功能添加到我的代码中时,该功能不存在(全局_G
字段中不存在).
Reading a little more, I found that lua 5.2 provides a function for this purpose, this function is loadin(env, chunk)
, which runs the given chunk in the given environment, but, when I try to add this function to my code, the function doesn't exist ( Is not present in the global _G
field).
一些帮助将不胜感激.
推荐答案
从sandbox
内部分配给_ENV
时,您不会覆盖全局环境,而是替换当前正在运行的代码的_ENV
升值.将呼叫添加到print(_ENV)
可能有助于您更好地了解所涉及表的身份.
When you assign to _ENV
from within sandbox
, you're not overwriting the global environment--you're replacing the _ENV
upvalue of the currently running code. Adding calls to print(_ENV)
may help you better understand the identities of the tables involved.
例如:
function print_env()
print(_ENV)
end
function sandbox()
print(_ENV) -- prints: "table: 0x100100610"
-- need to keep access to a few globals:
_ENV = { print = print, print_env = print_env, debug = debug, load = load }
print(_ENV) -- prints: "table: 0x100105140"
print_env() -- prints: "table: 0x100105140"
local code1 = load('print(_ENV)')
code1() -- prints: "table: 0x100100610"
debug.setupvalue(code1, 1, _ENV) -- set our modified env
code1() -- prints: "table: 0x100105140"
local code2 = load('print(_ENV)', nil, nil, _ENV) -- pass 'env' arg
code2() -- prints: "table: 0x100105140"
end
loadin
函数存在于Lua 5.2的某些预发行版本中,但在最终发行版本之前已被删除.相反,Lua 5.2 load
和loadfile
函数接受env
参数.您还可以使用 debug.setupvalue
修改另一个函数的_ENV
.
The loadin
function was present in some pre-release versions of Lua 5.2 but was removed before the final release. Instead, the Lua 5.2 load
and loadfile
functions take an env
argument. You can also modify the _ENV
of another function using debug.setupvalue
.
这篇关于Lua 5.2中的沙箱的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!