Reputation: 3054
I wonder if it's possible to only close a chuck of Lua code loaded with luaL_dostring
so all the variables inside the chunk can be freed accordingly.
Here's my simple example:
lua_State *L = luaL_newstate();
luaL_openlibs(L);
luaL_dostring(L, "a = 2"); // Script A
//How close the script A here?
luaL_dostring(L, "print(a)"); // Script B
lua_close(L);
This code prints 2
when I run it but I wonder if it's possible to somehow close(or free) only the firstly loaded chunk from the memory so it prints nil
.
Upvotes: 0
Views: 723
Reputation: 10939
Roughly speaking you want to sandbox script A, i.e. run it with a different global environment than script B. This can easily be done by backing up the global table into the registry and replacing it with an empty table (optionally populate the empty table with whatever you need inside the sandbox). After script A is finished you simply retrieve the old global table from the registry and make it the current global table again.
Apart from that I recommend reducing the usage of globals to an absolute minimum. In fact, I never use any global variables when I write Lua code. Usually I record information in local tables and pass these around. This is probably a more functional style of writing Lua.
#include <iostream>
#include <lua.hpp>
int main() {
lua_State *L = luaL_newstate();
luaL_openlibs(L);
// START SANDBOX
// Push the global table into the registry
lua_pushglobaltable(L);
lua_setfield(L, LUA_REGISTRYINDEX, "globals");
// Push a new empty table and make it the global table
lua_newtable(L);
lua_rawseti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS);
// Script A
if (luaL_dostring(L, "a = 2") != 0) {
std::cerr << "lua:" << lua_tostring(L, -1) << '\n';
lua_pop(L, 1);
}
// Retrieve the global table from the registry and make it the global table
lua_getfield(L, LUA_REGISTRYINDEX, "globals");
lua_rawseti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS);
// Optional: Remove the global table from the registry
lua_pushnil(L);
lua_setfield(L, LUA_REGISTRYINDEX, "globals");
// END SANDBOX
// Script B
if (luaL_dostring(L, "print(a)") != 0) {
std::cerr << "lua:" << lua_tostring(L, -1) << '\n';
lua_pop(L, 1);
}
lua_close(L);
}
$ clang++ -Wall -Wextra -Wpedantic -I /usr/include/lua5.2/ test.cpp -llua5.2
$ ./a.out
nil
Upvotes: 3