From b77463f5b274bdee3fd889ca748cafac1330ba70 Mon Sep 17 00:00:00 2001 From: Benoit Favre Date: Fri, 28 Feb 2025 15:07:20 +0100 Subject: [PATCH] jailed exec: add support for __builtins__ global --- src/interpreter/ceval.c | 56 +++++++++++++++++++++++++++++++++++++++++ tests/66_eval.py | 18 +++++++++++++ 2 files changed, 74 insertions(+) diff --git a/src/interpreter/ceval.c b/src/interpreter/ceval.c index dec2f112..b7d9e619 100644 --- a/src/interpreter/ceval.c +++ b/src/interpreter/ceval.c @@ -253,6 +253,20 @@ FrameResult VM__run_top_frame(VM* self) { } if(res == -1) goto __ERROR; // builtins + if (self->max_steps > 0) { + int res = Frame__getglobal(frame, py_name("__builtins__")); + if (res == 1) { + py_Ref builtins = &self->last_retval; + if(!py_istype(builtins, tp_dict)) { return TypeError("__builtins__ must be a dict object"); } + res = py_dict_getitem(builtins, py_name2ref(name)); + if (res == 1) { + PUSH(&self->last_retval); + DISPATCH(); + } + } + NameError(name); + goto __ERROR; + } py_Ref tmp = py_getdict(&self->builtins, name); if(tmp != NULL) { PUSH(tmp); @@ -275,6 +289,20 @@ FrameResult VM__run_top_frame(VM* self) { } if(res == -1) goto __ERROR; + if (self->max_steps > 0) { + int res = Frame__getglobal(frame, py_name("__builtins__")); + if (res == 1) { + py_Ref builtins = &self->last_retval; + if(!py_istype(builtins, tp_dict)) { return TypeError("__builtins__ must be a dict object"); } + res = py_dict_getitem(builtins, py_name2ref(name)); + if (res == 1) { + PUSH(&self->last_retval); + DISPATCH(); + } + } + NameError(name); + goto __ERROR; + } tmp = py_getdict(&self->builtins, name); if(tmp != NULL) { PUSH(tmp); @@ -291,6 +319,20 @@ FrameResult VM__run_top_frame(VM* self) { DISPATCH(); } if(res == -1) goto __ERROR; + if (self->max_steps > 0) { + int res = Frame__getglobal(frame, py_name("__builtins__")); + if (res == 1) { + py_Ref builtins = &self->last_retval; + if(!py_istype(builtins, tp_dict)) { return TypeError("__builtins__ must be a dict object"); } + res = py_dict_getitem(builtins, py_name2ref(name)); + if (res == 1) { + PUSH(&self->last_retval); + DISPATCH(); + } + } + NameError(name); + goto __ERROR; + } py_Ref tmp = py_getdict(&self->builtins, name); if(tmp != NULL) { PUSH(tmp); @@ -322,6 +364,20 @@ FrameResult VM__run_top_frame(VM* self) { DISPATCH(); } if(res == -1) goto __ERROR; + if (self->max_steps > 0) { + int res = Frame__getglobal(frame, py_name("__builtins__")); + if (res == 1) { + py_Ref builtins = &self->last_retval; + if(!py_istype(builtins, tp_dict)) { return TypeError("__builtins__ must be a dict object"); } + res = py_dict_getitem(builtins, py_name2ref(name)); + if (res == 1) { + PUSH(&self->last_retval); + DISPATCH(); + } + } + NameError(name); + goto __ERROR; + } tmp = py_getdict(&self->builtins, name); if(tmp) { PUSH(tmp); diff --git a/tests/66_eval.py b/tests/66_eval.py index dd41905f..fcf28255 100644 --- a/tests/66_eval.py +++ b/tests/66_eval.py @@ -82,3 +82,21 @@ try: exec_jailed(100000, code) except Timeout: pass + +code = ''' +def f(): + z(1) +f() +z(2) +''' +res = [] +exec_jailed(100000, code, {'__builtins__': {'z': lambda x: res.append(x)}}) +assert res == [1, 2] + +code = ''' +print(1) +''' +try: + exec_jailed(100000, code, {'__builtins__': {}}) +except NameError: + pass