summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2023-07-15 00:22:06 (GMT)
committerGitHub <noreply@github.com>2023-07-15 00:22:06 (GMT)
commit0db85eeba762e72f9f3c027e432cdebc627aac6c (patch)
treec69c2bdbb1a9986cfc5a454a1e4995f89241a51e
parent03185f0c150ebc52d41dd5ea6f369c7b5ba9fc16 (diff)
downloadcpython-0db85eeba762e72f9f3c027e432cdebc627aac6c.zip
cpython-0db85eeba762e72f9f3c027e432cdebc627aac6c.tar.gz
cpython-0db85eeba762e72f9f3c027e432cdebc627aac6c.tar.bz2
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.
-rw-r--r--Lib/test/test_capi/test_misc.py13
-rw-r--r--Makefile.pre.in1
-rw-r--r--Python/bytecodes.c14
-rw-r--r--Python/executor_cases.c.h14
4 files changed, 38 insertions, 4 deletions
diff --git a/Lib/test/test_capi/test_misc.py b/Lib/test/test_capi/test_misc.py
index 43c0446..6df9189 100644
--- a/Lib/test/test_capi/test_misc.py
+++ b/Lib/test/test_capi/test_misc.py
@@ -2649,6 +2649,19 @@ class TestUops(unittest.TestCase):
# 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()
diff --git a/Makefile.pre.in b/Makefile.pre.in
index ddf524a..553b2aa 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -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
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index 15b48ae..3432b02 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -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 {
@@ -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 {
diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h
index 626baec..ae21ffa 100644
--- a/Python/executor_cases.c.h
+++ b/Python/executor_cases.c.h
@@ -1750,7 +1750,12 @@
_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 {
@@ -1787,7 +1792,12 @@
_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 {