2010-08-03 8 views
9
luaL_loadfile(mState, path.c_str()); 
lua_pcall(mState, 0, 0, 0); 

C'è un modo per mettere un limite di tempo di esecuzione (diciamo 10-20 secondi) per quei due affermazioni C++, che il carico e quindi eseguire un file lua?esecuzione per uno script Lua chiamato dalla C API

Poiché il file Lua non è affidabile, non voglio che un utente malintenzionato appenda il programma indefinitamente con un ciclo infinito nel codice Lua.

Tagging C perché l'API Lua è C, codifica C++ perché sto utilizzando C++

risposta

20

C'è lua_sethook che può essere usato per dire all'interprete di chiamare un gancio dopo ogni 'contare' istruzioni eseguite. In questo modo è possibile monitorare lo script utente e terminare se si mangia la sua quota:

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

Questo può essere utilizzato anche da Lua:

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

Se si utilizzano le tecniche da http://lua-users.org/wiki/SandBoxes allora si può configurare un ambiente di esecuzione sicuro con sethook() e gli amici interamente da Lua e quindi passare alla modalità sandbox durante l'esecuzione dello script utente. Ho provato che qui, solo per voi per iniziare:

-- 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) 

Questo dovrebbe stampare i valori di fib() per 5 secondi e poi mostrare un errore.

+0

Ottima risposta, grazie! –