mirror of
https://github.com/python/cpython.git
synced 2025-07-24 11:44:31 +00:00
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.
This commit is contained in:
parent
03185f0c15
commit
0db85eeba7
4 changed files with 38 additions and 4 deletions
|
@ -2649,6 +2649,19 @@ class TestUops(unittest.TestCase):
|
||||||
# Verification that the jump goes past END_FOR
|
# Verification that the jump goes past END_FOR
|
||||||
# is done by manual inspection of the output
|
# 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__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -1564,6 +1564,7 @@ Python/ceval.o: \
|
||||||
$(srcdir)/Python/ceval_macros.h \
|
$(srcdir)/Python/ceval_macros.h \
|
||||||
$(srcdir)/Python/condvar.h \
|
$(srcdir)/Python/condvar.h \
|
||||||
$(srcdir)/Python/generated_cases.c.h \
|
$(srcdir)/Python/generated_cases.c.h \
|
||||||
|
$(srcdir)/Python/executor_cases.c.h \
|
||||||
$(srcdir)/Include/internal/pycore_opcode_metadata.h \
|
$(srcdir)/Include/internal/pycore_opcode_metadata.h \
|
||||||
$(srcdir)/Python/opcode_targets.h
|
$(srcdir)/Python/opcode_targets.h
|
||||||
|
|
||||||
|
|
|
@ -2448,7 +2448,12 @@ dummy_func(
|
||||||
_PyListIterObject *it = (_PyListIterObject *)iter;
|
_PyListIterObject *it = (_PyListIterObject *)iter;
|
||||||
assert(Py_TYPE(iter) == &PyListIter_Type);
|
assert(Py_TYPE(iter) == &PyListIter_Type);
|
||||||
PyListObject *seq = it->it_seq;
|
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;
|
exhausted = Py_True;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -2499,7 +2504,12 @@ dummy_func(
|
||||||
_PyTupleIterObject *it = (_PyTupleIterObject *)iter;
|
_PyTupleIterObject *it = (_PyTupleIterObject *)iter;
|
||||||
assert(Py_TYPE(iter) == &PyTupleIter_Type);
|
assert(Py_TYPE(iter) == &PyTupleIter_Type);
|
||||||
PyTupleObject *seq = it->it_seq;
|
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;
|
exhausted = Py_True;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
14
Python/executor_cases.c.h
generated
14
Python/executor_cases.c.h
generated
|
@ -1750,7 +1750,12 @@
|
||||||
_PyListIterObject *it = (_PyListIterObject *)iter;
|
_PyListIterObject *it = (_PyListIterObject *)iter;
|
||||||
assert(Py_TYPE(iter) == &PyListIter_Type);
|
assert(Py_TYPE(iter) == &PyListIter_Type);
|
||||||
PyListObject *seq = it->it_seq;
|
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;
|
exhausted = Py_True;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -1787,7 +1792,12 @@
|
||||||
_PyTupleIterObject *it = (_PyTupleIterObject *)iter;
|
_PyTupleIterObject *it = (_PyTupleIterObject *)iter;
|
||||||
assert(Py_TYPE(iter) == &PyTupleIter_Type);
|
assert(Py_TYPE(iter) == &PyTupleIter_Type);
|
||||||
PyTupleObject *seq = it->it_seq;
|
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;
|
exhausted = Py_True;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue