add jailed exec which raises timeout after a number of instructions have been interpreted

This commit is contained in:
Benoit Favre 2025-02-28 13:31:10 +01:00
parent e1373766b1
commit efacdad731
6 changed files with 40 additions and 3 deletions

View File

@ -26,6 +26,9 @@ typedef struct VM {
py_TValue builtins; // builtins module
py_TValue main; // __main__ module
py_i64 max_steps;
py_i64 used_steps;
py_Callbacks callbacks;
py_TValue ascii_literals[128+1];

View File

@ -735,6 +735,7 @@ enum py_PredefinedTypes {
tp_ImportError,
tp_AssertionError,
tp_KeyError,
tp_Timeout,
/* linalg */
tp_vec2,
tp_vec3,

View File

@ -109,6 +109,15 @@ FrameResult VM__run_top_frame(VM* self) {
goto __ERROR;
}
if (self->max_steps > 0) {
if (self->used_steps >= self->max_steps) {
py_exception(tp_Timeout, "execution timed out");
goto __ERROR;
}
self->used_steps++;
}
switch((Opcode)byte.op) {
case OP_NO_OP: DISPATCH();
/*****************************************/

View File

@ -176,6 +176,7 @@ void VM__ctor(VM* self) {
INJECT_BUILTIN_EXC(ImportError, tp_Exception);
INJECT_BUILTIN_EXC(AssertionError, tp_Exception);
INJECT_BUILTIN_EXC(KeyError, tp_Exception);
INJECT_BUILTIN_EXC(Timeout, tp_Exception);
#undef INJECT_BUILTIN_EXC
#undef validate

View File

@ -612,6 +612,20 @@ static bool builtins_exec(int argc, py_Ref argv) {
return ok;
}
static bool builtins_exec_jailed(int argc, py_Ref argv) {
VM* vm = pk_current_vm;
PY_CHECK_ARG_TYPE(0, tp_int);
int was_jailed = (vm->max_steps > 0);
if (!was_jailed) {
vm->max_steps = py_toint(py_arg(0));
vm->used_steps = 0;
}
bool ok = _builtins_execdyn("exec", argc - 1, argv + 1, EXEC_MODE);
if (!was_jailed) vm->max_steps = 0;
py_newnone(py_retval());
return ok;
}
static bool builtins_eval(int argc, py_Ref argv) {
return _builtins_execdyn("eval", argc, argv, EVAL_MODE);
}
@ -755,6 +769,7 @@ py_TValue pk_builtins__register() {
py_bindfunc(builtins, "globals", builtins_globals);
py_bindfunc(builtins, "locals", builtins_locals);
py_bindfunc(builtins, "exec", builtins_exec);
py_bindfunc(builtins, "exec_jailed", builtins_exec_jailed);
py_bindfunc(builtins, "eval", builtins_eval);
py_bindfunc(builtins, "compile", builtins_compile);

View File

@ -74,3 +74,11 @@ exec(code, {'x': 42, 'res': res})
assert res == [42, 42]
assert x == 33
code = '''
while True:
pass
'''
try:
exec_jailed(100000, code)
except Timeout:
pass