The unofficial Lua FAQ has an entry about sandboxing in Lua.
My guess is that you can transpose that logic easily enough to your C/C++ code.
See also LuaFiveTo on the lua-users wiki.
Correction
It's indeed not as trivial as it seemed. But in the end the point is simple: load your chunk, push the _ENV table, use lua_setupvalue(L,-2,1)
. The important is that the table should be at the top of the stack.
As a small example, using 2 environments defaulting to _G for reading stuff via metatables:
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
int main(void){
lua_State *L = luaL_newstate();
char *file1 = "file1.lua";
char *file2 = "file2.lua";
luaL_openlibs(L);
luaL_loadfile(L,file2); // S: 1
luaL_loadfile(L,file1); // S: 2
lua_newtable(L); // ENV for file 1: S: 321
lua_newtable(L); // ENV for file 2: S: 4321
//lets have each function have its metatable, where missed lookups are
//instead looked up in the global table _G
lua_newtable(L); // metatable S: 54321
lua_getglobal(L,"_G"); // pushes _G, which will be the __index metatable entry S: 654321
lua_setfield(L,-2,"__index"); // metatable on top S: 54321
lua_pushvalue(L,-1); // copy the metatable S: 554321
lua_setmetatable(L,-3); // set the last copy for env2 S: 54321
lua_setmetatable(L,-3); // set the original for env1 S: 4321
// here we end up having 2 tables on the stack for 2 environments
lua_setupvalue(L,1,1); // first upvalue == _ENV so set it. S: 321
lua_setupvalue(L,2,1); // set _ENV for file S: 21
// Remaining on the stack: 2 chunks with env set.
lua_pcall(L,0,LUA_MULTRET,0);
lua_pcall(L,0,LUA_MULTRET,0);
lua_close(L);
return 0;
}
And for the 2 Lua files:
-- file1.lua
function init()
A="foo"
print("Hello from file1")
print(A)
end
init()
-- file2.lua
-- this shows that stuff defined in file1 will not polute the environment for file2
print("init function is",tostring(init))
function init()
A="bar"
print("Hello from file2")
print(A)
end
init()
load
andloadfile
functions let you specify an environment; they are probably the best place to start searching for a solution. – Arksetuservalue
is definitely not the correct function to use when trying to manipulate the environment. The lua docs seem somewhat unclear on what you should be doing, however.lua_load
says that a single upvalue associated with a loaded chunk is set as its environment, but does not mention how you go about associating an upvalue with the chunk from C. If you were loading the chunk from within lua, the lua version of theload
function looks like it should set the environment correctly. – Arklua_setupvalue
. It is in the docs as part of the debug API, and as such you should not need to touch it for normal use of lua. – Arkload
orloadfile
as called from lua require you to mess with the debug interface, andlua_pushcclosure
(part of the C API) has a way of specifying the number of upvalues you wish to push by way of a function argument, also avoiding the need to use the debug API. Solua_load
is a bit unusual. Guess I'll just have to see what the lua mailing list folk have to say about that particular little wart. – Ark