Skip to content

Commit 3f73860

Browse files
authored
GH-94979: Pop the exception stack when jumping out of exception handlers. (#95003)
1 parent 3f2dd0a commit 3f73860

File tree

1 file changed

+52
-9
lines changed

1 file changed

+52
-9
lines changed

Objects/frameobject.c

+52-9
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;
@@ -420,6 +443,20 @@ mark_stacks(PyCodeObject *code_obj, int len)
420443
stacks[i+1] = next_stack;
421444
break;
422445
}
446+
case SWAP:
447+
{
448+
int n = get_arg(code, i);
449+
next_stack = stack_swap(next_stack, n);
450+
stacks[i+1] = next_stack;
451+
break;
452+
}
453+
case COPY:
454+
{
455+
int n = get_arg(code, i);
456+
next_stack = push_value(next_stack, peek(next_stack, n));
457+
stacks[i+1] = next_stack;
458+
break;
459+
}
423460
default:
424461
{
425462
int delta = PyCompile_OpcodeStackEffect(opcode, _Py_OPARG(code[i]));
@@ -556,13 +593,6 @@ first_line_not_before(int *lines, int len, int line)
556593
return result;
557594
}
558595

559-
static void
560-
frame_stack_pop(PyFrameObject *f)
561-
{
562-
PyObject *v = _PyFrame_StackPop(f->f_frame);
563-
Py_XDECREF(v);
564-
}
565-
566596
static PyFrameState
567597
_PyFrame_GetState(PyFrameObject *frame)
568598
{
@@ -782,7 +812,20 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore
782812
start_stack = pop_value(start_stack);
783813
}
784814
while (start_stack > best_stack) {
785-
frame_stack_pop(f);
815+
if (top_of_stack(start_stack) == Except) {
816+
/* Pop exception stack as well as the evaluation stack */
817+
PyThreadState *tstate = _PyThreadState_GET();
818+
_PyErr_StackItem *exc_info = tstate->exc_info;
819+
PyObject *value = exc_info->exc_value;
820+
PyObject *exc = _PyFrame_StackPop(f->f_frame);
821+
assert(PyExceptionInstance_Check(exc) || exc == Py_None);
822+
exc_info->exc_value = exc;
823+
Py_XDECREF(value);
824+
}
825+
else {
826+
PyObject *v = _PyFrame_StackPop(f->f_frame);
827+
Py_XDECREF(v);
828+
}
786829
start_stack = pop_value(start_stack);
787830
}
788831
/* Finally set the new lasti and return OK. */

0 commit comments

Comments
 (0)