LuaJIT setfenv 函数似乎没有将进一步的函数调用设置为指定的环境

我正在尝试使用 setfenv 函数对一些函数进行沙箱化,并且我收到以下输出:

123
nil

为什么在调用 sandboxTest()testValuenil,但在 callSandboxedTest() 中访问时却是 123?

使用的是 LuaJIT 2.1.0-beta2 (Lua 5.1)

function sandboxTest()
    print(testValue)
end

local aNumber = 123

function callSandboxedTest()
    setfenv(1, {
        print = print,
        testValue = aNumber,
        sandboxTest = sandboxTest
    })
    print(testValue)
    sandboxTest()
end

callSandboxedTest()
点赞
用户734069
用户734069

环境不是调用栈的一部分。每个函数都有自己的 环境。因此,sandboxTest 有一个环境,callSandboxTest 也有一个环境。更改一个函数的环境不会影响另一个函数的环境。

sandboxTest 将继续使用默认环境,因此它将访问常规全局表以查找 testValue。由于 testValue 从未在全局表中设置,sandboxTest 将得到 nil

因此,在维护沙盒时,非常重要的是仔细选择要向沙盒公开哪些功能。如果一个函数需要成为沙盒的一部分,则需要设置该函数的环境。

这就是为什么最好基于编译的 Lua 块而不是单个函数来创建沙盒。在创建函数时,创建的函数将继承当前环境。

2016-12-31 04:08:58
用户1442917
用户1442917

你没有修改sandboxTest使用的环境,你只修改了当前函数的环境。你可以使用setfenv通过传递函数名称来设置特定函数的环境(传递数字修改调用堆栈中的函数的环境):

setfenv(sandboxTest, {
        print = print,
        testValue = aNumber,
        sandboxTest = sandboxTest
    })

这将打印123 123

2016-12-31 05:27:19