Skip to content
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

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

Merged
merged 4 commits into from
Oct 2, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 15 additions & 8 deletions Doc/library/ast.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1991,20 +1991,27 @@ and classes for traversing abstract syntax trees:

.. 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
following Python literal structures: strings, bytes, numbers, tuples, lists,
dicts, sets, booleans, ``None`` and ``Ellipsis``.

This can be used for safely evaluating strings containing Python values from
untrusted sources without the need to parse the values oneself. It is not
capable of evaluating arbitrarily complex expressions, for example involving
operators or indexing.
This can be used for evaluating strings containing Python values without the
need to parse the values oneself. It is not capable of evaluating
arbitrarily complex expressions, for example involving operators or
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. Calling it on untrusted input is thus
gpshead marked this conversation as resolved.
Show resolved Hide resolved
unwise.

.. warning::
It is possible to crash the Python interpreter with a
sufficiently large/complex string due to stack depth limitations
in Python's AST compiler.
It is possible to crash the Python interpreter with a complex string due
to stack depth limitations in Python's AST compiler.
gpshead marked this conversation as resolved.
Show resolved Hide resolved

It can raise :exc:`ValueError`, :exc:`TypeError`, :exc:`SyntaxError`,
:exc:`MemoryError` and :exc:`RecursionError` depending on the malformed
Expand Down
4 changes: 3 additions & 1 deletion Lib/ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,12 @@ def parse(source, filename='<unknown>', mode='exec', *,

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
Python literal structures: strings, bytes, numbers, tuples, lists, dicts,
sets, booleans, and None.

Caution: A complex expression can overflow the C stack and cause a crash.
"""
if isinstance(node_or_string, str):
node_or_string = parse(node_or_string.lstrip(" \t"), mode='eval')
Expand Down
Original file line number Diff line number Diff line change
@@ -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.