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

Y at-il un moyen de mettre une limite de temps d'exécution (disons 10-20 secondes) pour ces deux déclarations C++, cette charge, puis d'exécuter un fichier lua? Comme le fichier Lua n'est pas approuvé, je ne veux pas qu'un utilisateur malveillant bloque le programme indéfiniment avec une boucle infinie dans le code Lua.délai d'exécution d'un script Lua appelé de l'API C

Tagging C car l'API Lua est C, marquage C++ parce que je suis en C++

Répondre

20

Il y a lua_sethook qui peut être utilisé pour indiquer l'interprète d'appeler un crochet après chaque « compte » instructions exécutées. De cette façon, vous pouvez suivre le script d'utilisateur et y mettre fin si elle mange son quota:

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

Cela peut aussi être utilisé à partir Lua:

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

Si vous utilisez les techniques de http://lua-users.org/wiki/SandBoxes alors vous pouvez configurer un environnement d'exécution sécurisé avec sethook() et des amis entièrement à partir de Lua, puis passer en mode sandbox lors de l'exécution du script utilisateur. J'ai essayé ici, juste pour vous pour commencer:

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

Cela devrait imprimer des valeurs de fib() pendant 5 secondes, puis montrer une erreur.

+0

Bonne réponse, merci! –