My situation is that I'm using the Lua (C) API to execute a script held in a string.
I would like the user to be able to terminate the execution of the script (this is essential if the script contains an infinite loop), how can I do this?
lua_State *Lua = lua_open();
char * code;
// Initialisation code
luaL_dostring(L, code);
You can use a hook to callback to C every time lua executes a line of the script.
In this hook function you can check if the user wanted to quit, and call lua_error if they did.
static bool ms_quit = false;
void IWantToQuit()
{
ms_quit = true;
}
void LineHookFunc(lua_State *L, lua_Debug *ar)
{
if(ar.event == LUA_HOOKLINE)
if(ms_quit == true)
luaL_error(L, "Too Many Lines Error");
}
//...
lua_State *Lua = lua_open();
char * code;
// Initialisation code
lua_sethook(Lua, &LineHookFunc, LUA_MASKLINE, 0);
luaL_dostring(L, code);
Hook on lines is not enough. This code is a single line, but loops forever:
while true do end
You need to set an instruction count hook. If I'm not mistaken, that would be
lua_sethook(Lua, &LineHookFunc, LUA_MASKCOUNT, NUM_INSTRUCTIONS);
You want to pick NUM_INSTRUCTIONS so it is not too small (or you get a performance overhead) and not too large (or you'll wait too long until stop).
For related Lua-only implementation please see this library.
If you want to add more protection from untrusted Lua code, google for "Lua sandboxing" -- there is more to it than just infinite loop prevention.