Skip to content

Commit 384c6d7

Browse files
bpo-37947: Avoid double-decrement in symtable recursion counting (GH-15593)
With `symtable_visit_expr` now correctly adjusting the recursion depth for named expressions, `symtable_handle_namedexpr` should be leaving it alone. Also adds a new check to `PySymtable_BuildObject` that raises `SystemError` if a successful first symbol analysis pass fails to keep the stack depth accounting clean. (cherry picked from commit 0614523) Co-authored-by: Nick Coghlan <ncoghlan@gmail.com>
1 parent c71ae1a commit 384c6d7

1 file changed

Lines changed: 14 additions & 4 deletions

File tree

‎Python/symtable.c‎

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ PySymtable_BuildObject(mod_ty mod, PyObject *filename, PyFutureFeatures *future)
266266
inti;
267267
PyThreadState*tstate;
268268
intrecursion_limit=Py_GetRecursionLimit();
269+
intstarting_recursion_depth;
269270

270271
if (st==NULL)
271272
returnNULL;
@@ -284,8 +285,9 @@ PySymtable_BuildObject(mod_ty mod, PyObject *filename, PyFutureFeatures *future)
284285
returnNULL;
285286
}
286287
/* Be careful here to prevent overflow. */
287-
st->recursion_depth= (tstate->recursion_depth<INT_MAX / COMPILER_STACK_FRAME_SCALE) ?
288+
starting_recursion_depth= (tstate->recursion_depth<INT_MAX / COMPILER_STACK_FRAME_SCALE) ?
288289
tstate->recursion_depth*COMPILER_STACK_FRAME_SCALE : tstate->recursion_depth;
290+
st->recursion_depth=starting_recursion_depth;
289291
st->recursion_limit= (recursion_limit<INT_MAX / COMPILER_STACK_FRAME_SCALE) ?
290292
recursion_limit*COMPILER_STACK_FRAME_SCALE : recursion_limit;
291293

@@ -329,6 +331,14 @@ PySymtable_BuildObject(mod_ty mod, PyObject *filename, PyFutureFeatures *future)
329331
PySymtable_Free(st);
330332
returnNULL;
331333
}
334+
/* Check that the recursion depth counting balanced correctly */
335+
if (st->recursion_depth!=starting_recursion_depth) {
336+
PyErr_Format(PyExc_SystemError,
337+
"symtable analysis recursion depth mismatch (before=%d, after=%d)",
338+
starting_recursion_depth, st->recursion_depth);
339+
PySymtable_Free(st);
340+
returnNULL;
341+
}
332342
/* Make the second symbol analysis pass */
333343
if (symtable_analyze(st))
334344
returnst;
@@ -1501,16 +1511,16 @@ symtable_handle_namedexpr(struct symtable *st, expr_ty e)
15011511
PyErr_SyntaxLocationObject(st->st_filename,
15021512
e->lineno,
15031513
e->col_offset);
1504-
VISIT_QUIT(st, 0);
1514+
return0;
15051515
}
15061516
if (st->st_cur->ste_comprehension) {
15071517
/* Inside a comprehension body, so find the right target scope */
15081518
if (!symtable_extend_namedexpr_scope(st, e->v.NamedExpr.target))
1509-
VISIT_QUIT(st, 0);
1519+
return0;
15101520
}
15111521
VISIT(st, expr, e->v.NamedExpr.value);
15121522
VISIT(st, expr, e->v.NamedExpr.target);
1513-
VISIT_QUIT(st, 1);
1523+
return1;
15141524
}
15151525

15161526
staticint

0 commit comments

Comments
 (0)