Предел времени выполнения для сценария Lua, названного от API C

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

Существует ли способ поместить предел времени выполнения (скажите 10-20 секунд) для тех двух операторов C++, что загрузка и затем выполняет lua файл?

Так как файл Lua недоверяем, я не хочу, чтобы злонамеренный пользователь подвесил программу неограниченно долго с бесконечным циклом в коде Lua.

Метки C, потому что API Lua является C, отмечая C++, потому что я использую C++

9
задан Thomas Bonini 4 August 2010 в 15:10
поделиться

1 ответ

Есть lua_sethook, который можно использовать, чтобы указать интерпретатору вызывать ловушку после выполнения каждой инструкции count. Таким образом вы можете отслеживать пользовательский сценарий и прекращать его, если он исчерпает свою квоту:

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

Это также можно использовать из Lua:

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

Если вы используете методы из http://lua-users.org / wiki / SandBoxes , тогда вы можете настроить безопасную среду выполнения с помощью sethook () и друзей полностью из Lua, а затем переключиться в режим песочницы во время выполнения пользовательского скрипта. Я пробовал это здесь, просто для того, чтобы вы начали:

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

Это должно напечатать значения fib () в течение 5 секунд, а затем показать ошибку.

21
ответ дан 4 December 2019 в 10:02
поделиться