From: Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> Date: Tue, 5 May 2020 20:00:57 +0000 (-0700) Subject: bpo-40355: Improve error messages in ast.literal_eval with malformed Dict nodes ... X-Git-Tag: v3.8.3~6 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2a3b876b0286b22a9058510d9e51dc4d60eeb89a;p=thirdparty%2FPython%2Fcpython.git bpo-40355: Improve error messages in ast.literal_eval with malformed Dict nodes (GH-19868) Co-authored-by: Pablo Galindo (cherry picked from commit c21c51235aa8061da6b0593d6f857f42fd92fd8b) Co-authored-by: Curtis Bucher --- diff --git a/Lib/ast.py b/Lib/ast.py index 157a8332ebcc..0c88bcf4c821 100644 --- a/Lib/ast.py +++ b/Lib/ast.py @@ -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)): diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py index 3e8a39dc4104..8887558ce4c3 100644 --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -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', diff --git a/Misc/NEWS.d/next/Library/2020-05-02-14-24-48.bpo-40355.xTujaB.rst b/Misc/NEWS.d/next/Library/2020-05-02-14-24-48.bpo-40355.xTujaB.rst new file mode 100644 index 000000000000..81f9e937a2bf --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-05-02-14-24-48.bpo-40355.xTujaB.rst @@ -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.