tags:

views:

109

answers:

1
luaL_loadfile(mState, path.c_str());
lua_pcall(mState, 0, 0, 0);

Is there a way to put an execution time limit (say 10-20 seconds) for those two C++ statements, that load and then execute a lua file?

Since the Lua file is untrusted I don't want a malicious user to hang the program indefinitely with an infinite loop in the Lua code.

Tagging C because the Lua API is C, tagging C++ because I'm using C++

+8  A: 

There's lua_sethook which can be used to tell the interpreter to call a hook after every 'count' instructions executed. This way you can monitor the user script and terminate it if it eats up its quota:

 int lua_sethook (lua_State *L, lua_Hook f, int mask, int count);

This can also be used from Lua:

debug.sethook(function() print("That's enough for today"); os.exit(0); end, "", 10000)
for i=1,10000 do end

If you use the techniques from:

then you can set up a safe execution environment with sethook() and friends entirely from Lua and then switch to sandbox mode while executing the user script. I've tried that here, just for you to get started:

-- set an execution quota 
local function set_quota(secs)
 local st=os.clock()
 function check() 
  if os.clock()-st > secs then 
    debug.sethook() -- disable hooks
    error("quota exceeded")
  end
 end
 debug.sethook(check,"",100000);
end

-- these are the global objects, the user can use:
local env = {print=print}

-- The user code is allowed to run for 5 seconds.
set_quota(5)

-- run code under environment:
local function run(untrusted_code)
  local untrusted_function, message = loadstring(untrusted_code)
  if not untrusted_function then return nil, message end
  setfenv(untrusted_function, env)
  return pcall(untrusted_function)
end

-- here is the user code:
local userscript=[[
function fib(n) 
 if n<2 then return n
 else return fib(n-2)+fib(n-1)
 end
end
for n=1,42 do print(n,fib(n)) end
]]
-- call it:
local r,m=run(userscript)
print(r,m)

This should print values of fib() for 5 seconds and then show an error.

Luther Blissett
Great answer, thank you!
Andreas Bonini