Skip to content

Commit 2a3b876

Browse files
bpo-40355: Improve error messages in ast.literal_eval with malformed Dict nodes (GH-19868)
Co-authored-by: Pablo Galindo <Pablogsal@gmail.com> (cherry picked from commit c21c512) Co-authored-by: Curtis Bucher <cpbucher5@gmail.com>
1 parent a6a116c commit 2a3b876

File tree

3 files changed

+15
-4
lines changed

3 files changed

+15
-4
lines changed

Lib/ast.py

+7-4
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,12 @@ def literal_eval(node_or_string):
5959
node_or_string = parse(node_or_string, mode='eval')
6060
if isinstance(node_or_string, Expression):
6161
node_or_string = node_or_string.body
62+
def _raise_malformed_node(node):
63+
raise ValueError(f'malformed node or string: {node!r}')
6264
def _convert_num(node):
63-
if isinstance(node, Constant):
64-
if type(node.value) in (int, float, complex):
65-
return node.value
66-
raise ValueError('malformed node or string: ' + repr(node))
65+
if not isinstance(node, Constant) or type(node.value) not in (int, float, complex):
66+
_raise_malformed_node(node)
67+
return node.value
6768
def _convert_signed_num(node):
6869
if isinstance(node, UnaryOp) and isinstance(node.op, (UAdd, USub)):
6970
operand = _convert_num(node.operand)
@@ -82,6 +83,8 @@ def _convert(node):
8283
elif isinstance(node, Set):
8384
return set(map(_convert, node.elts))
8485
elif isinstance(node, Dict):
86+
if len(node.keys) != len(node.values):
87+
_raise_malformed_node(node)
8588
return dict(zip(map(_convert, node.keys),
8689
map(_convert, node.values)))
8790
elif isinstance(node, BinOp) and isinstance(node.op, (Add, Sub)):

Lib/test/test_ast.py

+6
Original file line numberDiff line numberDiff line change
@@ -869,6 +869,12 @@ def test_literal_eval_complex(self):
869869
self.assertRaises(ValueError, ast.literal_eval, '3+(0+6j)')
870870
self.assertRaises(ValueError, ast.literal_eval, '-(3+6j)')
871871

872+
def test_literal_eval_malformed_dict_nodes(self):
873+
malformed = ast.Dict(keys=[ast.Constant(1), ast.Constant(2)], values=[ast.Constant(3)])
874+
self.assertRaises(ValueError, ast.literal_eval, malformed)
875+
malformed = ast.Dict(keys=[ast.Constant(1)], values=[ast.Constant(2), ast.Constant(3)])
876+
self.assertRaises(ValueError, ast.literal_eval, malformed)
877+
872878
def test_bad_integer(self):
873879
# issue13436: Bad error message with invalid numeric values
874880
body = [ast.ImportFrom(module='time',
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Improve error reporting in :func:`ast.literal_eval` in the presence of malformed :class:`ast.Dict`
2+
nodes instead of silently ignoring any non-conforming elements. Patch by Curtis Bucher.

0 commit comments

Comments
 (0)