Skip to content

Commit 0c6d26e

Browse files
StanFromIrelandmiss-islington
authored andcommitted
gh-156689: Fix out-of-bounds read in PyAst_CheckMode() for mode='func_type' (GH-156697)
(cherry picked from commit d7f9c64) Co-authored-by: Stan Ulbrych <stan@python.org>
1 parent 686b543 commit 0c6d26e

5 files changed

Lines changed: 26 additions & 9 deletions

File tree

Doc/library/ast.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2257,7 +2257,7 @@ and classes for traversing abstract syntax trees:
22572257

22582258
In addition, if ``mode`` is ``'func_type'``, the input syntax is
22592259
modified to correspond to :pep:`484` "signature type comments",
2260-
e.g. ``(str, int) -> List[str]``.
2260+
for example ``(str, int) -> List[str]``.
22612261

22622262
Setting ``feature_version`` to a tuple ``(major, minor)`` will result in
22632263
a "best-effort" attempt to parse using that Python version's grammar.

Lib/test/test_ast/test_ast.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,15 @@ def test_parse_invalid_ast(self):
152152
self.assertRaises(TypeError, ast.parse, ast.Constant(42),
153153
optimize=optval)
154154

155+
def test_parse_ast_func_type(self):
156+
# see gh-156689
157+
tree = ast.parse('(int, str) -> bool', mode='func_type')
158+
self.assertEqual(ast.dump(ast.parse(tree, mode='func_type')),
159+
ast.dump(tree))
160+
self.assertRaises(TypeError, ast.parse, ast.Constant(42),
161+
mode='func_type')
162+
self.assertRaises(TypeError, ast.parse, tree, mode='exec')
163+
155164
def test_optimization_levels__debug__(self):
156165
cases = [(-1, '__debug__'), (0, '__debug__'), (1, False), (2, False)]
157166
for (optval, expected) in cases:
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix an out-of-bounds read in :func:`compile` and :func:`ast.parse` when an AST
2+
object is passed with ``mode='func_type'``.

Parser/asdl_c.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2169,22 +2169,25 @@ class PartingShots(StaticVisitor):
21692169
return result;
21702170
}
21712171
2172-
/* mode is 0 for "exec", 1 for "eval" and 2 for "single" input */
2172+
/* mode is 0 for "exec", 1 for "eval", 2 for "single" and 3 for "func_type"
2173+
input */
21732174
int PyAst_CheckMode(PyObject *ast, int mode)
21742175
{
2175-
const char * const req_name[] = {"Module", "Expression", "Interactive"};
2176+
const char * const req_name[] = {"Module", "Expression", "Interactive",
2177+
"FunctionType"};
21762178
21772179
struct ast_state *state = get_ast_state();
21782180
if (state == NULL) {
21792181
return -1;
21802182
}
21812183
2182-
PyObject *req_type[3];
2184+
PyObject *req_type[4];
21832185
req_type[0] = state->Module_type;
21842186
req_type[1] = state->Expression_type;
21852187
req_type[2] = state->Interactive_type;
2188+
req_type[3] = state->FunctionType_type;
21862189
2187-
assert(0 <= mode && mode <= 2);
2190+
assert(0 <= mode && mode <= 3);
21882191
int isinstance = PyObject_IsInstance(ast, req_type[mode]);
21892192
if (isinstance == -1) {
21902193
return -1;

Python/Python-ast.c

Lines changed: 7 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)