Skip to content

Commit b3bf212

Browse files
gh-141976: Check stack bounds in JIT optimizer (GH-142201)
1 parent 2dac9e6 commit b3bf212

File tree

6 files changed

+212
-6
lines changed

6 files changed

+212
-6
lines changed

Lib/test/test_generated_cases.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2115,6 +2115,7 @@ def test_validate_uop_unused_input(self):
21152115
"""
21162116
output = """
21172117
case OP: {
2118+
CHECK_STACK_BOUNDS(-1);
21182119
stack_pointer += -1;
21192120
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
21202121
break;
@@ -2132,6 +2133,7 @@ def test_validate_uop_unused_input(self):
21322133
"""
21332134
output = """
21342135
case OP: {
2136+
CHECK_STACK_BOUNDS(-1);
21352137
stack_pointer += -1;
21362138
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
21372139
break;
@@ -2153,6 +2155,7 @@ def test_validate_uop_unused_output(self):
21532155
case OP: {
21542156
JitOptRef foo;
21552157
foo = NULL;
2158+
CHECK_STACK_BOUNDS(1);
21562159
stack_pointer[0] = foo;
21572160
stack_pointer += 1;
21582161
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
@@ -2172,6 +2175,7 @@ def test_validate_uop_unused_output(self):
21722175
"""
21732176
output = """
21742177
case OP: {
2178+
CHECK_STACK_BOUNDS(1);
21752179
stack_pointer += 1;
21762180
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
21772181
break;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Check against abstract stack overflow in the JIT optimizer.

Python/optimizer_analysis.c

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,10 +144,6 @@ incorrect_keys(PyObject *obj, uint32_t version)
144144

145145
#define CURRENT_FRAME_IS_INIT_SHIM() (ctx->frame->code == ((PyCodeObject *)&_Py_InitCleanup))
146146

147-
#define WITHIN_STACK_BOUNDS() \
148-
(CURRENT_FRAME_IS_INIT_SHIM() || (STACK_LEVEL() >= 0 && STACK_LEVEL() <= STACK_SIZE()))
149-
150-
151147
#define GETLOCAL(idx) ((ctx->frame->locals[idx]))
152148

153149
#define REPLACE_OP(INST, OP, ARG, OPERAND) \
@@ -192,6 +188,27 @@ incorrect_keys(PyObject *obj, uint32_t version)
192188

193189
#define JUMP_TO_LABEL(label) goto label;
194190

191+
static int
192+
check_stack_bounds(JitOptContext *ctx, JitOptRef *stack_pointer, int offset, int opcode)
193+
{
194+
int stack_level = (int)(stack_pointer + (offset) - ctx->frame->stack);
195+
int should_check = !CURRENT_FRAME_IS_INIT_SHIM() ||
196+
(opcode == _RETURN_VALUE) ||
197+
(opcode == _RETURN_GENERATOR) ||
198+
(opcode == _YIELD_VALUE);
199+
if (should_check && (stack_level < 0 || stack_level > STACK_SIZE())) {
200+
ctx->contradiction = true;
201+
ctx->done = true;
202+
return 1;
203+
}
204+
return 0;
205+
}
206+
207+
#define CHECK_STACK_BOUNDS(offset) \
208+
if (check_stack_bounds(ctx, stack_pointer, offset, opcode)) { \
209+
break; \
210+
} \
211+
195212
static int
196213
optimize_to_bool(
197214
_PyUOpInstruction *this_instr,

0 commit comments

Comments
 (0)