代码之家  ›  专栏  ›  技术社区  ›  Lee

LuaJIT setfenv似乎没有对给定环境设置进一步的函数调用

  •  3
  • Lee  · 技术社区  · 9 年前

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

    123
    nil
    

    为什么 testValue 打电话的时候 sandboxTest() nil ,但在访问时是123 callSandboxedTest() ?

    使用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()
    
    2 回复  |  直到 9 年前
        1
  •  2
  •   Nicol Bolas    9 年前

    环境不是调用堆栈的一部分。每个函数都有它的 拥有 环境所以 sandboxTest 有一个环境 callSandboxTest 改变一个功能的环境对另一功能的环境没有影响。

    沙盒试验 将继续使用默认环境,因此它将访问常规全局表以查找 testValue .及自 测试值 从未在全局表中设置, 沙盒试验 会得到 nil .

    这就是为什么在维护沙箱时,仔细选择向沙箱公开哪些功能非常重要。如果函数需要成为沙盒的一部分,那么该函数需要设置其环境。

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

        2
  •  1
  •   Paul Kulchenko    9 年前

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

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

    这将打印 123 123 .