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.