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:
Nick Coghlan 2019-08-29 23:26:53 +10:00 committed by GitHub
parent 2c5fb17118
commit 06145230c8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 14 additions and 4 deletions

View File

@ -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