[Python-ideas] Any chance on (slowly) deprecating `eval` and `exec` as builtins?
Steven D'Aprano
steve at pearwood.info
Tue Nov 7 09:41:16 EST 2017
On Tue, Nov 07, 2017 at 03:35:58PM +0200, Serhiy Storchaka wrote:
> 07.11.17 12:29, אלעזר пише:
> >Also, it is unfortunate that `ast.literal_eval` is less accessible than
> >`builtins.eval`. Giving it an alias in builtins might make it easier for
> >programmers (and less scary - "ast" might sound like I need a PhD to use
> >it).
>
> ast.literal_eval is not so safe as you think. Malicious input can cause
> a stack overflow in your program. [1]
>
> [1] https://bugs.python.org/issue31113
I don't see anything about literal_eval in that bug report.
In any case, I think that securing literal_eval is much simpler than
securing eval:
try:
# a thousand character expression ought to be enough for
# any legitimate purpose...
value = literal_eval(tainted_string[:1000]) # untested
except MemoryError:
value = None
versus, well, there's no obvious or simple way to secure eval. You might
get something reasonable with:
if '_' in tainted_string:
raise ValueError("no underscores allowed!")
globalns = {'__builtins__': None} # I think?
eval(tainted_string[:1000], globalns, globalns)
but even that is probably vulnerable to a clever enough attacker.
I tried this on my computer with Python 3.5:
# Build a deeply nested dict {'x':{'x':{...}}} as a string
s = "{'x':0}"
for i in range(1665):
s = "{'x':%s}" % s
assert len(s) < 10000
d = ast.literal_eval(s)
and it failed with MemoryError rather than a segfault, so that's
something.
--
Steve
More information about the Python-ideas
mailing list