On 2020-01-19, Jon Ribbens via Python-list <python-list@python.org> wrote: > On 2020-01-19, mus...@posteo.org <mus...@posteo.org> wrote: >> Is it actually possible to build a "sandbox" around eval [...] >> >> [...] >> >> It works, but is it safe? > > No, not even slightly. If you want to do this you need to write your > own interpreter that runs your own domain-specific language.
And for that, one is often pointed to the ast module as a starting point. Here's an excerpt from an expression evaluator I wrote as part of a two-pass symbolic assembler. [NB: it may have security issues too, but they should be easier to find/fix than anything involving eval()] # evaluate an arithmetic expression in the context of the symbol table. # only the operators in the table below are supported import ast,operator operators = \ { # unary ast.Invert: operator.invert, ast.USub: operator.neg, ast.UAdd: operator.pos, # binary ast.Add: operator.iadd, ast.Sub: operator.isub, ast.Mult: operator.imul, ast.Div: operator.idiv, ast.BitXor: operator.ixor, ast.BitAnd: operator.iand, ast.BitOr: operator.ior, ast.LShift: operator.lshift, ast.RShift: operator.rshift, ast.Mod: operator.mod, ast.Pow: operator.pow, } def _eval_expr(node): global symbolTable, PC if isinstance(node, ast.Name): if node.id == "PC": return PC if node.id not in symbolTable: raise Exception("name '%s' undefined" % node.id) return symbolTable[node.id] elif isinstance(node, ast.Num): return node.n elif isinstance(node, ast.Str): if len(node.s) != 1: raise Exception("invalid string constant '%s' must be single character" % node.s) return ord(node.s[0]) elif isinstance(node, ast.operator) or isinstance(node, ast.unaryop): if type(node) not in operators: errormsg(repr(dir(node))) raise Exception("illegal operator '%s" % node) return operators[type(node)] elif isinstance(node, ast.BinOp): return _eval_expr(node.op)(_eval_expr(node.left), _eval_expr(node.right)) elif isinstance(node, ast.UnaryOp): return _eval_expr(node.op)(_eval_expr(node.operand)) else: raise Exception("unsupported node type %s" % node) def eval_expr(expr): return _eval_expr(ast.parse(expr).body[0].value) -- https://mail.python.org/mailman/listinfo/python-list