Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Doc/library/ast.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2254,7 +2254,7 @@ and classes for traversing abstract syntax trees:

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

Setting ``feature_version`` to a tuple ``(major, minor)`` will result in
a "best-effort" attempt to parse using that Python version's grammar.
Expand Down
9 changes: 9 additions & 0 deletions Lib/test/test_ast/test_ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,15 @@ def test_parse_invalid_ast(self):
self.assertRaises(TypeError, ast.parse, ast.Constant(42),
optimize=optval)

def test_parse_ast_func_type(self):
# see gh-156689
tree = ast.parse('(int, str) -> bool', mode='func_type')
self.assertEqual(ast.dump(ast.parse(tree, mode='func_type')),
ast.dump(tree))
self.assertRaises(TypeError, ast.parse, ast.Constant(42),
mode='func_type')
self.assertRaises(TypeError, ast.parse, tree, mode='exec')

def test_optimization_levels__debug__(self):
cases = [(-1, '__debug__'), (0, '__debug__'), (1, False), (2, False)]
for (optval, expected) in cases:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix an out-of-bounds read in :func:`compile` and :func:`ast.parse` when an AST
object is passed with ``mode='func_type'``.
11 changes: 7 additions & 4 deletions Parser/asdl_c.py
Original file line number Diff line number Diff line change
Expand Up @@ -2122,22 +2122,25 @@ class PartingShots(StaticVisitor):
return result;
}

/* mode is 0 for "exec", 1 for "eval" and 2 for "single" input */
/* mode is 0 for "exec", 1 for "eval", 2 for "single" and 3 for "func_type"
input */
int PyAst_CheckMode(PyObject *ast, int mode)
{
const char * const req_name[] = {"Module", "Expression", "Interactive"};
const char * const req_name[] = {"Module", "Expression", "Interactive",
"FunctionType"};

struct ast_state *state = get_ast_state();
if (state == NULL) {
return -1;
}

PyObject *req_type[3];
PyObject *req_type[4];
req_type[0] = state->Module_type;
req_type[1] = state->Expression_type;
req_type[2] = state->Interactive_type;
req_type[3] = state->FunctionType_type;

assert(0 <= mode && mode <= 2);
assert(0 <= mode && mode <= 3);
int isinstance = PyObject_IsInstance(ast, req_type[mode]);
if (isinstance == -1) {
return -1;
Expand Down
11 changes: 7 additions & 4 deletions Python/Python-ast.c

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading