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]
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