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 __build_builtins(self): builtins = safe_builtins.copy() builtins['_unpack_sequence_'] = guarded_unpack_sequence builtins['_iter_unpack_sequence_'] = guarded_iter_unpack_sequence builtins['_getiter_'] = default_guarded_getiter builtins['_getitem_'] = safer_getitem return builtins
def source_execute(source, add_buildins=None, max_steps=5000): """compile source, execute by VM, eval and compare result""" # compile code = compile(source=source, filename='<example>', mode='exec') # vm b = safe_builtins.copy() if add_buildins: b.update(add_buildins) l1 = dict() g1 = dict() vm = VirtualMachine(code, b, l1, g1) steps = 0 while not vm.finish and steps < max_steps: vm.exec() steps += 1 # eval l2 = dict() g2 = {'__builtins__': b} r = eval(code, g2, l2) del g2['__builtins__'] # check assert l1 == l2, "{} X {}".format(l1, l2) assert g1 == g2, "{} X {}".format(g1, g2) assert vm.return_value == r, "{} X {}".format(vm.return_value, r)
def execute(hass, filename, source, data=None): """Execute Python source.""" compiled = compile_restricted_exec(source, filename=filename) if compiled.errors: _LOGGER.error("Error loading script %s: %s", filename, ", ".join(compiled.errors)) return if compiled.warnings: _LOGGER.warning("Warning loading script %s: %s", filename, ", ".join(compiled.warnings)) def protected_getattr(obj, name, default=None): """Restricted method to get attributes.""" if name.startswith("async_"): raise ScriptError("Not allowed to access async methods") if (obj is hass and name not in ALLOWED_HASS or obj is hass.bus and name not in ALLOWED_EVENTBUS or obj is hass.states and name not in ALLOWED_STATEMACHINE or obj is hass.services and name not in ALLOWED_SERVICEREGISTRY or obj is dt_util and name not in ALLOWED_DT_UTIL or obj is datetime and name not in ALLOWED_DATETIME or isinstance(obj, TimeWrapper) and name not in ALLOWED_TIME): raise ScriptError( f"Not allowed to access {obj.__class__.__name__}.{name}") return getattr(obj, name, default) extra_builtins = { "datetime": datetime, "sorted": sorted, "time": TimeWrapper(), "dt_util": dt_util, "min": min, "max": max, "sum": sum, "any": any, "all": all, } builtins = safe_builtins.copy() builtins.update(utility_builtins) builtins.update(limited_builtins) builtins.update(extra_builtins) logger = logging.getLogger(f"{__name__}.{filename}") restricted_globals = { "__builtins__": builtins, "_print_": StubPrinter, "_getattr_": protected_getattr, "_write_": full_write_guard, "_getiter_": iter, "_getitem_": default_guarded_getitem, "_iter_unpack_sequence_": guarded_iter_unpack_sequence, "_unpack_sequence_": guarded_unpack_sequence, "hass": hass, "data": data or {}, "logger": logger, } try: _LOGGER.info("Executing %s: %s", filename, data) # pylint: disable=exec-used exec(compiled.code, restricted_globals) except ScriptError as err: logger.error("Error executing script: %s", err) except Exception as err: # pylint: disable=broad-except logger.exception("Error executing script: %s", err)
from aim.storage.proxy import AimObjectProxy if TYPE_CHECKING: from aim.storage.context import Context extra_builtins = { 'datetime': datetime, 'sorted': sorted, 'min': min, 'max': max, 'sum': sum, 'any': any, 'all': all, } builtins = safe_builtins.copy() builtins.update(utility_builtins) builtins.update(limited_builtins) builtins.update(extra_builtins) def safer_getattr(object, name, default=None, getattr=getattr): '''Getattr implementation which prevents using format on string objects. format() is considered harmful: http://lucumr.pocoo.org/2016/12/29/careful-with-str-format/ ''' if name == 'format' and isinstance(object, str): raise NotImplementedError('Using format() on a %s is not safe.' % object.__class__.__name__)
locals = {} 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 {}