Skip to content

Commit

Permalink
pythongh-106529: Fix subtle Tier 2 edge case with list iterator (pyth…
Browse files Browse the repository at this point in the history
…on#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 pythongh-106696.

Added this as an explicit test.

Also fixed the dependencies for ceval.o -- it depends on executor_cases.c.h.
  • Loading branch information
gvanrossum committed Jul 15, 2023
1 parent 03185f0 commit 0db85ee
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 4 deletions.
13 changes: 13 additions & 0 deletions Lib/test/test_capi/test_misc.py
Expand Up @@ -2649,6 +2649,19 @@ def testfunc(a):
# Verification that the jump goes past END_FOR
# is done by manual inspection of the output

def test_list_edge_case(self):
def testfunc(it):
for x in it:
pass

opt = _testinternalcapi.get_uop_optimizer()
with temporary_optimizer(opt):
a = [1, 2, 3]
it = iter(a)
testfunc(it)
a.append(4)
with self.assertRaises(StopIteration):
next(it)

if __name__ == "__main__":
unittest.main()
1 change: 1 addition & 0 deletions Makefile.pre.in
Expand Up @@ -1564,6 +1564,7 @@ Python/ceval.o: \
$(srcdir)/Python/ceval_macros.h \
$(srcdir)/Python/condvar.h \
$(srcdir)/Python/generated_cases.c.h \
$(srcdir)/Python/executor_cases.c.h \
$(srcdir)/Include/internal/pycore_opcode_metadata.h \
$(srcdir)/Python/opcode_targets.h

Expand Down
14 changes: 12 additions & 2 deletions Python/bytecodes.c
Expand Up @@ -2448,7 +2448,12 @@ dummy_func(
_PyListIterObject *it = (_PyListIterObject *)iter;
assert(Py_TYPE(iter) == &PyListIter_Type);
PyListObject *seq = it->it_seq;
if (seq == NULL || it->it_index >= PyList_GET_SIZE(seq)) {
if (seq == NULL) {
exhausted = Py_True;
}
else if (it->it_index >= PyList_GET_SIZE(seq)) {
Py_DECREF(seq);
it->it_seq = NULL;
exhausted = Py_True;
}
else {
Expand Down Expand Up @@ -2499,7 +2504,12 @@ dummy_func(
_PyTupleIterObject *it = (_PyTupleIterObject *)iter;
assert(Py_TYPE(iter) == &PyTupleIter_Type);
PyTupleObject *seq = it->it_seq;
if (seq == NULL || it->it_index >= PyTuple_GET_SIZE(seq)) {
if (seq == NULL) {
exhausted = Py_True;
}
else if (it->it_index >= PyTuple_GET_SIZE(seq)) {
Py_DECREF(seq);
it->it_seq = NULL;
exhausted = Py_True;
}
else {
Expand Down
14 changes: 12 additions & 2 deletions Python/executor_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 0db85ee

Please sign in to comment.