Il unofficial Lua FAQ ha una voce sulla sandboxing in Lua. La mia ipotesi è che si possa trasporre quella logica abbastanza facilmente al proprio codice C/C++.
Vedere anche LuaFiveTo on the lua-users wiki.
Correzione
Non è infatti così banale come sembrava. Ma alla fine il punto è semplice: carica il tuo chunk, premi il tavolo _ENV, usa lua_setupvalue(L,-2,1)
. L'importante è che la tabella dovrebbe essere in cima alla pila.
Come un piccolo esempio, utilizzando 2 ambienti inadempienti per _G per le cose di lettura tramite 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;
}
E per i file di 2 Lua:
-- 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()
Questo è uno dei motivi per cui ho bloccato con lua 5.1 nei miei progetti, per ora. Credo che le funzioni v5.2 'load' e' loadfile' permettano di specificare un ambiente; sono probabilmente il posto migliore in cui iniziare a cercare una soluzione. – Rook
grazie ma ho letto su load e loadfile tuttavia non sono riuscito a trovare una soluzione – Steve
'setuservalue' non è sicuramente la funzione corretta da utilizzare quando si tenta di manipolare l'ambiente. I documenti lua sembrano in qualche modo poco chiari su ciò che dovresti fare, comunque. 'lua_load' dice che un singolo upvalue associato ad un chunk caricato viene impostato come ambiente, ma non menziona come si va ad associare un upvalue con il chunk di C. Se si stava caricando il blocco da dentro lua, la versione lua di la funzione 'load' sembra che dovrebbe impostare correttamente l'ambiente. – Rook