Sandboxing Embedded Lua in 5.2 / Installing Envirenment for functions from lua.file

Suppose I have at least two lua script files.

test1.lua test2.lua

both define an init function and other functions with similar names.

How can I upload each script file using C ++ / c to a separate environment using Lua 5.2, so that the same function names will not collide - I found code example for 5.1 that does not work for me (since setenv is gone and lua_setuservalue doesn't seem to work)

Sample here Calling lua functions from .lua usage descriptors?

Basically, if I replace setenv with setuservalue, I get an access violation.

+7
source share
2 answers

The unofficial Lua FAQ contains a record about the sandbox in Lua. I assume that you can easily port this logic to your C / C ++ code.

See also LuaFiveTo for lua wiki users .

Correction

It really is not as trivial as it seemed. But in the end, the point is simple: upload your piece, click the _ENV table, use lua_setupvalue(L,-2,1) . The important thing is that the table should be at the top of the stack.

As a small example, using 2 default environments for _G to read materials through 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 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() 
+8
source

both define an init function and other functions with similar names.

First of all, why are these features global? They must be local to the script. If you are going to require them in other files, they must create and return a table containing the functions that they want to open.

The modern idiom requiring these files is to do something like this:

 local Library = require 'library' Library.Func1(...) 

This way you are not polluting the global Lua namespace. You are using local variables.

However, if you insist on using such global globals, you can do exactly what the documentation says: change the first upvalue of the compiled fragment.

Basically, if I replace setenv with setuservalue, I get an access violation.

Of course yes. This is not what lua_setuservalue does. It is designed to set values ​​associated with user data. What you want is called lua_setupvalue .

Using the code sample that you are quoting, the correct answer would be:

 lua_setupvalue(L, -2, 1); 
0
source

All Articles