Hi. Background: I've been using Lua 5.1 for a few years as a configuration and extension language for our C++ programs at my work. We have a C++ wrapper interface that sandboxes the lua script that's loaded from file or string, and also provides a sandboxed interface to calling out to lua functions where desired. The original ideas for the sandbox were derived from my reading of the various Lua literature available a few years ago when Lua 5.1 was the current release. I'm seeking advice on the best way to use Lua 5.2 from C/C++ to load chunks in a sandboxed environment and subsequently invoke lua functions from C/C++ in that same sandbox. With the change in Lua 5.2 to deprecate lua_setfenv() in favour of other techniques (upvalues ?), I would like to update the C++ wrapper library for Lua 5.2/5.3 as well as continuing to support Lua 5.1. It may be that the pattern I used for Lua 5.1 can't be used for Lua 5.2 and I need to redesign my wrapper library. I'd prefer to do that in a way that reduces change on callers of the library. Current use in Lua 5.1: The sandboxing setup technique used in Lua 5.1 is: a) create a table for the environment b) copy names of "safe" globals into the table, such as assert(), ipairs(), string.*, (etc) c) add other (private) extensions to the table d) add the table to the global environment with a well-known name To invoke a chunk or function a) limit instructions / maskcount b) get the sandbox table from the global environment c) set the environment for the chunk/function with lua_setfenv() d) call the chunk/function To lookup a table value (e.g. to obtain t1.t2 from "t1 = { t2 = 5, }") methods to obtain the values by traversing the sandbox table. This has been working well for a few years. Attempt to convert to Lua 5.2: I've tried converting our use of lua_setfenv() to lua_setupvalue() but it's not setting up the environment correctly when trying to set the environment for a function call (versus a chunk call). lua_setupvalue(L, -3, 1) is returning NULL when the stack has; 1: function 2: table as function argument 3: table to use as environment I.e. When I change Lua 5.1's lua_setfenv(L, -iNumArgs - 2)) to Lua 5.2's lua_setupvalue(L, -iNumArgs - 2, 1) my sandboxing doesn't work. Pseudo-code of the Lua 5.1 sandbox technique: // Construct state lua_State * setup() lua_State * L = luaL_newstate(); // sandbox will get a subset of the libs luaL_openlibs(L); return L; // Load string onto stack loadstring(lua_state * L, const char * str) // (loadfile is similar) luaL_loadstring(L, str) callChunk(L); // Setup sandbox and call chunk on the stack callChunk(lua_state * LL) lua_newtable(L) // populate table for sandbox setupSandbox(L) lua_setglobal(L, "LuaSandbox"); // store sandbox in global var sandboxCall(L, 0, 0) // Call function on stack in a sandbox (maskcount, restricted environment) sandboxCall(lua_state * L, int iNumArgs, int iNumResults) lua_sethook(L, &maskcount, LUA_MASKCOUNT, someLimit); lua_getglobal(L, "LuaSandBox"); // set environment to sandbox lua_setfenv(L, -iNumArgs - 2); lua_pcall(L, iNumArgs, iNumResults); lua_sethook(L, &maskcount, LUA_MASKCOUNT, 0); // Setup table for use as a sandbox environment. Caller may extend. setupSandbox(lua_State * L) // copy values from global environment into sandbox table on stack top // Call a lua function from C that takes a table argument & returns a bool fooFunction(lua_State * L) findName(L, "some_method"); if (! lua_isfunction(L, -1)) error(); lua_createTable(L, 0, 1); lua_pushstring(L, "some value"); lua_setfield(L, "k"); // { k = "somevalue", } sandboxCall(L, 1, 1) // invoke some_method({k="somevalue"}) bool result = lua_toboolean(L, -1) lua_pop(L, 1); return result; Regards, Luke.
Attachment:
pgpU5o5L9z_lg.pgp
Description: PGP signature