Skip to content

Commit 28e2929

Browse files
committed
GH-94979: Pop the exception stack when jumping out of exception handlers. (#95003)
1 parent 9ae9992 commit 28e2929

File tree

1 file changed

+52
-9
lines changed

1 file changed

+52
-9
lines changed

Objects/frameobject.c

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -182,10 +182,31 @@ pop_value(int64_t stack)
182182
return Py_ARITHMETIC_RIGHT_SHIFT(int64_t, stack, BITS_PER_BLOCK);
183183
}
184184

185+
#define MASK ((1<<BITS_PER_BLOCK)-1)
186+
185187
static inline Kind
186188
top_of_stack(int64_t stack)
187189
{
188-
return stack & ((1<<BITS_PER_BLOCK)-1);
190+
return stack & MASK;
191+
}
192+
193+
static inline Kind
194+
peek(int64_t stack, int n)
195+
{
196+
assert(n >= 1);
197+
return (stack>>(BITS_PER_BLOCK*(n-1))) & MASK;
198+
}
199+
200+
static Kind
201+
stack_swap(int64_t stack, int n)
202+
{
203+
assert(n >= 1);
204+
Kind to_swap = peek(stack, n);
205+
Kind top = top_of_stack(stack);
206+
int shift = BITS_PER_BLOCK*(n-1);
207+
int64_t replaced_low = (stack & ~(MASK << shift)) | (top << shift);
208+
int64_t replaced_top = (replaced_low & ~MASK) | to_swap;
209+
return replaced_top;
189210
}
190211

191212
static int64_t
@@ -218,6 +239,7 @@ tos_char(int64_t stack) {
218239
case Null:
219240
return 'N';
220241
}
242+
return '?';
221243
}
222244

223245
static void
@@ -371,6 +393,7 @@ mark_stacks(PyCodeObject *code_obj, int len)
371393
stacks[i+1] = next_stack;
372394
break;
373395
case POP_EXCEPT:
396+
assert(top_of_stack(next_stack) == Except);
374397
next_stack = pop_value(next_stack);
375398
stacks[i+1] = next_stack;
376399
break;
@@ -409,6 +432,20 @@ mark_stacks(PyCodeObject *code_obj, int len)
409432
stacks[i+1] = next_stack;
410433
break;
411434
}
435+
case SWAP:
436+
{
437+
int n = get_arg(code, i);
438+
next_stack = stack_swap(next_stack, n);
439+
stacks[i+1] = next_stack;
440+
break;
441+
}
442+
case COPY:
443+
{
444+
int n = get_arg(code, i);
445+
next_stack = push_value(next_stack, peek(next_stack, n));
446+
stacks[i+1] = next_stack;
447+
break;
448+
}
412449
default:
413450
{
414451
int delta = PyCompile_OpcodeStackEffect(opcode, _Py_OPARG(code[i]));
@@ -545,13 +582,6 @@ first_line_not_before(int *lines, int len, int line)
545582
return result;
546583
}
547584

548-
static void
549-
frame_stack_pop(PyFrameObject *f)
550-
{
551-
PyObject *v = _PyFrame_StackPop(f->f_frame);
552-
Py_XDECREF(v);
553-
}
554-
555585
static PyFrameState
556586
_PyFrame_GetState(PyFrameObject *frame)
557587
{
@@ -739,7 +769,20 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore
739769
start_stack = pop_value(start_stack);
740770
}
741771
while (start_stack > best_stack) {
742-
frame_stack_pop(f);
772+
if (top_of_stack(start_stack) == Except) {
773+
/* Pop exception stack as well as the evaluation stack */
774+
PyThreadState *tstate = _PyThreadState_GET();
775+
_PyErr_StackItem *exc_info = tstate->exc_info;
776+
PyObject *value = exc_info->exc_value;
777+
PyObject *exc = _PyFrame_StackPop(f->f_frame);
778+
assert(PyExceptionInstance_Check(exc) || exc == Py_None);
779+
exc_info->exc_value = exc;
780+
Py_XDECREF(value);
781+
}
782+
else {
783+
PyObject *v = _PyFrame_StackPop(f->f_frame);
784+
Py_XDECREF(v);
785+
}
743786
start_stack = pop_value(start_stack);
744787
}
745788
/* Finally set the new lasti and return OK. */

0 commit comments

Comments
 (0)