Skip to content

Commit c21c512

Browse files
bpo-40355: Improve error messages in ast.literal_eval with malformed Dict nodes (GH-19868)
Co-authored-by: Pablo Galindo <[email protected]>
1 parent fb2c7c4 commit c21c512

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
@@ -62,11 +62,12 @@ def literal_eval(node_or_string):
6262
node_or_string = parse(node_or_string, mode='eval')
6363
if isinstance(node_or_string, Expression):
6464
node_or_string = node_or_string.body
65+
def _raise_malformed_node(node):
66+
raise ValueError(f'malformed node or string: {node!r}')
6567
def _convert_num(node):
66-
if isinstance(node, Constant):
67-
if type(node.value) in (int, float, complex):
68-
return node.value
69-
raise ValueError('malformed node or string: ' + repr(node))
68+
if not isinstance(node, Constant) or type(node.value) not in (int, float, complex):
69+
_raise_malformed_node(node)
70+
return node.value
7071
def _convert_signed_num(node):
7172
if isinstance(node, UnaryOp) and isinstance(node.op, (UAdd, USub)):
7273
operand = _convert_num(node.operand)
@@ -88,6 +89,8 @@ def _convert(node):
8889
node.func.id == 'set' and node.args == node.keywords == []):
8990
return set()
9091
elif isinstance(node, Dict):
92+
if len(node.keys) != len(node.values):
93+
_raise_malformed_node(node)
9194
return dict(zip(map(_convert, node.keys),
9295
map(_convert, node.values)))
9396
elif isinstance(node, BinOp) and isinstance(node.op, (Add, Sub)):

Lib/test/test_ast.py

+6
Original file line numberDiff line numberDiff line change
@@ -965,6 +965,12 @@ def test_literal_eval_complex(self):
965965
self.assertRaises(ValueError, ast.literal_eval, '3+(0+6j)')
966966
self.assertRaises(ValueError, ast.literal_eval, '-(3+6j)')
967967

968+
def test_literal_eval_malformed_dict_nodes(self):
969+
malformed = ast.Dict(keys=[ast.Constant(1), ast.Constant(2)], values=[ast.Constant(3)])
970+
self.assertRaises(ValueError, ast.literal_eval, malformed)
971+
malformed = ast.Dict(keys=[ast.Constant(1)], values=[ast.Constant(2), ast.Constant(3)])
972+
self.assertRaises(ValueError, ast.literal_eval, malformed)
973+
968974
def test_bad_integer(self):
969975
# issue13436: Bad error message with invalid numeric values
970976
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)