[Python-checkins] [3.11] GH-105588: Add missing error checks to some obj2ast_* converters (GH-105839)
brandtbucher
webhook-mailer at python.org
Thu Jun 15 19:13:55 EDT 2023
https://github.com/python/cpython/commit/c0c41868587cea93f69e02311406555a99902183
commit: c0c41868587cea93f69e02311406555a99902183
branch: 3.11
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: brandtbucher <brandtbucher at gmail.com>
date: 2023-06-15T23:13:51Z
summary:
[3.11] GH-105588: Add missing error checks to some obj2ast_* converters (GH-105839)
GH-105588: Add missing error checks to some obj2ast_* converters (GH-105589)
(cherry picked from commit a4056c8f9c2d9970d39e3cb6bffb255cd4b8a42c)
Co-authored-by: Brandt Bucher <brandtbucher at microsoft.com>
files:
A Misc/NEWS.d/next/Core and Builtins/2023-06-09-11-19-51.gh-issue-105588.Y5ovpY.rst
M Lib/test/test_ast.py
M Parser/asdl_c.py
M Python/Python-ast.c
diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py
index f7221955e3e04..33c13ee29a268 100644
--- a/Lib/test/test_ast.py
+++ b/Lib/test/test_ast.py
@@ -3,6 +3,7 @@
import dis
import enum
import os
+import re
import sys
import types
import unittest
@@ -862,6 +863,32 @@ def test_null_bytes(self):
msg="source code string cannot contain null bytes"):
ast.parse("a\0b")
+ def assert_none_check(self, node: type[ast.AST], attr: str, source: str) -> None:
+ with self.subTest(f"{node.__name__}.{attr}"):
+ tree = ast.parse(source)
+ found = 0
+ for child in ast.walk(tree):
+ if isinstance(child, node):
+ setattr(child, attr, None)
+ found += 1
+ self.assertEqual(found, 1)
+ e = re.escape(f"field '{attr}' is required for {node.__name__}")
+ with self.assertRaisesRegex(ValueError, f"^{e}$"):
+ compile(tree, "<test>", "exec")
+
+ def test_none_checks(self) -> None:
+ tests = [
+ (ast.alias, "name", "import spam as SPAM"),
+ (ast.arg, "arg", "def spam(SPAM): spam"),
+ (ast.comprehension, "target", "[spam for SPAM in spam]"),
+ (ast.comprehension, "iter", "[spam for spam in SPAM]"),
+ (ast.keyword, "value", "spam(**SPAM)"),
+ (ast.match_case, "pattern", "match spam:\n case SPAM: spam"),
+ (ast.withitem, "context_expr", "with SPAM: spam"),
+ ]
+ for node, attr, source in tests:
+ self.assert_none_check(node, attr, source)
+
class ASTHelpers_Test(unittest.TestCase):
maxDiff = None
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-09-11-19-51.gh-issue-105588.Y5ovpY.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-09-11-19-51.gh-issue-105588.Y5ovpY.rst
new file mode 100644
index 0000000000000..3981dad7a49df
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-06-09-11-19-51.gh-issue-105588.Y5ovpY.rst
@@ -0,0 +1,2 @@
+Fix an issue that could result in crashes when compiling malformed
+:mod:`ast` nodes.
diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py
index ec8b53350b3ef..e19038e9d3fca 100755
--- a/Parser/asdl_c.py
+++ b/Parser/asdl_c.py
@@ -602,6 +602,7 @@ def visitProduct(self, prod, name):
args = [f.name for f in prod.fields]
args.extend([a.name for a in prod.attributes])
self.emit("*out = %s(%s);" % (ast_func_name(name), self.buildArgs(args)), 1)
+ self.emit("if (*out == NULL) goto failed;", 1)
self.emit("return 0;", 1)
self.emit("failed:", 0)
self.emit("Py_XDECREF(tmp);", 1)
diff --git a/Python/Python-ast.c b/Python/Python-ast.c
index f485af675ccff..9139f6e54f36d 100644
--- a/Python/Python-ast.c
+++ b/Python/Python-ast.c
@@ -10309,6 +10309,7 @@ obj2ast_comprehension(struct ast_state *state, PyObject* obj, comprehension_ty*
Py_CLEAR(tmp);
}
*out = _PyAST_comprehension(target, iter, ifs, is_async, arena);
+ if (*out == NULL) goto failed;
return 0;
failed:
Py_XDECREF(tmp);
@@ -10727,6 +10728,7 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out,
}
*out = _PyAST_arguments(posonlyargs, args, vararg, kwonlyargs, kw_defaults,
kwarg, defaults, arena);
+ if (*out == NULL) goto failed;
return 0;
failed:
Py_XDECREF(tmp);
@@ -10866,6 +10868,7 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena)
}
*out = _PyAST_arg(arg, annotation, type_comment, lineno, col_offset,
end_lineno, end_col_offset, arena);
+ if (*out == NULL) goto failed;
return 0;
failed:
Py_XDECREF(tmp);
@@ -10988,6 +10991,7 @@ obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out,
}
*out = _PyAST_keyword(arg, value, lineno, col_offset, end_lineno,
end_col_offset, arena);
+ if (*out == NULL) goto failed;
return 0;
failed:
Py_XDECREF(tmp);
@@ -11110,6 +11114,7 @@ obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena*
}
*out = _PyAST_alias(name, asname, lineno, col_offset, end_lineno,
end_col_offset, arena);
+ if (*out == NULL) goto failed;
return 0;
failed:
Py_XDECREF(tmp);
@@ -11159,6 +11164,7 @@ obj2ast_withitem(struct ast_state *state, PyObject* obj, withitem_ty* out,
Py_CLEAR(tmp);
}
*out = _PyAST_withitem(context_expr, optional_vars, arena);
+ if (*out == NULL) goto failed;
return 0;
failed:
Py_XDECREF(tmp);
@@ -11246,6 +11252,7 @@ obj2ast_match_case(struct ast_state *state, PyObject* obj, match_case_ty* out,
Py_CLEAR(tmp);
}
*out = _PyAST_match_case(pattern, guard, body, arena);
+ if (*out == NULL) goto failed;
return 0;
failed:
Py_XDECREF(tmp);
More information about the Python-checkins
mailing list