5

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);
CiscoIPPhone
  • 9,457
  • 3
  • 38
  • 42

2 Answers2

9

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.

Alexander Gladysh
  • 39,865
  • 32
  • 103
  • 160
  • You are correct. Shouldn't the third parameter be LUA_MASKCOUNT though? Even just instructions is not ideal - for example if the Lua code goes off an calls a long C function. However it will do for my purposes for now, thanks. – CiscoIPPhone May 15 '09 at 07:06
  • Yes, sorry. I've added LUA_MASKCOUNT now. – Alexander Gladysh May 15 '09 at 09:52
7

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);
  • You probably want either to call `luaL_error(L, "message")` or to push something on Lua stack before call to `lua_error(L)`. – Alexander Gladysh May 14 '09 at 22:42
  • Thanks Alexander, I've edited the answer. You're correct about single line loops / infinite loops in C code, I admit I didn't delve into the complexities of the situation. – Matthew Monaghan May 15 '09 at 15:26