def compile_and_print(source, max_steps=500): from RestrictedPython import safe_builtins, safe_globals import dis code = compile(source=source, filename='<example>', mode='exec') print("==== dis ====") dis.dis(code) print("\n==== vm ====") l1 = dict() g1 = dict() vm = VirtualMachine(code, safe_builtins.copy(), l1, g1) steps = 0 while not vm.finish and steps < max_steps: op, data = vm.exec() steps += 1 print("{:5} {:20} {:3} stack={} block_stack={}".format( steps, opname[op], data, vm.stack, vm.block_stack)) print("\n==== vm result ====") print("finish", vm.finish) print("local", l1) print("global", g1) print("return", vm.return_value) l2 = dict() g2 = safe_globals.copy() r = eval(code, g2, l2) del g2['__builtins__'] print("\n==== eval result ====") print("local", l2) print("global", g2) print("return", r)
def test_iterate_over_dict_items_safe(c_exec): glb = safe_globals.copy() glb['_getiter_'] = default_guarded_getiter glb['_iter_unpack_sequence_'] = guarded_iter_unpack_sequence result = c_exec(ITERATE_OVER_DICT_ITEMS) assert result.code is not None assert result.errors == () exec(result.code, glb, None)
def test_iterate_over_dict_items_safe(): glb = safe_globals.copy() glb['_getiter_'] = default_guarded_getiter glb['_iter_unpack_sequence_'] = guarded_iter_unpack_sequence result = compile_restricted_exec(ITERATE_OVER_DICT_ITEMS) assert result.code is not None assert result.errors == () exec(result.code, glb, None)
def _get_migrate_function(code): byte_code = compile_restricted(code, filename="<inline code>", mode="exec") glob = safe_globals.copy() glob.update({ "sa": sqlalchemy, "sqlalchemy_jsonfield": sqlalchemy_jsonfield, "morpfw": morpfw, "sqlalchemy_utils": sqlalchemy_utils, }) loc = {} exec(byte_code, glob, loc) return loc["migrate"]
def compile_str(s, name="<unknown>"): """code and globals for *s*. *s* must be acceptable for ``compile_restricted`` (this is (especially) the case for an ``str`` or ``ast.Module``). *name* is a ``str`` used in error messages. """ code = compile_restricted(s, name, 'exec') gs = safe_globals.copy() gs["__debug__"] = True # assert active return code, gs
def run(code, output): '''Safely compile and run user uploaded code''' glb = safe_globals.copy() glb['_getiter_'] = default_guarded_getiter glb['_getitem_'] = default_guarded_getitem glb['_iter_unpack_sequence_'] = guarded_iter_unpack_sequence try: byte_code = compile_restricted_exec(code) # pylint: disable=W0122 exec(byte_code.code, glb, output) # pylint: disable=W0703 except Exception: output[ 'out'] = 'Something went wrong. Please inspect the code you entered.'
def compile_python_code(request): """ Function for compiling Python code """ # Set global variables to allow safe for loop iteration glb = safe_globals.copy() glb['_getiter_'] = default_guarded_getiter glb['_iter_unpack_sequence_'] = guarded_iter_unpack_sequence # Get the submitted untrusted code untrustedCode = request.GET.get('untrustedCode') untrustedCode = untrustedCode.replace('\t', ' ') # Get the function name from untrusted code using regex lessonTitle = re.search('def (.*)():', untrustedCode) # Isolate the function name lessonTitle = lessonTitle.group(1).replace('(', '').replace(')', '') try: # loc used to store functions loc = {} # byteCode stores the restricted compilation configurations byteCode = compile_restricted(untrustedCode, '<inline>', 'exec') # Compile the untrusted code using restricted compilation configurations and store the function in loc exec(byteCode, glb, loc) # Retrieve the return from the user submitted function result = loc[lessonTitle]() data = {'output': result} # If a general SyntaxError is thrown except SyntaxError as e: data = { 'output': "Error with the input code. Take another look at your code." + str(e) } # If a general Execption is thrown except Exception as e: # Check the user is not trying to use in-place operations if ("+=" in untrustedCode): data = { 'output': "Error with the input code. In-place operations ('+=') are not currently supported." } else: data = { 'output': "Error with the input code. Take another look at your code. \n" + str(e) } return JsonResponse(data)
def run_sandbox(self, script_src, function_name, params): if _valid_name_re.match(function_name) is None: raise RR.InvalidArgumentException("Function name is invalid") if params is not None: for k in params: if _valid_name_re.match(params) is None: raise RR.InvalidArgumentException("Param name is invalid") loc = {} byte_code = compile_restricted(script_src, '<robotraconteur_sandbox>', 'exec') sandbox_globals = safe_globals.copy() print_collector = PrintCollector() sandbox_globals["_print_"] = print_collector exec(byte_code, sandbox_globals, loc) if params is None: res = loc[function_name]() else: res = loc[function_name](*params) print(print_collector.printed)
if level != import_default_level: raise RestrictedImportError( "Using import with a level specification isn't supported: %s" % name) return self.app.get_restricted_module(name) class Print(PrintCollector): def _call_print(self, *objects, **kwargs): log.info(" ".join(objects)) safe_builtins = orig_safe_builtins.copy() safe_globals = orig_safe_globals.copy() safe_globals["dir"] = dir safe_globals["_getiter_"] = default_guarded_getiter safe_globals["_getitem_"] = default_guarded_getitem safe_globals["_iter_unpack_sequence_"] = guarded_iter_unpack_sequence safe_globals["_write_"] = full_write_guard safe_globals["_inplacevar_"] = default_inplacevar safe_globals["__builtins__"] = safe_builtins safe_globals["getattr"] = safer_getattr safe_globals["enumerate"] = enumerate safe_globals["log"] = log def get_restricted_function(app, bytecode, name, local_vars=None): local_vars = local_vars or {} glob = safe_globals.copy()