Lua 带有个人 baselib 的沙箱 _ENV(要求、断言等)
Lua sandbox _ENV with personal baselib (require, assert etc)
Lua 5.3.2
我有一个用 Lua/C 编写的服务,它在相同的 Lua_State.
中执行 lua 个文件
我需要提供文件执行环境的所有标准库。
最简单的就是这样执行文件:loadfile(file_path, "bt", _G)
问题是:文件中的代码能够破坏服务的全局状态,因此此方法不安全。
所以,我需要创建一个沙盒环境loadfile(file_path, "bt", env)
问题:如何在env
变量中注册linit.c的所有标准库?
我可以简单地注册 linit.c 中的所有库,除了 luaopen_base,因为它包含 lua_pushglobaltable
我想过这个:
local env = {}
for k,v in pairs(_G) do
if type(v)=="function" then
env[k] = v
end
end
但这看起来是个可悲的决定。有人有更好的解决方案吗?
最简单的方法是让 env
继承自 _G
:
setmetatable(env,{__index=_G})
_G
中的所有内容都会在env
中看到,但是如果你通过创建一个全局变量写入env
,它不会影响_G
,这看来是你想要的。
不幸的是,_G
本身在 _G
中可见,因此可以通过执行 _G.print=anyvalue
.
之类的操作来写入原始环境
为了保护 _G
,添加:
env._G = env
遗憾的是,原来的 _G
仍然可以通过 package.loaded._G
获得。如果您想授予对 package
的访问权限,这将更难保护。最简单的方法是将 _G.package
深复制到 env.package
并更改 env.package.loaded._G=env
.
Lua 5.3.2
我有一个用 Lua/C 编写的服务,它在相同的 Lua_State.
中执行 lua 个文件我需要提供文件执行环境的所有标准库。
最简单的就是这样执行文件:loadfile(file_path, "bt", _G)
问题是:文件中的代码能够破坏服务的全局状态,因此此方法不安全。
所以,我需要创建一个沙盒环境loadfile(file_path, "bt", env)
问题:如何在env
变量中注册linit.c的所有标准库?
我可以简单地注册 linit.c 中的所有库,除了 luaopen_base,因为它包含 lua_pushglobaltable
我想过这个:
local env = {}
for k,v in pairs(_G) do
if type(v)=="function" then
env[k] = v
end
end
但这看起来是个可悲的决定。有人有更好的解决方案吗?
最简单的方法是让 env
继承自 _G
:
setmetatable(env,{__index=_G})
_G
中的所有内容都会在env
中看到,但是如果你通过创建一个全局变量写入env
,它不会影响_G
,这看来是你想要的。
不幸的是,_G
本身在 _G
中可见,因此可以通过执行 _G.print=anyvalue
.
为了保护 _G
,添加:
env._G = env
遗憾的是,原来的 _G
仍然可以通过 package.loaded._G
获得。如果您想授予对 package
的访问权限,这将更难保护。最简单的方法是将 _G.package
深复制到 env.package
并更改 env.package.loaded._G=env
.