mirror of
https://github.com/python/cpython.git
synced 2026-10-28 10:25:05 +08:00
gh-156689: Fix out-of-bounds read in PyAst_CheckMode() for mode='func_type' (#156697)
This commit is contained in:
1 parent
03503dccd0
commit
d7f9c6400f
5 files changed
+26
-9
No files matched your search
+1
-1
@@ -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.
|
||||
|
||||
@@ -162,6 +162,15 @@ class AST_Tests(unittest.TestCase):
|
||||
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:
|
||||
|
||||
@@ -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'``.
|
||||
+7
-4
@@ -2122,22 +2122,25 @@ PyObject* PyAST_mod2obj(mod_ty t)
|
||||
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;
|
||||
|
||||
Generated
+7
-4
@@ -18549,22 +18549,25 @@ PyObject* PyAST_mod2obj(mod_ty t)
|
||||
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;
|
||||
|
||||
Reference in new issue
Block a user