]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-40355: Improve error messages in ast.literal_eval with malformed Dict nodes ...
authorCurtis Bucher <cpbucher5@gmail.com>
Tue, 5 May 2020 19:40:56 +0000 (12:40 -0700)
committerGitHub <noreply@github.com>
Tue, 5 May 2020 19:40:56 +0000 (20:40 +0100)
Co-authored-by: Pablo Galindo <Pablogsal@gmail.com>
Lib/ast.py
Lib/test/test_ast.py
Misc/NEWS.d/next/Library/2020-05-02-14-24-48.bpo-40355.xTujaB.rst [new file with mode: 0644]

index 5c68c4a66e1dd06d1aa6fdaba9d084bc61a76a7a..7a43581c0e6ce69cfde90cd6825fc43af058c045 100644 (file)
@@ -62,11 +62,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)
@@ -88,6 +89,8 @@ def literal_eval(node_or_string):
               node.func.id == 'set' and node.args == node.keywords == []):
             return set()
         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)):
index 9063b3d2d7b744b3c7789665883700790b20d5d8..a8a13fdcd7426e8218e4bebf594f0c5882752430 100644 (file)
@@ -965,6 +965,12 @@ Module(
         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 (file)
index 0000000..81f9e93
--- /dev/null
@@ -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.