-
-
Notifications
You must be signed in to change notification settings - Fork 32k
Ideas for making ast.literal_eval() usable #83340
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
A primary goal for ast.literal_eval() is to "Safely evaluate an expression node or a string". In the context of a real application, we need to do several things to make it possible to fulfill its design goal:
expr = input('Enter a dataset in Python format: ')
if len(expr) > 300:
error(f'Maximum supported size is 300, not {len(expr)}')
try:
data = literal_eval(expr)
except (TypeError, MemoryError, SyntaxError, ValueError):
error('Input cannot be evaluated') |
Maybe we should wrap all of these into something like LiteralEvalError to easily catch all of them, LiteralEvalError can be subclass of that four but I guess in some cases this change might break code.
>>> s = "(" * 101 + ")" * 101
>>> len(s)
202
>>> ast.literal_eval(s)
s_push: parser stack overflow
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python3.9/ast.py", line 61, in literal_eval
node_or_string = parse(node_or_string, mode='eval')
File "/usr/local/lib/python3.9/ast.py", line 49, in parse
return compile(source, filename, mode, flags,
MemoryError
Can you explain it a bit more detailed, how does this standalone expression compiler should work? |
Also, an addition to these errors is RecursionError
>>> t = ast.Tuple(elts=[], ctx=ast.Load())
>>> t.elts.append(t)
>>> ast.literal_eval(t)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python3.9/ast.py", line 101, in literal_eval
return _convert(node_or_string)
File "/usr/local/lib/python3.9/ast.py", line 81, in _convert
return tuple(map(_convert, node.elts))
File "/usr/local/lib/python3.9/ast.py", line 81, in _convert
return tuple(map(_convert, node.elts))
File "/usr/local/lib/python3.9/ast.py", line 81, in _convert
return tuple(map(_convert, node.elts))
[Previous line repeated 496 more times]
RecursionError: maximum recursion depth exceeded |
It can also crash. ast.literal_eval('+0'*10**6) The cause is that all AST handling C code (in particularly converting the AST from C to Python) is recursive, and therefore can overflow the C stack. Some recursive code has arbitrary limits which cause raising exceptions like MemoryError in the initial example, but not all code has such checks. |
Aim for something like JSON parser but for the supported Python constant expressions and with the existing tokenize module to feed a hand-rolled on-recursive parser |
related: the old #55552 issue about producing better errors from the parser. not crashing due to a C stack overflow counts as better. ;) |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: