Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 26c9f56

Browse files
bpo-33026: Fix jumping out of "with" block by setting f_lineno. (python#6026)
1 parent 51302a5 commit 26c9f56

File tree

3 files changed

+44
-9
lines changed

3 files changed

+44
-9
lines changed

Lib/test/test_sys_settrace.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -827,6 +827,34 @@ def test_jump_across_with(output):
827827
with tracecontext(output, 4):
828828
output.append(5)
829829

830+
@jump_test(4, 5, [1, 3, 5, 6])
831+
def test_jump_out_of_with_block_within_for_block(output):
832+
output.append(1)
833+
for i in [1]:
834+
with tracecontext(output, 3):
835+
output.append(4)
836+
output.append(5)
837+
output.append(6)
838+
839+
@jump_test(4, 5, [1, 2, 3, 5, -2, 6])
840+
def test_jump_out_of_with_block_within_with_block(output):
841+
output.append(1)
842+
with tracecontext(output, 2):
843+
with tracecontext(output, 3):
844+
output.append(4)
845+
output.append(5)
846+
output.append(6)
847+
848+
@jump_test(5, 6, [2, 4, 6, 7])
849+
def test_jump_out_of_with_block_within_finally_block(output):
850+
try:
851+
output.append(2)
852+
finally:
853+
with tracecontext(output, 4):
854+
output.append(5)
855+
output.append(6)
856+
output.append(7)
857+
830858
@jump_test(8, 11, [1, 3, 5, 11, 12])
831859
def test_jump_out_of_complex_nested_blocks(output):
832860
output.append(1)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed jumping out of "with" block by setting f_lineno.

Objects/frameobject.c

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno)
8989
long l_new_lineno;
9090
int overflow;
9191
int new_lasti = 0; /* The new value of f_lasti */
92-
int new_iblock = 0; /* The new value of f_iblock */
9392
unsigned char *code = NULL; /* The bytecode for the frame... */
9493
Py_ssize_t code_len = 0; /* ...and its length */
9594
unsigned char *lnotab = NULL; /* Iterating over co_lnotab */
@@ -99,6 +98,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno)
9998
int addr = 0; /* (ditto) */
10099
int delta_iblock = 0; /* Scanning the SETUPs and POPs */
101100
int for_loop_delta = 0; /* (ditto) */
101+
int delta;
102102
int blockstack[CO_MAXBLOCKS]; /* Walking the 'finally' blocks */
103103
int blockstack_top = 0; /* (ditto) */
104104

@@ -258,19 +258,25 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno)
258258
assert(blockstack_top == 0);
259259

260260
/* Pop any blocks that we're jumping out of. */
261-
new_iblock = f->f_iblock - delta_iblock;
262-
while (f->f_iblock > new_iblock) {
263-
PyTryBlock *b = &f->f_blockstack[--f->f_iblock];
264-
while ((f->f_stacktop - f->f_valuestack) > b->b_level) {
265-
PyObject *v = (*--f->f_stacktop);
266-
Py_DECREF(v);
261+
delta = 0;
262+
if (delta_iblock > 0) {
263+
f->f_iblock -= delta_iblock;
264+
PyTryBlock *b = &f->f_blockstack[f->f_iblock];
265+
delta = (f->f_stacktop - f->f_valuestack) - b->b_level;
266+
if (b->b_type == SETUP_FINALLY &&
267+
code[b->b_handler] == WITH_CLEANUP_START)
268+
{
269+
/* Pop the exit function. */
270+
delta++;
267271
}
268272
}
269273
/* Pop the iterators of any 'for' loop we're jumping out of. */
270-
while (for_loop_delta > 0) {
274+
delta += for_loop_delta;
275+
276+
while (delta > 0) {
271277
PyObject *v = (*--f->f_stacktop);
272278
Py_DECREF(v);
273-
for_loop_delta--;
279+
delta--;
274280
}
275281

276282
/* Finally set the new f_lineno and f_lasti and return OK. */

0 commit comments

Comments
 (0)