stringExp = \"2^4\"
intVal = int(stringExp) # Expected value: 16
This returns the following error:
Traceback (most recent call
Okay, so the problem with eval is that it can escape its sandbox too easily, even if you get rid of __builtins__
. All the methods for escaping the sandbox come down to using getattr
or object.__getattribute__
(via the .
operator) to obtain a reference to some dangerous object via some allowed object (''.__class__.__bases__[0].__subclasses__
or similar). getattr
is eliminated by setting __builtins__
to None
. object.__getattribute__
is the difficult one, since it cannot simply be removed, both because object
is immutable and because removing it would break everything. However, __getattribute__
is only accessible via the .
operator, so purging that from your input is sufficient to ensure eval cannot escape its sandbox.
In processing formulas, the only valid use of a decimal is when it is preceded or followed by [0-9]
, so we just remove all other instances of .
.
import re
inp = re.sub(r"\.(?![0-9])","", inp)
val = eval(inp, {'__builtins__':None})
Note that while python normally treats 1 + 1.
as 1 + 1.0
, this will remove the trailing .
and leave you with 1 + 1
. You could add )
,, and
EOF
to the list of things allowed to follow .
, but why bother?