Skip to content

Commit 0db85ee

Browse files
authored
gh-106529: Fix subtle Tier 2 edge case with list iterator (#106756)
The Tier 2 opcode _IS_ITER_EXHAUSTED_LIST (and _TUPLE) didn't set it->it_seq to NULL, causing a subtle bug that resulted in test_exhausted_iterator in list_tests.py to fail when running all tests with -Xuops. The bug was introduced in gh-106696. Added this as an explicit test. Also fixed the dependencies for ceval.o -- it depends on executor_cases.c.h.
1 parent 03185f0 commit 0db85ee

File tree

4 files changed

+38
-4
lines changed

4 files changed

+38
-4
lines changed

Lib/test/test_capi/test_misc.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2649,6 +2649,19 @@ def testfunc(a):
26492649
# Verification that the jump goes past END_FOR
26502650
# is done by manual inspection of the output
26512651

2652+
def test_list_edge_case(self):
2653+
def testfunc(it):
2654+
for x in it:
2655+
pass
2656+
2657+
opt = _testinternalcapi.get_uop_optimizer()
2658+
with temporary_optimizer(opt):
2659+
a = [1, 2, 3]
2660+
it = iter(a)
2661+
testfunc(it)
2662+
a.append(4)
2663+
with self.assertRaises(StopIteration):
2664+
next(it)
26522665

26532666
if __name__ == "__main__":
26542667
unittest.main()

Makefile.pre.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1564,6 +1564,7 @@ Python/ceval.o: \
15641564
$(srcdir)/Python/ceval_macros.h \
15651565
$(srcdir)/Python/condvar.h \
15661566
$(srcdir)/Python/generated_cases.c.h \
1567+
$(srcdir)/Python/executor_cases.c.h \
15671568
$(srcdir)/Include/internal/pycore_opcode_metadata.h \
15681569
$(srcdir)/Python/opcode_targets.h
15691570

Python/bytecodes.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2448,7 +2448,12 @@ dummy_func(
24482448
_PyListIterObject *it = (_PyListIterObject *)iter;
24492449
assert(Py_TYPE(iter) == &PyListIter_Type);
24502450
PyListObject *seq = it->it_seq;
2451-
if (seq == NULL || it->it_index >= PyList_GET_SIZE(seq)) {
2451+
if (seq == NULL) {
2452+
exhausted = Py_True;
2453+
}
2454+
else if (it->it_index >= PyList_GET_SIZE(seq)) {
2455+
Py_DECREF(seq);
2456+
it->it_seq = NULL;
24522457
exhausted = Py_True;
24532458
}
24542459
else {
@@ -2499,7 +2504,12 @@ dummy_func(
24992504
_PyTupleIterObject *it = (_PyTupleIterObject *)iter;
25002505
assert(Py_TYPE(iter) == &PyTupleIter_Type);
25012506
PyTupleObject *seq = it->it_seq;
2502-
if (seq == NULL || it->it_index >= PyTuple_GET_SIZE(seq)) {
2507+
if (seq == NULL) {
2508+
exhausted = Py_True;
2509+
}
2510+
else if (it->it_index >= PyTuple_GET_SIZE(seq)) {
2511+
Py_DECREF(seq);
2512+
it->it_seq = NULL;
25032513
exhausted = Py_True;
25042514
}
25052515
else {

Python/executor_cases.c.h

Lines changed: 12 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy