diff options
author | Petr Viktorin <encukou@gmail.com> | 2025-02-24 11:16:08 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-02-24 11:16:08 +0100 |
commit | ef29104f7d7ad7864f5f153cd7391af73d7cef63 (patch) | |
tree | 38c76b08e114a9e6e993081b828b64978bfefa2e /Python/ast_opt.c | |
parent | 0ff16115741aeaaaf7f963f68d5c575efb960277 (diff) | |
download | cpython-ef29104f7d7ad7864f5f153cd7391af73d7cef63.tar.gz cpython-ef29104f7d7ad7864f5f153cd7391af73d7cef63.zip |
GH-91079: Revert "GH-91079: Implement C stack limits using addresses, not counters. (GH-130007)" for now (GH130413)
Revert "GH-91079: Implement C stack limits using addresses, not counters. (GH-130007)" for now
Unfortunatlely, the change broke some buildbots.
This reverts commit 2498c22fa0a2b560491bc503fa676585c1a603d0.
Diffstat (limited to 'Python/ast_opt.c')
-rw-r--r-- | Python/ast_opt.c | 56 |
1 files changed, 44 insertions, 12 deletions
diff --git a/Python/ast_opt.c b/Python/ast_opt.c index 2c6e16817f2..1db9980d4fc 100644 --- a/Python/ast_opt.c +++ b/Python/ast_opt.c @@ -10,14 +10,24 @@ typedef struct { int optimize; int ff_features; + + int recursion_depth; /* current recursion depth */ + int recursion_limit; /* recursion limit */ } _PyASTOptimizeState; -#define ENTER_RECURSIVE() \ -if (Py_EnterRecursiveCall(" during compilation")) { \ - return 0; \ -} +#define ENTER_RECURSIVE(ST) \ + do { \ + if (++(ST)->recursion_depth > (ST)->recursion_limit) { \ + PyErr_SetString(PyExc_RecursionError, \ + "maximum recursion depth exceeded during compilation"); \ + return 0; \ + } \ + } while(0) -#define LEAVE_RECURSIVE() Py_LeaveRecursiveCall(); +#define LEAVE_RECURSIVE(ST) \ + do { \ + --(ST)->recursion_depth; \ + } while(0) static int make_const(expr_ty node, PyObject *val, PyArena *arena) @@ -414,7 +424,7 @@ astfold_mod(mod_ty node_, PyArena *ctx_, _PyASTOptimizeState *state) static int astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state) { - ENTER_RECURSIVE(); + ENTER_RECURSIVE(state); switch (node_->kind) { case BoolOp_kind: CALL_SEQ(astfold_expr, expr, node_->v.BoolOp.values); @@ -510,7 +520,7 @@ astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state) case Name_kind: if (node_->v.Name.ctx == Load && _PyUnicode_EqualToASCIIString(node_->v.Name.id, "__debug__")) { - LEAVE_RECURSIVE(); + LEAVE_RECURSIVE(state); return make_const(node_, PyBool_FromLong(!state->optimize), ctx_); } break; @@ -523,7 +533,7 @@ astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state) // No default case, so the compiler will emit a warning if new expression // kinds are added without being handled here } - LEAVE_RECURSIVE(); + LEAVE_RECURSIVE(state);; return 1; } @@ -568,7 +578,7 @@ astfold_arg(arg_ty node_, PyArena *ctx_, _PyASTOptimizeState *state) static int astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state) { - ENTER_RECURSIVE(); + ENTER_RECURSIVE(state); switch (node_->kind) { case FunctionDef_kind: CALL_SEQ(astfold_type_param, type_param, node_->v.FunctionDef.type_params); @@ -690,7 +700,7 @@ astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state) // No default case, so the compiler will emit a warning if new statement // kinds are added without being handled here } - LEAVE_RECURSIVE(); + LEAVE_RECURSIVE(state); return 1; } @@ -760,7 +770,7 @@ astfold_pattern(pattern_ty node_, PyArena *ctx_, _PyASTOptimizeState *state) // Currently, this is really only used to form complex/negative numeric // constants in MatchValue and MatchMapping nodes // We still recurse into all subexpressions and subpatterns anyway - ENTER_RECURSIVE(); + ENTER_RECURSIVE(state); switch (node_->kind) { case MatchValue_kind: CALL(fold_const_match_patterns, expr_ty, node_->v.MatchValue.value); @@ -792,7 +802,7 @@ astfold_pattern(pattern_ty node_, PyArena *ctx_, _PyASTOptimizeState *state) // No default case, so the compiler will emit a warning if new pattern // kinds are added without being handled here } - LEAVE_RECURSIVE(); + LEAVE_RECURSIVE(state); return 1; } @@ -830,12 +840,34 @@ astfold_type_param(type_param_ty node_, PyArena *ctx_, _PyASTOptimizeState *stat int _PyAST_Optimize(mod_ty mod, PyArena *arena, int optimize, int ff_features) { + PyThreadState *tstate; + int starting_recursion_depth; + _PyASTOptimizeState state; state.optimize = optimize; state.ff_features = ff_features; + /* Setup recursion depth check counters */ + tstate = _PyThreadState_GET(); + if (!tstate) { + return 0; + } + /* Be careful here to prevent overflow. */ + int recursion_depth = Py_C_RECURSION_LIMIT - tstate->c_recursion_remaining; + starting_recursion_depth = recursion_depth; + state.recursion_depth = starting_recursion_depth; + state.recursion_limit = Py_C_RECURSION_LIMIT; + int ret = astfold_mod(mod, arena, &state); assert(ret || PyErr_Occurred()); + /* Check that the recursion depth counting balanced correctly */ + if (ret && state.recursion_depth != starting_recursion_depth) { + PyErr_Format(PyExc_SystemError, + "AST optimizer recursion depth mismatch (before=%d, after=%d)", + starting_recursion_depth, state.recursion_depth); + return 0; + } + return ret; } |