LuaJIT setfenv not appearing to set further function calls to the given environment

498 views Asked by At

I'm attempting to sandbox some functions using setfenv, and I recieve the following output:

123
nil

Why is testValue when calling sandboxTest() nil, but it's 123 when it's accessed in callSandboxedTest()?

Using 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

There are 2 answers

0
Nicol Bolas On BEST ANSWER

Environments aren't part of the call stack. Every function has its own environment. So sandboxTest has an environment, as does callSandboxTest. Changing the environment of one function has no effect on the environment of another.

sandboxTest will continue to use the default environment, so it will access the regular global table to find testValue. And since testValue is never set in the global table, sandboxTest will get nil.

That's why, when maintaining a sandbox, it is very important to carefully choose what functionality to expose to the sandbox. If a function needs to be part of the sandbox, then that function needs to have its environment set.

That's why it's best to sandbox based on compiled Lua chunks rather than individual functions. When creating functions, the functions created will inherit the current environment.

0
Paul Kulchenko On

You haven't modified the environment that sandboxTest is using; you only modified the environment of the current function. You can use setfenv to set the environment of a particular function by passing a function name (passing a number modifies the environment of a function in the call stack):

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

This will print 123 123.