Skip to content

Commit 801f771

Browse files
authored
[3.9] gh-92311: Let frame_setlineno jump over listcomps (#92740)
1 parent f6bd1bd commit 801f771

File tree

3 files changed

+53
-1
lines changed

3 files changed

+53
-1
lines changed

Lib/test/test_sys_settrace.py

+48
Original file line numberDiff line numberDiff line change
@@ -1603,6 +1603,54 @@ def gen():
16031603
next(gen())
16041604
output.append(5)
16051605

1606+
@jump_test(2, 3, [1, 3])
1607+
def test_jump_forward_over_listcomp(output):
1608+
output.append(1)
1609+
x = [i for i in range(10)]
1610+
output.append(3)
1611+
1612+
# checking for segfaults.
1613+
# See https://github.com/python/cpython/issues/92311
1614+
@jump_test(3, 1, [])
1615+
def test_jump_backward_over_listcomp(output):
1616+
a = 1
1617+
x = [i for i in range(10)]
1618+
c = 3
1619+
1620+
@jump_test(8, 2, [2, 7, 2])
1621+
def test_jump_backward_over_listcomp_v2(output):
1622+
flag = False
1623+
output.append(2)
1624+
if flag:
1625+
return
1626+
x = [i for i in range(5)]
1627+
flag = 6
1628+
output.append(7)
1629+
output.append(8)
1630+
1631+
@async_jump_test(2, 3, [1, 3])
1632+
async def test_jump_forward_over_async_listcomp(output):
1633+
output.append(1)
1634+
x = [i async for i in asynciter(range(10))]
1635+
output.append(3)
1636+
1637+
@async_jump_test(3, 1, [])
1638+
async def test_jump_backward_over_async_listcomp(output):
1639+
a = 1
1640+
x = [i async for i in asynciter(range(10))]
1641+
c = 3
1642+
1643+
@async_jump_test(8, 2, [2, 7, 2])
1644+
async def test_jump_backward_over_async_listcomp_v2(output):
1645+
flag = False
1646+
output.append(2)
1647+
if flag:
1648+
return
1649+
x = [i async for i in asynciter(range(5))]
1650+
flag = 6
1651+
output.append(7)
1652+
output.append(8)
1653+
16061654

16071655
if __name__ == "__main__":
16081656
unittest.main()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed a bug where setting ``frame.f_lineno`` to jump over a list comprehension could misbehave or crash.

Objects/frameobject.c

+4-1
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,10 @@ markblocks(PyCodeObject *code_obj, int len)
173173
break;
174174
case GET_ITER:
175175
case GET_AITER:
176-
block_stack = push_block(block_stack, Loop);
176+
// For-loops get a Loop block, but comprehensions do not.
177+
if (_Py_OPCODE(code[i + 1]) != CALL_FUNCTION) {
178+
block_stack = push_block(block_stack, Loop);
179+
}
177180
blocks[i+1] = block_stack;
178181
break;
179182
case FOR_ITER:

0 commit comments

Comments
 (0)