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 c21c51235a)

Co-authored-by: Curtis Bucher <cpbucher5@gmail.com>
This commit is contained in:
Miss Islington (bot) 2020-05-05 13:00:57 -07:00 committed by GitHub
parent a6a116c1b9
commit 2a3b876b02
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 15 additions and 4 deletions

View File

@ -59,11 +59,12 @@ def literal_eval(node_or_string):
node_or_string = parse(node_or_string, mode='eval')
if isinstance(node_or_string, Expression):
node_or_string = node_or_string.body
def _raise_malformed_node(node):
raise ValueError(f'malformed node or string: {node!r}')
def _convert_num(node):
if isinstance(node, Constant):
if type(node.value) in (int, float, complex):
return node.value
raise ValueError('malformed node or string: ' + repr(node))
if not isinstance(node, Constant) or type(node.value) not in (int, float, complex):
_raise_malformed_node(node)
return node.value
def _convert_signed_num(node):
if isinstance(node, UnaryOp) and isinstance(node.op, (UAdd, USub)):
operand = _convert_num(node.operand)
@ -82,6 +83,8 @@ def literal_eval(node_or_string):
elif isinstance(node, Set):
return set(map(_convert, node.elts))
elif isinstance(node, Dict):
if len(node.keys) != len(node.values):
_raise_malformed_node(node)
return dict(zip(map(_convert, node.keys),
map(_convert, node.values)))
elif isinstance(node, BinOp) and isinstance(node.op, (Add, Sub)):

View File

@ -869,6 +869,12 @@ class ASTHelpers_Test(unittest.TestCase):
self.assertRaises(ValueError, ast.literal_eval, '3+(0+6j)')
self.assertRaises(ValueError, ast.literal_eval, '-(3+6j)')
def test_literal_eval_malformed_dict_nodes(self):
malformed = ast.Dict(keys=[ast.Constant(1), ast.Constant(2)], values=[ast.Constant(3)])
self.assertRaises(ValueError, ast.literal_eval, malformed)
malformed = ast.Dict(keys=[ast.Constant(1)], values=[ast.Constant(2), ast.Constant(3)])
self.assertRaises(ValueError, ast.literal_eval, malformed)
def test_bad_integer(self):
# issue13436: Bad error message with invalid numeric values
body = [ast.ImportFrom(module='time',

View File

@ -0,0 +1,2 @@
Improve error reporting in :func:`ast.literal_eval` in the presence of malformed :class:`ast.Dict`
nodes instead of silently ignoring any non-conforming elements. Patch by Curtis Bucher.