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.
This commit is contained in:
parent
2c5fb17118
commit
06145230c8
|
@ -266,6 +266,7 @@ PySymtable_BuildObject(mod_ty mod, PyObject *filename, PyFutureFeatures *future)
|
||||||
int i;
|
int i;
|
||||||
PyThreadState *tstate;
|
PyThreadState *tstate;
|
||||||
int recursion_limit = Py_GetRecursionLimit();
|
int recursion_limit = Py_GetRecursionLimit();
|
||||||
|
int starting_recursion_depth;
|
||||||
|
|
||||||
if (st == NULL)
|
if (st == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -284,8 +285,9 @@ PySymtable_BuildObject(mod_ty mod, PyObject *filename, PyFutureFeatures *future)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
/* Be careful here to prevent overflow. */
|
/* Be careful here to prevent overflow. */
|
||||||
st->recursion_depth = (tstate->recursion_depth < INT_MAX / COMPILER_STACK_FRAME_SCALE) ?
|
starting_recursion_depth = (tstate->recursion_depth < INT_MAX / COMPILER_STACK_FRAME_SCALE) ?
|
||||||
tstate->recursion_depth * COMPILER_STACK_FRAME_SCALE : tstate->recursion_depth;
|
tstate->recursion_depth * COMPILER_STACK_FRAME_SCALE : tstate->recursion_depth;
|
||||||
|
st->recursion_depth = starting_recursion_depth;
|
||||||
st->recursion_limit = (recursion_limit < INT_MAX / COMPILER_STACK_FRAME_SCALE) ?
|
st->recursion_limit = (recursion_limit < INT_MAX / COMPILER_STACK_FRAME_SCALE) ?
|
||||||
recursion_limit * COMPILER_STACK_FRAME_SCALE : recursion_limit;
|
recursion_limit * COMPILER_STACK_FRAME_SCALE : recursion_limit;
|
||||||
|
|
||||||
|
@ -329,6 +331,14 @@ PySymtable_BuildObject(mod_ty mod, PyObject *filename, PyFutureFeatures *future)
|
||||||
PySymtable_Free(st);
|
PySymtable_Free(st);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
/* Check that the recursion depth counting balanced correctly */
|
||||||
|
if (st->recursion_depth != starting_recursion_depth) {
|
||||||
|
PyErr_Format(PyExc_SystemError,
|
||||||
|
"symtable analysis recursion depth mismatch (before=%d, after=%d)",
|
||||||
|
starting_recursion_depth, st->recursion_depth);
|
||||||
|
PySymtable_Free(st);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
/* Make the second symbol analysis pass */
|
/* Make the second symbol analysis pass */
|
||||||
if (symtable_analyze(st))
|
if (symtable_analyze(st))
|
||||||
return st;
|
return st;
|
||||||
|
@ -1501,16 +1511,16 @@ symtable_handle_namedexpr(struct symtable *st, expr_ty e)
|
||||||
PyErr_SyntaxLocationObject(st->st_filename,
|
PyErr_SyntaxLocationObject(st->st_filename,
|
||||||
e->lineno,
|
e->lineno,
|
||||||
e->col_offset);
|
e->col_offset);
|
||||||
VISIT_QUIT(st, 0);
|
return 0;
|
||||||
}
|
}
|
||||||
if (st->st_cur->ste_comprehension) {
|
if (st->st_cur->ste_comprehension) {
|
||||||
/* Inside a comprehension body, so find the right target scope */
|
/* Inside a comprehension body, so find the right target scope */
|
||||||
if (!symtable_extend_namedexpr_scope(st, e->v.NamedExpr.target))
|
if (!symtable_extend_namedexpr_scope(st, e->v.NamedExpr.target))
|
||||||
VISIT_QUIT(st, 0);
|
return 0;
|
||||||
}
|
}
|
||||||
VISIT(st, expr, e->v.NamedExpr.value);
|
VISIT(st, expr, e->v.NamedExpr.value);
|
||||||
VISIT(st, expr, e->v.NamedExpr.target);
|
VISIT(st, expr, e->v.NamedExpr.target);
|
||||||
VISIT_QUIT(st, 1);
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
Loading…
Reference in New Issue