From 07604150db8403abb19c9a14c94614ba81b6094f Mon Sep 17 00:00:00 2001 From: Ken Jin Date: Tue, 2 Dec 2025 21:10:11 +0000 Subject: [PATCH 1/8] Check stack bounds in JIT optimizer --- Lib/test/test_generated_cases.py | 8 +- Python/optimizer_analysis.c | 11 +- Python/optimizer_cases.c.h | 346 +++++++++---------- Tools/cases_generator/optimizer_generator.py | 24 +- Tools/cases_generator/stack.py | 15 +- 5 files changed, 213 insertions(+), 191 deletions(-) diff --git a/Lib/test/test_generated_cases.py b/Lib/test/test_generated_cases.py index 09ce329bdcd14d..b51c8bd07cd2a4 100644 --- a/Lib/test/test_generated_cases.py +++ b/Lib/test/test_generated_cases.py @@ -2116,7 +2116,7 @@ def test_validate_uop_unused_input(self): output = """ case OP: { stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } """ @@ -2133,7 +2133,7 @@ def test_validate_uop_unused_input(self): output = """ case OP: { stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } """ @@ -2155,7 +2155,7 @@ def test_validate_uop_unused_output(self): foo = NULL; stack_pointer[0] = foo; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } """ @@ -2173,7 +2173,7 @@ def test_validate_uop_unused_output(self): output = """ case OP: { stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } """ diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c index 8d7b734e17cb0b..84a847a4ae4eb0 100644 --- a/Python/optimizer_analysis.c +++ b/Python/optimizer_analysis.c @@ -144,10 +144,6 @@ incorrect_keys(PyObject *obj, uint32_t version) #define CURRENT_FRAME_IS_INIT_SHIM() (ctx->frame->code == ((PyCodeObject *)&_Py_InitCleanup)) -#define WITHIN_STACK_BOUNDS() \ - (CURRENT_FRAME_IS_INIT_SHIM() || (STACK_LEVEL() >= 0 && STACK_LEVEL() <= STACK_SIZE())) - - #define GETLOCAL(idx) ((ctx->frame->locals[idx])) #define REPLACE_OP(INST, OP, ARG, OPERAND) \ @@ -191,6 +187,13 @@ incorrect_keys(PyObject *obj, uint32_t version) #define sym_new_truthiness _Py_uop_sym_new_truthiness #define JUMP_TO_LABEL(label) goto label; +#define CHECK_STACK_BOUNDS() do { \ + if (!CURRENT_FRAME_IS_INIT_SHIM() && (STACK_LEVEL() < 0 || STACK_LEVEL() > STACK_SIZE())) { \ + ctx->contradiction = true; \ + ctx->done = true; \ + break; \ + } \ +} while (0); static int optimize_to_bool( diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index 9ebd113df2dabf..98c094ac15b0fd 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -35,7 +35,7 @@ } stack_pointer[0] = value; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -44,7 +44,7 @@ value = GETLOCAL(oparg); stack_pointer[0] = value; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -53,7 +53,7 @@ value = PyJitRef_Borrow(GETLOCAL(oparg)); stack_pointer[0] = value; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -64,7 +64,7 @@ GETLOCAL(oparg) = temp; stack_pointer[0] = value; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -76,7 +76,7 @@ value = PyJitRef_Borrow(sym_new_const(ctx, val)); stack_pointer[0] = value; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -89,7 +89,7 @@ value = PyJitRef_Borrow(sym_new_const(ctx, val)); stack_pointer[0] = value; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -98,7 +98,7 @@ value = stack_pointer[-1]; GETLOCAL(oparg) = value; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -121,37 +121,37 @@ REPLACE_OP(this_instr, _POP_TOP_UNICODE, 0, 0); } stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } case _POP_TOP_NOP: { stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } case _POP_TOP_INT: { stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } case _POP_TOP_FLOAT: { stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } case _POP_TOP_UNICODE: { stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } case _POP_TWO: { stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -160,19 +160,19 @@ res = sym_new_null(ctx); stack_pointer[0] = res; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } case _END_FOR: { stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } case _POP_ITER: { stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -181,7 +181,7 @@ val = sym_new_not_null(ctx); stack_pointer[-2] = val; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -506,13 +506,13 @@ } stack_pointer[-2] = res; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } res = sym_new_compact_int(ctx); stack_pointer[-2] = res; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -556,13 +556,13 @@ } stack_pointer[-2] = res; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } res = sym_new_compact_int(ctx); stack_pointer[-2] = res; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -606,13 +606,13 @@ } stack_pointer[-2] = res; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } res = sym_new_compact_int(ctx); stack_pointer[-2] = res; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -675,7 +675,7 @@ } stack_pointer[-2] = res; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } res = sym_new_type(ctx, &PyFloat_Type); @@ -684,7 +684,7 @@ } stack_pointer[-2] = res; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -727,7 +727,7 @@ } stack_pointer[-2] = res; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } res = sym_new_type(ctx, &PyFloat_Type); @@ -736,7 +736,7 @@ } stack_pointer[-2] = res; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -779,7 +779,7 @@ } stack_pointer[-2] = res; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } res = sym_new_type(ctx, &PyFloat_Type); @@ -788,7 +788,7 @@ } stack_pointer[-2] = res; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -797,7 +797,7 @@ res = sym_new_not_null(ctx); stack_pointer[-2] = res; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -806,7 +806,7 @@ res = sym_new_not_null(ctx); stack_pointer[-2] = res; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -815,7 +815,7 @@ res = sym_new_not_null(ctx); stack_pointer[-2] = res; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -858,13 +858,13 @@ } stack_pointer[-2] = res; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } res = sym_new_type(ctx, &PyUnicode_Type); stack_pointer[-2] = res; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -889,7 +889,7 @@ } GETLOCAL(this_instr->operand0) = res; stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -902,7 +902,7 @@ res = sym_new_not_null(ctx); stack_pointer[-2] = res; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -922,13 +922,13 @@ } stack_pointer[-3] = res; stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } case _STORE_SLICE: { stack_pointer += -4; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -937,7 +937,7 @@ res = sym_new_not_null(ctx); stack_pointer[-2] = res; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -946,7 +946,7 @@ res = sym_new_not_null(ctx); stack_pointer[-2] = res; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -955,7 +955,7 @@ res = sym_new_type(ctx, &PyUnicode_Type); stack_pointer[-2] = res; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -1004,7 +1004,7 @@ } stack_pointer[-2] = res; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -1033,7 +1033,7 @@ res = sym_new_not_null(ctx); stack_pointer[-2] = res; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -1042,7 +1042,7 @@ getitem = sym_new_not_null(ctx); stack_pointer[0] = getitem; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -1052,43 +1052,43 @@ ctx->done = true; stack_pointer[-3] = new_frame; stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } case _LIST_APPEND: { stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } case _SET_ADD: { stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } case _STORE_SUBSCR: { stack_pointer += -3; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } case _STORE_SUBSCR_LIST_INT: { stack_pointer += -3; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } case _STORE_SUBSCR_DICT: { stack_pointer += -3; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } case _DELETE_SUBSCR: { stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -1104,7 +1104,7 @@ res = sym_new_not_null(ctx); stack_pointer[-2] = res; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -1114,7 +1114,7 @@ retval = stack_pointer[-1]; JitOptRef temp = PyJitRef_StripReferenceInfo(retval); stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); ctx->frame->stack_pointer = stack_pointer; PyCodeObject *returning_code = get_code_with_logging(this_instr); if (returning_code == NULL) { @@ -1136,7 +1136,7 @@ res = temp; stack_pointer[0] = res; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -1152,7 +1152,7 @@ awaitable = sym_new_not_null(ctx); stack_pointer[0] = awaitable; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -1179,7 +1179,7 @@ retval = stack_pointer[-1]; JitOptRef temp = PyJitRef_StripReferenceInfo(retval); stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); ctx->frame->stack_pointer = stack_pointer; PyCodeObject *returning_code = get_code_with_logging(this_instr); if (returning_code == NULL) { @@ -1195,13 +1195,13 @@ value = temp; stack_pointer[0] = value; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } case _POP_EXCEPT: { stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -1210,7 +1210,7 @@ value = sym_new_not_null(ctx); stack_pointer[0] = value; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -1219,13 +1219,13 @@ bc = sym_new_not_null(ctx); stack_pointer[0] = bc; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } case _STORE_NAME: { stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -1243,7 +1243,7 @@ values[i] = sym_new_unknown(ctx); } stack_pointer += -1 + oparg; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -1257,7 +1257,7 @@ stack_pointer[-1] = val1; stack_pointer[0] = val0; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -1270,7 +1270,7 @@ values[i] = sym_tuple_getitem(ctx, seq, oparg - i - 1); } stack_pointer += -1 + oparg; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -1281,7 +1281,7 @@ values[_i] = sym_new_not_null(ctx); } stack_pointer += -1 + oparg; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -1296,25 +1296,25 @@ values[i] = sym_new_unknown(ctx); } stack_pointer += (oparg & 0xFF) + (oparg >> 8); - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } case _STORE_ATTR: { stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } case _DELETE_ATTR: { stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } case _STORE_GLOBAL: { stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -1327,7 +1327,7 @@ locals = sym_new_not_null(ctx); stack_pointer[0] = locals; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -1338,7 +1338,7 @@ v = sym_new_not_null(ctx); stack_pointer[0] = v; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -1347,7 +1347,7 @@ res = &stack_pointer[0]; res[0] = sym_new_not_null(ctx); stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -1362,7 +1362,7 @@ REPLACE_OP(this_instr, _NOP, 0, 0); } stack_pointer += (oparg & 1); - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -1428,7 +1428,7 @@ } stack_pointer[0] = res; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -1464,7 +1464,7 @@ } stack_pointer[0] = res; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -1492,13 +1492,13 @@ value = sym_new_not_null(ctx); stack_pointer[0] = value; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } case _STORE_DEREF: { stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -1511,7 +1511,7 @@ str = sym_new_type(ctx, &PyUnicode_Type); stack_pointer[-oparg] = str; stack_pointer += 1 - oparg; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -1520,7 +1520,7 @@ interpolation = sym_new_not_null(ctx); stack_pointer[-2 - (oparg & 1)] = interpolation; stack_pointer += -1 - (oparg & 1); - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -1529,7 +1529,7 @@ template = sym_new_not_null(ctx); stack_pointer[-2] = template; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -1540,7 +1540,7 @@ tup = sym_new_tuple(ctx, oparg, values); stack_pointer[-oparg] = tup; stack_pointer += 1 - oparg; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -1549,19 +1549,19 @@ list = sym_new_type(ctx, &PyList_Type); stack_pointer[-oparg] = list; stack_pointer += 1 - oparg; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } case _LIST_EXTEND: { stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } case _SET_UPDATE: { stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -1570,7 +1570,7 @@ set = sym_new_type(ctx, &PySet_Type); stack_pointer[-oparg] = set; stack_pointer += 1 - oparg; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -1579,7 +1579,7 @@ map = sym_new_type(ctx, &PyDict_Type); stack_pointer[-oparg*2] = map; stack_pointer += 1 - oparg*2; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -1589,19 +1589,19 @@ case _DICT_UPDATE: { stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } case _DICT_MERGE: { stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } case _MAP_ADD: { stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -1610,7 +1610,7 @@ attr_st = sym_new_not_null(ctx); stack_pointer[-3] = attr_st; stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -1622,7 +1622,7 @@ stack_pointer[-3] = attr; stack_pointer[-2] = self_or_null; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -1639,7 +1639,7 @@ self_or_null[0] = sym_new_unknown(ctx); } stack_pointer += (oparg&1); - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -1781,19 +1781,19 @@ case _STORE_ATTR_INSTANCE_VALUE: { stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } case _STORE_ATTR_WITH_HINT: { stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } case _STORE_ATTR_SLOT: { stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -1842,7 +1842,7 @@ } stack_pointer[-2] = res; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } if (oparg & 16) { @@ -1853,7 +1853,7 @@ } stack_pointer[-2] = res; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -1893,13 +1893,13 @@ } stack_pointer[-2] = res; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } res = sym_new_type(ctx, &PyBool_Type); stack_pointer[-2] = res; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -1943,13 +1943,13 @@ } stack_pointer[-2] = res; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } res = sym_new_type(ctx, &PyBool_Type); stack_pointer[-2] = res; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -1991,13 +1991,13 @@ } stack_pointer[-2] = res; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } res = sym_new_type(ctx, &PyBool_Type); stack_pointer[-2] = res; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2006,7 +2006,7 @@ b = sym_new_type(ctx, &PyBool_Type); stack_pointer[-2] = b; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2044,13 +2044,13 @@ } stack_pointer[-2] = b; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } b = sym_new_type(ctx, &PyBool_Type); stack_pointer[-2] = b; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2070,7 +2070,7 @@ b = sym_new_type(ctx, &PyBool_Type); stack_pointer[-2] = b; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2079,7 +2079,7 @@ b = sym_new_type(ctx, &PyBool_Type); stack_pointer[-2] = b; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2105,7 +2105,7 @@ res = sym_new_not_null(ctx); stack_pointer[-2] = res; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2114,7 +2114,7 @@ res = sym_new_not_null(ctx); stack_pointer[0] = res; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2151,13 +2151,13 @@ len = sym_new_const(ctx, temp); stack_pointer[0] = len; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); Py_DECREF(temp); stack_pointer += -1; } stack_pointer[0] = len; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2166,7 +2166,7 @@ attrs = sym_new_not_null(ctx); stack_pointer[-3] = attrs; stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2175,7 +2175,7 @@ res = sym_new_not_null(ctx); stack_pointer[0] = res; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2184,7 +2184,7 @@ res = sym_new_not_null(ctx); stack_pointer[0] = res; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2193,7 +2193,7 @@ values_or_none = sym_new_not_null(ctx); stack_pointer[0] = values_or_none; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2213,7 +2213,7 @@ stack_pointer[-1] = iter; stack_pointer[0] = index_or_null; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2231,7 +2231,7 @@ next = sym_new_not_null(ctx); stack_pointer[0] = next; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2254,7 +2254,7 @@ next = sym_new_not_null(ctx); stack_pointer[0] = next; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2279,7 +2279,7 @@ next = sym_new_not_null(ctx); stack_pointer[0] = next; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2298,7 +2298,7 @@ next = sym_new_type(ctx, &PyLong_Type); stack_pointer[0] = next; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2308,7 +2308,7 @@ ctx->done = true; stack_pointer[0] = gen_frame; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2320,7 +2320,7 @@ method_and_self[0] = sym_new_null(ctx); method_and_self[1] = self; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2337,7 +2337,7 @@ res = sym_new_not_null(ctx); stack_pointer[0] = res; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2349,7 +2349,7 @@ stack_pointer[-1] = prev_exc; stack_pointer[0] = new_exc; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2377,7 +2377,7 @@ stack_pointer[-1] = attr; stack_pointer[0] = self; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2397,7 +2397,7 @@ stack_pointer[-1] = attr; stack_pointer[0] = self; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2451,7 +2451,7 @@ stack_pointer[-1] = attr; stack_pointer[0] = self; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2485,7 +2485,7 @@ new_frame = PyJitRef_Wrap((JitOptSymbol *)frame_new(ctx, co, 0, NULL, 0)); stack_pointer[-2 - oparg] = new_frame; stack_pointer += -1 - oparg; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2533,7 +2533,7 @@ res = sym_new_not_null(ctx); stack_pointer[-2 - oparg] = res; stack_pointer += -1 - oparg; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2618,7 +2618,7 @@ } stack_pointer[-2 - oparg] = new_frame; stack_pointer += -1 - oparg; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2626,7 +2626,7 @@ JitOptRef new_frame; new_frame = stack_pointer[-1]; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); if (!CURRENT_FRAME_IS_INIT_SHIM()) { ctx->frame->stack_pointer = stack_pointer; } @@ -2705,7 +2705,7 @@ } stack_pointer[-3] = res; stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2731,7 +2731,7 @@ } stack_pointer[-3] = res; stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2757,7 +2757,7 @@ } stack_pointer[-3] = res; stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2799,13 +2799,13 @@ init_frame = PyJitRef_Wrap((JitOptSymbol *)frame_new(ctx, co, 0, args-1, oparg+1)); stack_pointer[-2 - oparg] = init_frame; stack_pointer += -1 - oparg; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } case _EXIT_INIT_CHECK: { stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2814,7 +2814,7 @@ res = sym_new_not_null(ctx); stack_pointer[-2 - oparg] = res; stack_pointer += -1 - oparg; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2823,7 +2823,7 @@ res = sym_new_not_null(ctx); stack_pointer[-2 - oparg] = res; stack_pointer += -1 - oparg; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2832,7 +2832,7 @@ res = sym_new_not_null(ctx); stack_pointer[-2 - oparg] = res; stack_pointer += -1 - oparg; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2841,7 +2841,7 @@ res = sym_new_not_null(ctx); stack_pointer[-2 - oparg] = res; stack_pointer += -1 - oparg; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2874,13 +2874,13 @@ res = sym_new_const(ctx, temp); stack_pointer[-3] = res; stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); Py_DECREF(temp); stack_pointer += 2; } stack_pointer[-3] = res; stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2914,7 +2914,7 @@ } stack_pointer[-4] = res; stack_pointer += -3; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2931,7 +2931,7 @@ case _CALL_LIST_APPEND: { stack_pointer += -3; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2940,7 +2940,7 @@ res = sym_new_not_null(ctx); stack_pointer[-2 - oparg] = res; stack_pointer += -1 - oparg; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2949,7 +2949,7 @@ res = sym_new_not_null(ctx); stack_pointer[-2 - oparg] = res; stack_pointer += -1 - oparg; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2958,7 +2958,7 @@ res = sym_new_not_null(ctx); stack_pointer[-2 - oparg] = res; stack_pointer += -1 - oparg; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2967,7 +2967,7 @@ res = sym_new_not_null(ctx); stack_pointer[-2 - oparg] = res; stack_pointer += -1 - oparg; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -2990,7 +2990,7 @@ new_frame = PyJitRef_Wrap((JitOptSymbol *)frame_new(ctx, co, 0, NULL, 0)); stack_pointer[-3 - oparg] = new_frame; stack_pointer += -2 - oparg; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -3015,7 +3015,7 @@ res = sym_new_not_null(ctx); stack_pointer[-3 - oparg] = res; stack_pointer += -2 - oparg; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -3037,7 +3037,7 @@ func_out = sym_new_not_null(ctx); stack_pointer[-2] = func_out; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -3058,7 +3058,7 @@ res = sym_new_unknown(ctx); stack_pointer[0] = res; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -3067,7 +3067,7 @@ slice = sym_new_type(ctx, &PySlice_Type); stack_pointer[-oparg] = slice; stack_pointer += 1 - oparg; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -3090,7 +3090,7 @@ res = sym_new_not_null(ctx); stack_pointer[-2] = res; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -3102,7 +3102,7 @@ top = bottom; stack_pointer[0] = top; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -3141,7 +3141,7 @@ } stack_pointer[-2] = res; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } bool lhs_int = sym_matches_type(lhs, &PyLong_Type); @@ -3179,7 +3179,7 @@ } stack_pointer[-2] = res; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -3225,7 +3225,7 @@ } sym_set_const(flag, Py_True); stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -3239,7 +3239,7 @@ } sym_set_const(flag, Py_False); stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -3257,7 +3257,7 @@ } sym_set_const(val, Py_None); stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -3274,7 +3274,7 @@ eliminate_pop_guard(this_instr, false); } stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -3319,7 +3319,7 @@ value = sym_new_const(ctx, ptr); stack_pointer[0] = value; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -3337,25 +3337,25 @@ value = PyJitRef_Borrow(sym_new_const(ctx, ptr)); stack_pointer[0] = value; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } case _POP_CALL: { stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } case _POP_CALL_ONE: { stack_pointer += -3; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } case _POP_CALL_TWO: { stack_pointer += -4; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -3372,7 +3372,7 @@ value = sym_new_not_null(ctx); stack_pointer[-2] = value; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -3382,7 +3382,7 @@ value = PyJitRef_Borrow(sym_new_const(ctx, ptr)); stack_pointer[-2] = value; stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -3392,7 +3392,7 @@ value = PyJitRef_Borrow(sym_new_const(ctx, ptr)); stack_pointer[-3] = value; stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -3402,7 +3402,7 @@ value = PyJitRef_Borrow(sym_new_const(ctx, ptr)); stack_pointer[-4] = value; stack_pointer += -3; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -3414,7 +3414,7 @@ stack_pointer[-1] = value; stack_pointer[0] = new; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } @@ -3426,7 +3426,7 @@ stack_pointer[-1] = value; stack_pointer[0] = new; stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); + CHECK_STACK_BOUNDS(); break; } diff --git a/Tools/cases_generator/optimizer_generator.py b/Tools/cases_generator/optimizer_generator.py index 41df073cf6df23..ea3dff69c663ba 100644 --- a/Tools/cases_generator/optimizer_generator.py +++ b/Tools/cases_generator/optimizer_generator.py @@ -148,7 +148,23 @@ def __init__(self, out: CWriter, labels: dict[str, Label], original_uop: Uop, st self.stack = stack def emit_save(self, storage: Storage) -> None: - storage.flush(self.out) + storage.flush(self.out, check_stack_bounds=True) + + def sync_sp( + self, + tkn: Token, + tkn_iter: TokenIterator, + uop: CodeSection, + storage: Storage, + inst: Instruction | None, + ) -> bool: + next(tkn_iter) + next(tkn_iter) + next(tkn_iter) + storage.clear_inputs("when syncing stack") + storage.flush(self.out, check_stack_bounds=True) + storage.stack.clear(self.out) + return True def emit_reload(self, storage: Storage) -> None: pass @@ -256,7 +272,7 @@ def replace_opcode_if_evaluates_pure( emitter.emit("}\n") emitter.emit("}\n") - storage.flush(self.out) + storage.flush(self.out, check_stack_bounds=True) emitter.emit("break;\n") emitter.emit("}\n") return True @@ -397,12 +413,12 @@ def write_uop( var.in_local = False _, storage = emitter.emit_tokens(override, storage, None, False) out.start_line() - storage.flush(out) + storage.flush(out, check_stack_bounds=True) out.start_line() else: emit_default(out, uop, stack) out.start_line() - stack.flush(out) + stack.flush(out, check_stack_bounds=True) except StackError as ex: raise analysis_error(ex.args[0], prototype.body.open) # from None diff --git a/Tools/cases_generator/stack.py b/Tools/cases_generator/stack.py index 3a0e7e5d0d5636..8e74538f218069 100644 --- a/Tools/cases_generator/stack.py +++ b/Tools/cases_generator/stack.py @@ -291,12 +291,15 @@ def _do_emit( ) -> None: out.emit(f"stack_pointer[{stack_offset.to_c()}] = {var.name};\n") - def _save_physical_sp(self, out: CWriter) -> None: + def _save_physical_sp(self, out: CWriter, check_stack_bounds: bool) -> None: if self.physical_sp != self.logical_sp: diff = self.logical_sp - self.physical_sp out.start_line() out.emit(f"stack_pointer += {diff.to_c()};\n") - out.emit(f"assert(WITHIN_STACK_BOUNDS());\n") + if check_stack_bounds: + out.emit("CHECK_STACK_BOUNDS();\n") + else: + out.emit(f"assert(WITHIN_STACK_BOUNDS());\n") self.physical_sp = self.logical_sp self._print(out) @@ -316,10 +319,10 @@ def save_variables(self, out: CWriter) -> None: self._print(out) var_offset = var_offset.push(var.item) - def flush(self, out: CWriter) -> None: + def flush(self, out: CWriter, check_stack_bounds: bool = False) -> None: self._print(out) self.save_variables(out) - self._save_physical_sp(out) + self._save_physical_sp(out, check_stack_bounds) out.start_line() def is_flushed(self) -> bool: @@ -498,10 +501,10 @@ def locals_cached(self) -> bool: return True return False - def flush(self, out: CWriter) -> None: + def flush(self, out: CWriter, check_stack_bounds: bool = False) -> None: self.clear_dead_inputs() self._push_defined_outputs() - self.stack.flush(out) + self.stack.flush(out, check_stack_bounds=check_stack_bounds) def save(self, out: CWriter) -> None: assert self.spilled >= 0 From 3c22cb5456574ea3d7b8dc70b8321a9f07a5d8c5 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Tue, 2 Dec 2025 21:11:54 +0000 Subject: [PATCH 2/8] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2025-12-02-21-11-46.gh-issue-141976.yu7pDV.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-12-02-21-11-46.gh-issue-141976.yu7pDV.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-12-02-21-11-46.gh-issue-141976.yu7pDV.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-12-02-21-11-46.gh-issue-141976.yu7pDV.rst new file mode 100644 index 00000000000000..f77315b7c37d80 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-12-02-21-11-46.gh-issue-141976.yu7pDV.rst @@ -0,0 +1 @@ +Check against abstract stack overflow in the JIT optimizer. From 63f6fc04b41dd8563d6f05d3eb13b3711d91276a Mon Sep 17 00:00:00 2001 From: Ken Jin Date: Wed, 3 Dec 2025 19:27:33 +0000 Subject: [PATCH 3/8] apply review suggestions --- Python/optimizer_analysis.c | 3 ++- Tools/cases_generator/optimizer_generator.py | 12 ++++++------ Tools/cases_generator/stack.py | 16 +++++++++------- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c index 84a847a4ae4eb0..2427360b5718ef 100644 --- a/Python/optimizer_analysis.c +++ b/Python/optimizer_analysis.c @@ -187,7 +187,8 @@ incorrect_keys(PyObject *obj, uint32_t version) #define sym_new_truthiness _Py_uop_sym_new_truthiness #define JUMP_TO_LABEL(label) goto label; -#define CHECK_STACK_BOUNDS() do { \ +#define CHECK_STACK_BOUNDS() \ +do { \ if (!CURRENT_FRAME_IS_INIT_SHIM() && (STACK_LEVEL() < 0 || STACK_LEVEL() > STACK_SIZE())) { \ ctx->contradiction = true; \ ctx->done = true; \ diff --git a/Tools/cases_generator/optimizer_generator.py b/Tools/cases_generator/optimizer_generator.py index ea3dff69c663ba..c008679a9354b7 100644 --- a/Tools/cases_generator/optimizer_generator.py +++ b/Tools/cases_generator/optimizer_generator.py @@ -148,7 +148,7 @@ def __init__(self, out: CWriter, labels: dict[str, Label], original_uop: Uop, st self.stack = stack def emit_save(self, storage: Storage) -> None: - storage.flush(self.out, check_stack_bounds=True) + storage.flush(self.out) def sync_sp( self, @@ -162,7 +162,7 @@ def sync_sp( next(tkn_iter) next(tkn_iter) storage.clear_inputs("when syncing stack") - storage.flush(self.out, check_stack_bounds=True) + storage.flush(self.out) storage.stack.clear(self.out) return True @@ -272,7 +272,7 @@ def replace_opcode_if_evaluates_pure( emitter.emit("}\n") emitter.emit("}\n") - storage.flush(self.out, check_stack_bounds=True) + storage.flush(self.out) emitter.emit("break;\n") emitter.emit("}\n") return True @@ -413,12 +413,12 @@ def write_uop( var.in_local = False _, storage = emitter.emit_tokens(override, storage, None, False) out.start_line() - storage.flush(out, check_stack_bounds=True) + storage.flush(out) out.start_line() else: emit_default(out, uop, stack) out.start_line() - stack.flush(out, check_stack_bounds=True) + stack.flush(out) except StackError as ex: raise analysis_error(ex.args[0], prototype.body.open) # from None @@ -461,7 +461,7 @@ def generate_abstract_interpreter( declare_variables(override, out, skip_inputs=False) else: declare_variables(uop, out, skip_inputs=True) - stack = Stack() + stack = Stack(check_stack_bounds=True) write_uop(override, uop, out, stack, debug, skip_inputs=(override is None)) out.start_line() out.emit("break;\n") diff --git a/Tools/cases_generator/stack.py b/Tools/cases_generator/stack.py index 8e74538f218069..9febe800efbe5e 100644 --- a/Tools/cases_generator/stack.py +++ b/Tools/cases_generator/stack.py @@ -216,11 +216,12 @@ def array_or_scalar(var: StackItem | Local) -> str: return "array" if var.is_array() else "scalar" class Stack: - def __init__(self) -> None: + def __init__(self, check_stack_bounds: bool = False) -> None: self.base_offset = PointerOffset.zero() self.physical_sp = PointerOffset.zero() self.logical_sp = PointerOffset.zero() self.variables: list[Local] = [] + self.check_stack_bounds = check_stack_bounds def drop(self, var: StackItem, check_liveness: bool) -> None: self.logical_sp = self.logical_sp.pop(var) @@ -291,12 +292,12 @@ def _do_emit( ) -> None: out.emit(f"stack_pointer[{stack_offset.to_c()}] = {var.name};\n") - def _save_physical_sp(self, out: CWriter, check_stack_bounds: bool) -> None: + def _save_physical_sp(self, out: CWriter) -> None: if self.physical_sp != self.logical_sp: diff = self.logical_sp - self.physical_sp out.start_line() out.emit(f"stack_pointer += {diff.to_c()};\n") - if check_stack_bounds: + if self.check_stack_bounds: out.emit("CHECK_STACK_BOUNDS();\n") else: out.emit(f"assert(WITHIN_STACK_BOUNDS());\n") @@ -319,10 +320,10 @@ def save_variables(self, out: CWriter) -> None: self._print(out) var_offset = var_offset.push(var.item) - def flush(self, out: CWriter, check_stack_bounds: bool = False) -> None: + def flush(self, out: CWriter) -> None: self._print(out) self.save_variables(out) - self._save_physical_sp(out, check_stack_bounds) + self._save_physical_sp(out) out.start_line() def is_flushed(self) -> bool: @@ -350,6 +351,7 @@ def copy(self) -> "Stack": other.physical_sp = self.physical_sp other.logical_sp = self.logical_sp other.variables = [var.copy() for var in self.variables] + other.check_stack_bounds = self.check_stack_bounds return other def __eq__(self, other: object) -> bool: @@ -501,10 +503,10 @@ def locals_cached(self) -> bool: return True return False - def flush(self, out: CWriter, check_stack_bounds: bool = False) -> None: + def flush(self, out: CWriter) -> None: self.clear_dead_inputs() self._push_defined_outputs() - self.stack.flush(out, check_stack_bounds=check_stack_bounds) + self.stack.flush(out) def save(self, out: CWriter) -> None: assert self.spilled >= 0 From 08d6c79bee21424820040a0786df93c7ddacc52a Mon Sep 17 00:00:00 2001 From: Ken Jin Date: Thu, 4 Dec 2025 12:51:00 +0000 Subject: [PATCH 4/8] address review --- Tools/cases_generator/optimizer_generator.py | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/Tools/cases_generator/optimizer_generator.py b/Tools/cases_generator/optimizer_generator.py index c008679a9354b7..ab0a90e234b124 100644 --- a/Tools/cases_generator/optimizer_generator.py +++ b/Tools/cases_generator/optimizer_generator.py @@ -150,22 +150,6 @@ def __init__(self, out: CWriter, labels: dict[str, Label], original_uop: Uop, st def emit_save(self, storage: Storage) -> None: storage.flush(self.out) - def sync_sp( - self, - tkn: Token, - tkn_iter: TokenIterator, - uop: CodeSection, - storage: Storage, - inst: Instruction | None, - ) -> bool: - next(tkn_iter) - next(tkn_iter) - next(tkn_iter) - storage.clear_inputs("when syncing stack") - storage.flush(self.out) - storage.stack.clear(self.out) - return True - def emit_reload(self, storage: Storage) -> None: pass From ac6c21ac952d2ca82588e38882759d6f83f10cee Mon Sep 17 00:00:00 2001 From: Ken Jin Date: Thu, 4 Dec 2025 13:15:49 +0000 Subject: [PATCH 5/8] check before not after --- Python/optimizer_analysis.c | 5 +- Python/optimizer_cases.c.h | 523 ++++++++++++++++++++++----------- Tools/cases_generator/stack.py | 13 +- 3 files changed, 358 insertions(+), 183 deletions(-) diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c index 03f73b383fe943..22eb937b8ea1df 100644 --- a/Python/optimizer_analysis.c +++ b/Python/optimizer_analysis.c @@ -187,9 +187,10 @@ incorrect_keys(PyObject *obj, uint32_t version) #define sym_new_truthiness _Py_uop_sym_new_truthiness #define JUMP_TO_LABEL(label) goto label; -#define CHECK_STACK_BOUNDS() \ +#define CHECK_STACK_BOUNDS(offset) \ do { \ - if (!CURRENT_FRAME_IS_INIT_SHIM() && (STACK_LEVEL() < 0 || STACK_LEVEL() > STACK_SIZE())) { \ + int stack_level = (int)(stack_pointer + (offset) - ctx->frame->stack); \ + if (!CURRENT_FRAME_IS_INIT_SHIM() && (stack_level < 0 || stack_level > STACK_SIZE())) { \ ctx->contradiction = true; \ ctx->done = true; \ break; \ diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index 98c094ac15b0fd..5a01169fa26f42 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -33,27 +33,30 @@ if (sym_is_null(value)) { ctx->done = true; } + CHECK_STACK_BOUNDS(1); stack_pointer[0] = value; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _LOAD_FAST: { JitOptRef value; value = GETLOCAL(oparg); + CHECK_STACK_BOUNDS(1); stack_pointer[0] = value; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _LOAD_FAST_BORROW: { JitOptRef value; value = PyJitRef_Borrow(GETLOCAL(oparg)); + CHECK_STACK_BOUNDS(1); stack_pointer[0] = value; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -62,9 +65,10 @@ value = GETLOCAL(oparg); JitOptRef temp = sym_new_null(ctx); GETLOCAL(oparg) = temp; + CHECK_STACK_BOUNDS(1); stack_pointer[0] = value; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -74,9 +78,10 @@ PyObject *val = PyTuple_GET_ITEM(co->co_consts, oparg); REPLACE_OP(this_instr, _LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)val); value = PyJitRef_Borrow(sym_new_const(ctx, val)); + CHECK_STACK_BOUNDS(1); stack_pointer[0] = value; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -87,9 +92,10 @@ assert(_Py_IsImmortal(val)); REPLACE_OP(this_instr, _LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)val); value = PyJitRef_Borrow(sym_new_const(ctx, val)); + CHECK_STACK_BOUNDS(1); stack_pointer[0] = value; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -97,8 +103,9 @@ JitOptRef value; value = stack_pointer[-1]; GETLOCAL(oparg) = value; + CHECK_STACK_BOUNDS(-1); stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -120,68 +127,78 @@ else if (typ == &PyUnicode_Type) { REPLACE_OP(this_instr, _POP_TOP_UNICODE, 0, 0); } + CHECK_STACK_BOUNDS(-1); stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _POP_TOP_NOP: { + CHECK_STACK_BOUNDS(-1); stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _POP_TOP_INT: { + CHECK_STACK_BOUNDS(-1); stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _POP_TOP_FLOAT: { + CHECK_STACK_BOUNDS(-1); stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _POP_TOP_UNICODE: { + CHECK_STACK_BOUNDS(-1); stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _POP_TWO: { + CHECK_STACK_BOUNDS(-2); stack_pointer += -2; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _PUSH_NULL: { JitOptRef res; res = sym_new_null(ctx); + CHECK_STACK_BOUNDS(1); stack_pointer[0] = res; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _END_FOR: { + CHECK_STACK_BOUNDS(-1); stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _POP_ITER: { + CHECK_STACK_BOUNDS(-2); stack_pointer += -2; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _END_SEND: { JitOptRef val; val = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = val; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -504,15 +521,17 @@ REPLACE_OP(this_instr, _POP_TWO_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); } } + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = res; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } res = sym_new_compact_int(ctx); + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = res; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -554,15 +573,17 @@ REPLACE_OP(this_instr, _POP_TWO_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); } } + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = res; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } res = sym_new_compact_int(ctx); + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = res; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -604,15 +625,17 @@ REPLACE_OP(this_instr, _POP_TWO_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); } } + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = res; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } res = sym_new_compact_int(ctx); + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = res; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -673,18 +696,20 @@ REPLACE_OP(this_instr, _POP_TWO_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); } } + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = res; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } res = sym_new_type(ctx, &PyFloat_Type); if (PyJitRef_IsBorrowed(left) && PyJitRef_IsBorrowed(right)) { REPLACE_OP(this_instr, op_without_decref_inputs[opcode], oparg, 0); } + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = res; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -725,18 +750,20 @@ REPLACE_OP(this_instr, _POP_TWO_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); } } + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = res; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } res = sym_new_type(ctx, &PyFloat_Type); if (PyJitRef_IsBorrowed(left) && PyJitRef_IsBorrowed(right)) { REPLACE_OP(this_instr, op_without_decref_inputs[opcode], oparg, 0); } + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = res; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -777,45 +804,50 @@ REPLACE_OP(this_instr, _POP_TWO_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); } } + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = res; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } res = sym_new_type(ctx, &PyFloat_Type); if (PyJitRef_IsBorrowed(left) && PyJitRef_IsBorrowed(right)) { REPLACE_OP(this_instr, op_without_decref_inputs[opcode], oparg, 0); } + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = res; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _BINARY_OP_MULTIPLY_FLOAT__NO_DECREF_INPUTS: { JitOptRef res; res = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = res; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _BINARY_OP_ADD_FLOAT__NO_DECREF_INPUTS: { JitOptRef res; res = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = res; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _BINARY_OP_SUBTRACT_FLOAT__NO_DECREF_INPUTS: { JitOptRef res; res = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = res; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -856,15 +888,17 @@ REPLACE_OP(this_instr, _POP_TWO_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); } } + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = res; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } res = sym_new_type(ctx, &PyUnicode_Type); + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = res; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -888,8 +922,9 @@ res = sym_new_type(ctx, &PyUnicode_Type); } GETLOCAL(this_instr->operand0) = res; + CHECK_STACK_BOUNDS(-2); stack_pointer += -2; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -900,9 +935,10 @@ case _BINARY_OP_EXTEND: { JitOptRef res; res = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = res; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -920,42 +956,47 @@ else { res = sym_new_not_null(ctx); } + CHECK_STACK_BOUNDS(-2); stack_pointer[-3] = res; stack_pointer += -2; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _STORE_SLICE: { + CHECK_STACK_BOUNDS(-4); stack_pointer += -4; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _BINARY_OP_SUBSCR_LIST_INT: { JitOptRef res; res = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = res; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _BINARY_OP_SUBSCR_LIST_SLICE: { JitOptRef res; res = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = res; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _BINARY_OP_SUBSCR_STR_INT: { JitOptRef res; res = sym_new_type(ctx, &PyUnicode_Type); + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = res; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -1002,9 +1043,10 @@ else { res = sym_new_not_null(ctx); } + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = res; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -1031,18 +1073,20 @@ case _BINARY_OP_SUBSCR_DICT: { JitOptRef res; res = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = res; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _BINARY_OP_SUBSCR_CHECK_FUNC: { JitOptRef getitem; getitem = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); stack_pointer[0] = getitem; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -1050,45 +1094,52 @@ JitOptRef new_frame; new_frame = PyJitRef_NULL; ctx->done = true; + CHECK_STACK_BOUNDS(-2); stack_pointer[-3] = new_frame; stack_pointer += -2; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _LIST_APPEND: { + CHECK_STACK_BOUNDS(-1); stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _SET_ADD: { + CHECK_STACK_BOUNDS(-1); stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _STORE_SUBSCR: { + CHECK_STACK_BOUNDS(-3); stack_pointer += -3; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _STORE_SUBSCR_LIST_INT: { + CHECK_STACK_BOUNDS(-3); stack_pointer += -3; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _STORE_SUBSCR_DICT: { + CHECK_STACK_BOUNDS(-3); stack_pointer += -3; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _DELETE_SUBSCR: { + CHECK_STACK_BOUNDS(-2); stack_pointer += -2; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -1102,9 +1153,10 @@ case _CALL_INTRINSIC_2: { JitOptRef res; res = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = res; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -1112,9 +1164,9 @@ JitOptRef retval; JitOptRef res; retval = stack_pointer[-1]; - JitOptRef temp = PyJitRef_StripReferenceInfo(retval); + JitOptRef temp = PyJitRef_StripReferenceInfo(retval);CHECK_STACK_BOUNDS(-1); stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); ctx->frame->stack_pointer = stack_pointer; PyCodeObject *returning_code = get_code_with_logging(this_instr); if (returning_code == NULL) { @@ -1134,9 +1186,10 @@ } stack_pointer = ctx->frame->stack_pointer; res = temp; + CHECK_STACK_BOUNDS(1); stack_pointer[0] = res; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -1150,9 +1203,10 @@ case _GET_ANEXT: { JitOptRef awaitable; awaitable = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); stack_pointer[0] = awaitable; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -1177,9 +1231,9 @@ JitOptRef retval; JitOptRef value; retval = stack_pointer[-1]; - JitOptRef temp = PyJitRef_StripReferenceInfo(retval); + JitOptRef temp = PyJitRef_StripReferenceInfo(retval);CHECK_STACK_BOUNDS(-1); stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); ctx->frame->stack_pointer = stack_pointer; PyCodeObject *returning_code = get_code_with_logging(this_instr); if (returning_code == NULL) { @@ -1193,39 +1247,44 @@ } stack_pointer = ctx->frame->stack_pointer; value = temp; + CHECK_STACK_BOUNDS(1); stack_pointer[0] = value; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _POP_EXCEPT: { + CHECK_STACK_BOUNDS(-1); stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _LOAD_COMMON_CONSTANT: { JitOptRef value; value = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); stack_pointer[0] = value; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _LOAD_BUILD_CLASS: { JitOptRef bc; bc = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); stack_pointer[0] = bc; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _STORE_NAME: { + CHECK_STACK_BOUNDS(-1); stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -1242,8 +1301,9 @@ for (int i = 0; i < oparg; i++) { values[i] = sym_new_unknown(ctx); } + CHECK_STACK_BOUNDS(-1 + oparg); stack_pointer += -1 + oparg; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -1254,10 +1314,11 @@ seq = stack_pointer[-1]; val0 = sym_tuple_getitem(ctx, seq, 0); val1 = sym_tuple_getitem(ctx, seq, 1); + CHECK_STACK_BOUNDS(1); stack_pointer[-1] = val1; stack_pointer[0] = val0; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -1269,8 +1330,9 @@ for (int i = 0; i < oparg; i++) { values[i] = sym_tuple_getitem(ctx, seq, oparg - i - 1); } + CHECK_STACK_BOUNDS(-1 + oparg); stack_pointer += -1 + oparg; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -1280,8 +1342,9 @@ for (int _i = oparg; --_i >= 0;) { values[_i] = sym_new_not_null(ctx); } + CHECK_STACK_BOUNDS(-1 + oparg); stack_pointer += -1 + oparg; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -1295,26 +1358,30 @@ for (int i = 0; i < totalargs; i++) { values[i] = sym_new_unknown(ctx); } + CHECK_STACK_BOUNDS((oparg & 0xFF) + (oparg >> 8)); stack_pointer += (oparg & 0xFF) + (oparg >> 8); - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _STORE_ATTR: { + CHECK_STACK_BOUNDS(-2); stack_pointer += -2; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _DELETE_ATTR: { + CHECK_STACK_BOUNDS(-1); stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _STORE_GLOBAL: { + CHECK_STACK_BOUNDS(-1); stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -1325,9 +1392,10 @@ case _LOAD_LOCALS: { JitOptRef locals; locals = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); stack_pointer[0] = locals; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -1336,9 +1404,10 @@ case _LOAD_NAME: { JitOptRef v; v = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); stack_pointer[0] = v; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -1346,8 +1415,9 @@ JitOptRef *res; res = &stack_pointer[0]; res[0] = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -1361,8 +1431,9 @@ else { REPLACE_OP(this_instr, _NOP, 0, 0); } + CHECK_STACK_BOUNDS((oparg & 1)); stack_pointer += (oparg & 1); - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -1426,9 +1497,10 @@ else { res = sym_new_const(ctx, cnst); } + CHECK_STACK_BOUNDS(1); stack_pointer[0] = res; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -1462,9 +1534,10 @@ else { res = sym_new_const(ctx, cnst); } + CHECK_STACK_BOUNDS(1); stack_pointer[0] = res; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -1490,15 +1563,17 @@ case _LOAD_DEREF: { JitOptRef value; value = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); stack_pointer[0] = value; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _STORE_DEREF: { + CHECK_STACK_BOUNDS(-1); stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -1509,27 +1584,30 @@ case _BUILD_STRING: { JitOptRef str; str = sym_new_type(ctx, &PyUnicode_Type); + CHECK_STACK_BOUNDS(1 - oparg); stack_pointer[-oparg] = str; stack_pointer += 1 - oparg; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _BUILD_INTERPOLATION: { JitOptRef interpolation; interpolation = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(-1 - (oparg & 1)); stack_pointer[-2 - (oparg & 1)] = interpolation; stack_pointer += -1 - (oparg & 1); - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _BUILD_TEMPLATE: { JitOptRef template; template = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = template; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -1538,48 +1616,54 @@ JitOptRef tup; values = &stack_pointer[-oparg]; tup = sym_new_tuple(ctx, oparg, values); + CHECK_STACK_BOUNDS(1 - oparg); stack_pointer[-oparg] = tup; stack_pointer += 1 - oparg; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _BUILD_LIST: { JitOptRef list; list = sym_new_type(ctx, &PyList_Type); + CHECK_STACK_BOUNDS(1 - oparg); stack_pointer[-oparg] = list; stack_pointer += 1 - oparg; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _LIST_EXTEND: { + CHECK_STACK_BOUNDS(-1); stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _SET_UPDATE: { + CHECK_STACK_BOUNDS(-1); stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _BUILD_SET: { JitOptRef set; set = sym_new_type(ctx, &PySet_Type); + CHECK_STACK_BOUNDS(1 - oparg); stack_pointer[-oparg] = set; stack_pointer += 1 - oparg; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _BUILD_MAP: { JitOptRef map; map = sym_new_type(ctx, &PyDict_Type); + CHECK_STACK_BOUNDS(1 - oparg*2); stack_pointer[-oparg*2] = map; stack_pointer += 1 - oparg*2; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -1588,29 +1672,33 @@ } case _DICT_UPDATE: { + CHECK_STACK_BOUNDS(-1); stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _DICT_MERGE: { + CHECK_STACK_BOUNDS(-1); stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _MAP_ADD: { + CHECK_STACK_BOUNDS(-2); stack_pointer += -2; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _LOAD_SUPER_ATTR_ATTR: { JitOptRef attr_st; attr_st = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(-2); stack_pointer[-3] = attr_st; stack_pointer += -2; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -1619,10 +1707,11 @@ JitOptRef self_or_null; attr = sym_new_not_null(ctx); self_or_null = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(-1); stack_pointer[-3] = attr; stack_pointer[-2] = self_or_null; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -1638,8 +1727,9 @@ if (oparg & 1) { self_or_null[0] = sym_new_unknown(ctx); } + CHECK_STACK_BOUNDS((oparg&1)); stack_pointer += (oparg&1); - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -1780,20 +1870,23 @@ } case _STORE_ATTR_INSTANCE_VALUE: { + CHECK_STACK_BOUNDS(-2); stack_pointer += -2; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _STORE_ATTR_WITH_HINT: { + CHECK_STACK_BOUNDS(-2); stack_pointer += -2; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _STORE_ATTR_SLOT: { + CHECK_STACK_BOUNDS(-2); stack_pointer += -2; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -1840,9 +1933,10 @@ REPLACE_OP(this_instr, _POP_TWO_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); } } + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = res; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } if (oparg & 16) { @@ -1851,9 +1945,10 @@ else { res = _Py_uop_sym_new_not_null(ctx); } + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = res; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -1891,15 +1986,17 @@ REPLACE_OP(this_instr, _POP_TWO_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); } } + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = res; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } res = sym_new_type(ctx, &PyBool_Type); + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = res; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -1941,15 +2038,17 @@ REPLACE_OP(this_instr, _POP_TWO_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); } } + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = res; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } res = sym_new_type(ctx, &PyBool_Type); + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = res; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -1989,24 +2088,27 @@ REPLACE_OP(this_instr, _POP_TWO_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); } } + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = res; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } res = sym_new_type(ctx, &PyBool_Type); + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = res; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _IS_OP: { JitOptRef b; b = sym_new_type(ctx, &PyBool_Type); + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = b; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -2042,15 +2144,17 @@ REPLACE_OP(this_instr, _POP_TWO_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); } } + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = b; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } b = sym_new_type(ctx, &PyBool_Type); + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = b; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -2068,18 +2172,20 @@ case _CONTAINS_OP_SET: { JitOptRef b; b = sym_new_type(ctx, &PyBool_Type); + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = b; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _CONTAINS_OP_DICT: { JitOptRef b; b = sym_new_type(ctx, &PyBool_Type); + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = b; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -2103,18 +2209,20 @@ case _IMPORT_NAME: { JitOptRef res; res = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = res; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _IMPORT_FROM: { JitOptRef res; res = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); stack_pointer[0] = res; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -2148,52 +2256,57 @@ if (_Py_IsImmortal(temp)) { REPLACE_OP(this_instr, _LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)temp); } - len = sym_new_const(ctx, temp); + len = sym_new_const(ctx, temp);CHECK_STACK_BOUNDS(1); stack_pointer[0] = len; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); Py_DECREF(temp); stack_pointer += -1; } + CHECK_STACK_BOUNDS(1); stack_pointer[0] = len; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _MATCH_CLASS: { JitOptRef attrs; attrs = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(-2); stack_pointer[-3] = attrs; stack_pointer += -2; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _MATCH_MAPPING: { JitOptRef res; res = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); stack_pointer[0] = res; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _MATCH_SEQUENCE: { JitOptRef res; res = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); stack_pointer[0] = res; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _MATCH_KEYS: { JitOptRef values_or_none; values_or_none = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); stack_pointer[0] = values_or_none; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -2210,10 +2323,11 @@ iter = sym_new_not_null(ctx); index_or_null = sym_new_unknown(ctx); } + CHECK_STACK_BOUNDS(1); stack_pointer[-1] = iter; stack_pointer[0] = index_or_null; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -2229,9 +2343,10 @@ case _FOR_ITER_TIER_TWO: { JitOptRef next; next = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); stack_pointer[0] = next; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -2252,9 +2367,10 @@ case _ITER_NEXT_LIST_TIER_TWO: { JitOptRef next; next = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); stack_pointer[0] = next; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -2277,9 +2393,10 @@ case _ITER_NEXT_TUPLE: { JitOptRef next; next = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); stack_pointer[0] = next; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -2296,9 +2413,10 @@ case _ITER_NEXT_RANGE: { JitOptRef next; next = sym_new_type(ctx, &PyLong_Type); + CHECK_STACK_BOUNDS(1); stack_pointer[0] = next; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -2306,9 +2424,10 @@ JitOptRef gen_frame; gen_frame = PyJitRef_NULL; ctx->done = true; + CHECK_STACK_BOUNDS(1); stack_pointer[0] = gen_frame; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -2319,8 +2438,9 @@ method_and_self = &stack_pointer[-1]; method_and_self[0] = sym_new_null(ctx); method_and_self[1] = self; + CHECK_STACK_BOUNDS(1); stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -2335,9 +2455,10 @@ case _WITH_EXCEPT_START: { JitOptRef res; res = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); stack_pointer[0] = res; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -2346,10 +2467,11 @@ JitOptRef new_exc; prev_exc = sym_new_not_null(ctx); new_exc = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); stack_pointer[-1] = prev_exc; stack_pointer[0] = new_exc; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -2374,10 +2496,11 @@ _LOAD_CONST_UNDER_INLINE_BORROW, _LOAD_CONST_UNDER_INLINE); self = owner; + CHECK_STACK_BOUNDS(1); stack_pointer[-1] = attr; stack_pointer[0] = self; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -2394,10 +2517,11 @@ _LOAD_CONST_UNDER_INLINE_BORROW, _LOAD_CONST_UNDER_INLINE); self = owner; + CHECK_STACK_BOUNDS(1); stack_pointer[-1] = attr; stack_pointer[0] = self; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -2448,10 +2572,11 @@ _LOAD_CONST_UNDER_INLINE_BORROW, _LOAD_CONST_UNDER_INLINE); self = owner; + CHECK_STACK_BOUNDS(1); stack_pointer[-1] = attr; stack_pointer[0] = self; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -2483,9 +2608,10 @@ break; } new_frame = PyJitRef_Wrap((JitOptSymbol *)frame_new(ctx, co, 0, NULL, 0)); + CHECK_STACK_BOUNDS(-1 - oparg); stack_pointer[-2 - oparg] = new_frame; stack_pointer += -1 - oparg; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -2531,9 +2657,10 @@ case _CALL_NON_PY_GENERAL: { JitOptRef res; res = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(-1 - oparg); stack_pointer[-2 - oparg] = res; stack_pointer += -1 - oparg; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -2616,17 +2743,19 @@ } else { new_frame = PyJitRef_Wrap((JitOptSymbol *)frame_new(ctx, co, 0, NULL, 0)); } + CHECK_STACK_BOUNDS(-1 - oparg); stack_pointer[-2 - oparg] = new_frame; stack_pointer += -1 - oparg; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _PUSH_FRAME: { JitOptRef new_frame; new_frame = stack_pointer[-1]; + CHECK_STACK_BOUNDS(-1); stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); if (!CURRENT_FRAME_IS_INIT_SHIM()) { ctx->frame->stack_pointer = stack_pointer; } @@ -2703,9 +2832,10 @@ else { res = sym_new_not_null(ctx); } + CHECK_STACK_BOUNDS(-2); stack_pointer[-3] = res; stack_pointer += -2; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -2729,9 +2859,10 @@ else { res = sym_new_type(ctx, &PyUnicode_Type); } + CHECK_STACK_BOUNDS(-2); stack_pointer[-3] = res; stack_pointer += -2; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -2755,9 +2886,10 @@ else { res = sym_new_type(ctx, &PyTuple_Type); } + CHECK_STACK_BOUNDS(-2); stack_pointer[-3] = res; stack_pointer += -2; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -2797,51 +2929,57 @@ assert((this_instr + 1)->opcode == _PUSH_FRAME); PyCodeObject *co = get_code_with_logging((this_instr + 1)); init_frame = PyJitRef_Wrap((JitOptSymbol *)frame_new(ctx, co, 0, args-1, oparg+1)); + CHECK_STACK_BOUNDS(-1 - oparg); stack_pointer[-2 - oparg] = init_frame; stack_pointer += -1 - oparg; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _EXIT_INIT_CHECK: { + CHECK_STACK_BOUNDS(-1); stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _CALL_BUILTIN_CLASS: { JitOptRef res; res = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(-1 - oparg); stack_pointer[-2 - oparg] = res; stack_pointer += -1 - oparg; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _CALL_BUILTIN_O: { JitOptRef res; res = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(-1 - oparg); stack_pointer[-2 - oparg] = res; stack_pointer += -1 - oparg; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _CALL_BUILTIN_FAST: { JitOptRef res; res = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(-1 - oparg); stack_pointer[-2 - oparg] = res; stack_pointer += -1 - oparg; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _CALL_BUILTIN_FAST_WITH_KEYWORDS: { JitOptRef res; res = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(-1 - oparg); stack_pointer[-2 - oparg] = res; stack_pointer += -1 - oparg; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -2871,16 +3009,17 @@ REPLACE_OP(this_instr, _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)temp); } - res = sym_new_const(ctx, temp); + res = sym_new_const(ctx, temp);CHECK_STACK_BOUNDS(-2); stack_pointer[-3] = res; stack_pointer += -2; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); Py_DECREF(temp); stack_pointer += 2; } + CHECK_STACK_BOUNDS(-2); stack_pointer[-3] = res; stack_pointer += -2; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -2912,9 +3051,10 @@ sym_set_const(res, out); REPLACE_OP(this_instr, _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)out); } + CHECK_STACK_BOUNDS(-3); stack_pointer[-4] = res; stack_pointer += -3; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -2930,44 +3070,49 @@ } case _CALL_LIST_APPEND: { + CHECK_STACK_BOUNDS(-3); stack_pointer += -3; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _CALL_METHOD_DESCRIPTOR_O: { JitOptRef res; res = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(-1 - oparg); stack_pointer[-2 - oparg] = res; stack_pointer += -1 - oparg; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS: { JitOptRef res; res = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(-1 - oparg); stack_pointer[-2 - oparg] = res; stack_pointer += -1 - oparg; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _CALL_METHOD_DESCRIPTOR_NOARGS: { JitOptRef res; res = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(-1 - oparg); stack_pointer[-2 - oparg] = res; stack_pointer += -1 - oparg; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _CALL_METHOD_DESCRIPTOR_FAST: { JitOptRef res; res = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(-1 - oparg); stack_pointer[-2 - oparg] = res; stack_pointer += -1 - oparg; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -2988,9 +3133,10 @@ break; } new_frame = PyJitRef_Wrap((JitOptSymbol *)frame_new(ctx, co, 0, NULL, 0)); + CHECK_STACK_BOUNDS(-2 - oparg); stack_pointer[-3 - oparg] = new_frame; stack_pointer += -2 - oparg; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -3013,9 +3159,10 @@ case _CALL_KW_NON_PY: { JitOptRef res; res = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(-2 - oparg); stack_pointer[-3 - oparg] = res; stack_pointer += -2 - oparg; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -3035,9 +3182,10 @@ case _SET_FUNCTION_ATTRIBUTE: { JitOptRef func_out; func_out = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = func_out; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -3056,18 +3204,20 @@ } stack_pointer = ctx->frame->stack_pointer; res = sym_new_unknown(ctx); + CHECK_STACK_BOUNDS(1); stack_pointer[0] = res; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _BUILD_SLICE: { JitOptRef slice; slice = sym_new_type(ctx, &PySlice_Type); + CHECK_STACK_BOUNDS(1 - oparg); stack_pointer[-oparg] = slice; stack_pointer += 1 - oparg; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -3088,9 +3238,10 @@ case _FORMAT_WITH_SPEC: { JitOptRef res; res = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = res; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -3100,9 +3251,10 @@ bottom = stack_pointer[-1 - (oparg-1)]; assert(oparg > 0); top = bottom; + CHECK_STACK_BOUNDS(1); stack_pointer[0] = top; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -3139,9 +3291,10 @@ REPLACE_OP(this_instr, _POP_TWO_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); } } + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = res; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } bool lhs_int = sym_matches_type(lhs, &PyLong_Type); @@ -3177,9 +3330,10 @@ else { res = sym_new_type(ctx, &PyFloat_Type); } + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = res; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -3224,8 +3378,9 @@ eliminate_pop_guard(this_instr, value != Py_True); } sym_set_const(flag, Py_True); + CHECK_STACK_BOUNDS(-1); stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -3238,8 +3393,9 @@ eliminate_pop_guard(this_instr, value != Py_False); } sym_set_const(flag, Py_False); + CHECK_STACK_BOUNDS(-1); stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -3256,8 +3412,9 @@ eliminate_pop_guard(this_instr, true); } sym_set_const(val, Py_None); + CHECK_STACK_BOUNDS(-1); stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -3273,8 +3430,9 @@ assert(!sym_matches_type(val, &_PyNone_Type)); eliminate_pop_guard(this_instr, false); } + CHECK_STACK_BOUNDS(-1); stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -3317,9 +3475,10 @@ JitOptRef value; PyObject *ptr = (PyObject *)this_instr->operand0; value = sym_new_const(ctx, ptr); + CHECK_STACK_BOUNDS(1); stack_pointer[0] = value; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -3335,27 +3494,31 @@ JitOptRef value; PyObject *ptr = (PyObject *)this_instr->operand0; value = PyJitRef_Borrow(sym_new_const(ctx, ptr)); + CHECK_STACK_BOUNDS(1); stack_pointer[0] = value; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _POP_CALL: { + CHECK_STACK_BOUNDS(-2); stack_pointer += -2; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _POP_CALL_ONE: { + CHECK_STACK_BOUNDS(-3); stack_pointer += -3; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } case _POP_CALL_TWO: { + CHECK_STACK_BOUNDS(-4); stack_pointer += -4; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -3370,9 +3533,10 @@ case _POP_TWO_LOAD_CONST_INLINE_BORROW: { JitOptRef value; value = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = value; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -3380,9 +3544,10 @@ JitOptRef value; PyObject *ptr = (PyObject *)this_instr->operand0; value = PyJitRef_Borrow(sym_new_const(ctx, ptr)); + CHECK_STACK_BOUNDS(-1); stack_pointer[-2] = value; stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -3390,9 +3555,10 @@ JitOptRef value; PyObject *ptr = (PyObject *)this_instr->operand0; value = PyJitRef_Borrow(sym_new_const(ctx, ptr)); + CHECK_STACK_BOUNDS(-2); stack_pointer[-3] = value; stack_pointer += -2; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -3400,9 +3566,10 @@ JitOptRef value; PyObject *ptr = (PyObject *)this_instr->operand0; value = PyJitRef_Borrow(sym_new_const(ctx, ptr)); + CHECK_STACK_BOUNDS(-3); stack_pointer[-4] = value; stack_pointer += -3; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -3411,10 +3578,11 @@ JitOptRef new; value = sym_new_not_null(ctx); new = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); stack_pointer[-1] = value; stack_pointer[0] = new; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -3423,10 +3591,11 @@ JitOptRef new; value = sym_new_not_null(ctx); new = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); stack_pointer[-1] = value; stack_pointer[0] = new; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } diff --git a/Tools/cases_generator/stack.py b/Tools/cases_generator/stack.py index f416e40b329466..71dbd6cddbd5db 100644 --- a/Tools/cases_generator/stack.py +++ b/Tools/cases_generator/stack.py @@ -297,10 +297,7 @@ def _save_physical_sp(self, out: CWriter) -> None: diff = self.logical_sp - self.physical_sp out.start_line() out.emit(f"stack_pointer += {diff.to_c()};\n") - if self.check_stack_bounds: - out.emit("CHECK_STACK_BOUNDS();\n") - else: - out.emit(f"ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);\n") + out.emit(f"ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);\n") self.physical_sp = self.logical_sp self._print(out) @@ -320,8 +317,16 @@ def save_variables(self, out: CWriter) -> None: self._print(out) var_offset = var_offset.push(var.item) + def stack_bound_check(self, out: CWriter): + if not self.check_stack_bounds: + return + if self.physical_sp != self.logical_sp: + diff = self.logical_sp - self.physical_sp + out.emit(f"CHECK_STACK_BOUNDS({diff});\n") + def flush(self, out: CWriter) -> None: self._print(out) + self.stack_bound_check(out) self.save_variables(out) self._save_physical_sp(out) out.start_line() From 558c2cf6f190fc79fdbf15e640e1377d2e0ca258 Mon Sep 17 00:00:00 2001 From: Ken Jin Date: Thu, 4 Dec 2025 13:26:42 +0000 Subject: [PATCH 6/8] fix tests --- Lib/test/test_generated_cases.py | 12 ++++++++---- Python/optimizer_analysis.c | 2 +- Python/optimizer_cases.c.h | 12 ++++++++---- Tools/cases_generator/stack.py | 3 ++- 4 files changed, 19 insertions(+), 10 deletions(-) diff --git a/Lib/test/test_generated_cases.py b/Lib/test/test_generated_cases.py index e6d0493cd46855..de0dbab480f5e5 100644 --- a/Lib/test/test_generated_cases.py +++ b/Lib/test/test_generated_cases.py @@ -2115,8 +2115,9 @@ def test_validate_uop_unused_input(self): """ output = """ case OP: { + CHECK_STACK_BOUNDS(-1); stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } """ @@ -2132,8 +2133,9 @@ def test_validate_uop_unused_input(self): """ output = """ case OP: { + CHECK_STACK_BOUNDS(-1); stack_pointer += -1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } """ @@ -2153,9 +2155,10 @@ def test_validate_uop_unused_output(self): case OP: { JitOptRef foo; foo = NULL; + CHECK_STACK_BOUNDS(1); stack_pointer[0] = foo; stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } """ @@ -2172,8 +2175,9 @@ def test_validate_uop_unused_output(self): """ output = """ case OP: { + CHECK_STACK_BOUNDS(1); stack_pointer += 1; - CHECK_STACK_BOUNDS(); + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } """ diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c index 22eb937b8ea1df..5f466a6c961db6 100644 --- a/Python/optimizer_analysis.c +++ b/Python/optimizer_analysis.c @@ -190,7 +190,7 @@ incorrect_keys(PyObject *obj, uint32_t version) #define CHECK_STACK_BOUNDS(offset) \ do { \ int stack_level = (int)(stack_pointer + (offset) - ctx->frame->stack); \ - if (!CURRENT_FRAME_IS_INIT_SHIM() && (stack_level < 0 || stack_level > STACK_SIZE())) { \ + if (stack_level < 0 || stack_level > STACK_SIZE()) { \ ctx->contradiction = true; \ ctx->done = true; \ break; \ diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index 5a01169fa26f42..85bebed58677ed 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -1164,7 +1164,8 @@ JitOptRef retval; JitOptRef res; retval = stack_pointer[-1]; - JitOptRef temp = PyJitRef_StripReferenceInfo(retval);CHECK_STACK_BOUNDS(-1); + JitOptRef temp = PyJitRef_StripReferenceInfo(retval); + CHECK_STACK_BOUNDS(-1); stack_pointer += -1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); ctx->frame->stack_pointer = stack_pointer; @@ -1231,7 +1232,8 @@ JitOptRef retval; JitOptRef value; retval = stack_pointer[-1]; - JitOptRef temp = PyJitRef_StripReferenceInfo(retval);CHECK_STACK_BOUNDS(-1); + JitOptRef temp = PyJitRef_StripReferenceInfo(retval); + CHECK_STACK_BOUNDS(-1); stack_pointer += -1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); ctx->frame->stack_pointer = stack_pointer; @@ -2256,7 +2258,8 @@ if (_Py_IsImmortal(temp)) { REPLACE_OP(this_instr, _LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)temp); } - len = sym_new_const(ctx, temp);CHECK_STACK_BOUNDS(1); + len = sym_new_const(ctx, temp); + CHECK_STACK_BOUNDS(1); stack_pointer[0] = len; stack_pointer += 1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); @@ -3009,7 +3012,8 @@ REPLACE_OP(this_instr, _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)temp); } - res = sym_new_const(ctx, temp);CHECK_STACK_BOUNDS(-2); + res = sym_new_const(ctx, temp); + CHECK_STACK_BOUNDS(-2); stack_pointer[-3] = res; stack_pointer += -2; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); diff --git a/Tools/cases_generator/stack.py b/Tools/cases_generator/stack.py index 71dbd6cddbd5db..d20f852eefe405 100644 --- a/Tools/cases_generator/stack.py +++ b/Tools/cases_generator/stack.py @@ -321,7 +321,8 @@ def stack_bound_check(self, out: CWriter): if not self.check_stack_bounds: return if self.physical_sp != self.logical_sp: - diff = self.logical_sp - self.physical_sp + diff = self.logical_sp - self.physical_sp + out.start_line() out.emit(f"CHECK_STACK_BOUNDS({diff});\n") def flush(self, out: CWriter) -> None: From a1b0ff1db3f3d0fe5a5803131f0724e787b811b9 Mon Sep 17 00:00:00 2001 From: Ken Jin Date: Thu, 4 Dec 2025 13:32:25 +0000 Subject: [PATCH 7/8] fix mypy --- Tools/cases_generator/stack.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tools/cases_generator/stack.py b/Tools/cases_generator/stack.py index d20f852eefe405..53499558aed876 100644 --- a/Tools/cases_generator/stack.py +++ b/Tools/cases_generator/stack.py @@ -317,7 +317,7 @@ def save_variables(self, out: CWriter) -> None: self._print(out) var_offset = var_offset.push(var.item) - def stack_bound_check(self, out: CWriter): + def stack_bound_check(self, out: CWriter) -> None: if not self.check_stack_bounds: return if self.physical_sp != self.logical_sp: From 32631e809aed92f6e5d48be03f9b6b283e743498 Mon Sep 17 00:00:00 2001 From: Ken Jin Date: Thu, 4 Dec 2025 13:54:14 +0000 Subject: [PATCH 8/8] refactor into own function --- Python/optimizer_analysis.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c index 5f466a6c961db6..51722556554609 100644 --- a/Python/optimizer_analysis.c +++ b/Python/optimizer_analysis.c @@ -187,15 +187,27 @@ incorrect_keys(PyObject *obj, uint32_t version) #define sym_new_truthiness _Py_uop_sym_new_truthiness #define JUMP_TO_LABEL(label) goto label; + +static int +check_stack_bounds(JitOptContext *ctx, JitOptRef *stack_pointer, int offset, int opcode) +{ + int stack_level = (int)(stack_pointer + (offset) - ctx->frame->stack); + int should_check = !CURRENT_FRAME_IS_INIT_SHIM() || + (opcode == _RETURN_VALUE) || + (opcode == _RETURN_GENERATOR) || + (opcode == _YIELD_VALUE); + if (should_check && (stack_level < 0 || stack_level > STACK_SIZE())) { + ctx->contradiction = true; + ctx->done = true; + return 1; + } + return 0; +} + #define CHECK_STACK_BOUNDS(offset) \ -do { \ - int stack_level = (int)(stack_pointer + (offset) - ctx->frame->stack); \ - if (stack_level < 0 || stack_level > STACK_SIZE()) { \ - ctx->contradiction = true; \ - ctx->done = true; \ + if (check_stack_bounds(ctx, stack_pointer, offset, opcode)) { \ break; \ } \ -} while (0); static int optimize_to_bool(