gh-95588: Drop the safety claim from ast.literal_eval docs. (#95919)

It was never really safe and this claim conflicts directly with the big warning in the docs about it being able to crash the interpreter.
This commit is contained in:
Gregory P. Smith 2022-10-01 17:55:40 -07:00 committed by GitHub
parent bd7d0e875e
commit 8baef8ae36
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 25 additions and 9 deletions

View file

@ -1991,20 +1991,28 @@ and classes for traversing abstract syntax trees:
.. function:: literal_eval(node_or_string) .. function:: literal_eval(node_or_string)
Safely evaluate an expression node or a string containing a Python literal or Evaluate an expression node or a string containing only a Python literal or
container display. The string or node provided may only consist of the container display. The string or node provided may only consist of the
following Python literal structures: strings, bytes, numbers, tuples, lists, following Python literal structures: strings, bytes, numbers, tuples, lists,
dicts, sets, booleans, ``None`` and ``Ellipsis``. dicts, sets, booleans, ``None`` and ``Ellipsis``.
This can be used for safely evaluating strings containing Python values from This can be used for evaluating strings containing Python values without the
untrusted sources without the need to parse the values oneself. It is not need to parse the values oneself. It is not capable of evaluating
capable of evaluating arbitrarily complex expressions, for example involving arbitrarily complex expressions, for example involving operators or
operators or indexing. indexing.
This function had been documented as "safe" in the past without defining
what that meant. That was misleading. This is specifically designed not to
execute Python code, unlike the more general :func:`eval`. There is no
namespace, no name lookups, or ability to call out. But it is not free from
attack: A relatively small input can lead to memory exhaustion or to C stack
exhaustion, crashing the process. There is also the possibility for
excessive CPU consumption denial of service on some inputs. Calling it on
untrusted data is thus not recommended.
.. warning:: .. warning::
It is possible to crash the Python interpreter with a It is possible to crash the Python interpreter due to stack depth
sufficiently large/complex string due to stack depth limitations limitations in Python's AST compiler.
in Python's AST compiler.
It can raise :exc:`ValueError`, :exc:`TypeError`, :exc:`SyntaxError`, It can raise :exc:`ValueError`, :exc:`TypeError`, :exc:`SyntaxError`,
:exc:`MemoryError` and :exc:`RecursionError` depending on the malformed :exc:`MemoryError` and :exc:`RecursionError` depending on the malformed

View file

@ -54,10 +54,12 @@ def parse(source, filename='<unknown>', mode='exec', *,
def literal_eval(node_or_string): def literal_eval(node_or_string):
""" """
Safely evaluate an expression node or a string containing a Python Evaluate an expression node or a string containing only a Python
expression. The string or node provided may only consist of the following expression. The string or node provided may only consist of the following
Python literal structures: strings, bytes, numbers, tuples, lists, dicts, Python literal structures: strings, bytes, numbers, tuples, lists, dicts,
sets, booleans, and None. sets, booleans, and None.
Caution: A complex expression can overflow the C stack and cause a crash.
""" """
if isinstance(node_or_string, str): if isinstance(node_or_string, str):
node_or_string = parse(node_or_string.lstrip(" \t"), mode='eval') node_or_string = parse(node_or_string.lstrip(" \t"), mode='eval')

View file

@ -0,0 +1,6 @@
Clarified the conflicting advice given in the :mod:`ast` documentation about
:func:`ast.literal_eval` being "safe" for use on untrusted input while at
the same time warning that it can crash the process. The latter statement is
true and is deemed unfixable without a large amount of work unsuitable for a
bugfix. So we keep the warning and no longer claim that ``literal_eval`` is
safe.