使用个人baselib(require,assert等)的Lua沙箱_ENV

我有一个用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

但它看起来很可怜。 有更好的解决方案吗?

点赞
用户107090
用户107090

最简单的方法是让 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 更改。

2016-01-05 01:05:51