https://github.com/python/cpython/commit/520403ed4cdf4890d63403c9cf01ac63233f5ef4
commit: 520403ed4cdf4890d63403c9cf01ac63233f5ef4
branch: main
author: Sam Gross <[email protected]>
committer: corona10 <[email protected]>
date: 2024-02-21T05:18:44+09:00
summary:

gh-115733: Fix crash involving exhausted list iterator (#115740)

* gh-115733: Fix crash involving exhausted iterator

* Add blurb

files:
A Misc/NEWS.d/next/Core and 
Builtins/2024-02-20-18-49-02.gh-issue-115733.51Zb85.rst
M Lib/test/list_tests.py
M Objects/listobject.c
M Python/bytecodes.c
M Python/executor_cases.c.h
M Python/generated_cases.c.h

diff --git a/Lib/test/list_tests.py b/Lib/test/list_tests.py
index d9ab21d4941cdb..26118e14bb97e0 100644
--- a/Lib/test/list_tests.py
+++ b/Lib/test/list_tests.py
@@ -562,3 +562,8 @@ def test_exhausted_iterator(self):
         self.assertEqual(list(exhit), [])
         self.assertEqual(list(empit), [9])
         self.assertEqual(a, self.type2test([1, 2, 3, 9]))
+
+        # gh-115733: Crash when iterating over exhausted iterator
+        exhit = iter(self.type2test([1, 2, 3]))
+        for _ in exhit:
+            next(exhit, 1)
diff --git a/Misc/NEWS.d/next/Core and 
Builtins/2024-02-20-18-49-02.gh-issue-115733.51Zb85.rst b/Misc/NEWS.d/next/Core 
and Builtins/2024-02-20-18-49-02.gh-issue-115733.51Zb85.rst
new file mode 100644
index 00000000000000..5cbb292065b5da
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and 
Builtins/2024-02-20-18-49-02.gh-issue-115733.51Zb85.rst 
@@ -0,0 +1 @@
+Fix crash when calling ``next()`` on exhausted list iterators.
diff --git a/Objects/listobject.c b/Objects/listobject.c
index eb466260318ec1..b07970298b8a00 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -3537,13 +3537,13 @@ listreviter_next(PyObject *self)
 {
     listreviterobject *it = (listreviterobject *)self;
     assert(it != NULL);
-    PyListObject *seq = it->it_seq;
-    assert(PyList_Check(seq));
-
     Py_ssize_t index = LOAD_SSIZE(it->it_index);
     if (index < 0) {
         return NULL;
     }
+
+    PyListObject *seq = it->it_seq;
+    assert(PyList_Check(seq));
     PyObject *item = list_get_item_ref(seq, index);
     if (item != NULL) {
         STORE_SSIZE(it->it_index, index - 1);
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index 9d790a9d3e6577..5835b80582b3bc 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -2612,7 +2612,7 @@ dummy_func(
             assert(Py_TYPE(iter) == &PyListIter_Type);
             STAT_INC(FOR_ITER, hit);
             PyListObject *seq = it->it_seq;
-            if ((size_t)it->it_index >= (size_t)PyList_GET_SIZE(seq)) {
+            if (seq == NULL || (size_t)it->it_index >= 
(size_t)PyList_GET_SIZE(seq)) {
                 it->it_index = -1;
                 #ifndef Py_GIL_DISABLED
                 if (seq != NULL) {
@@ -2633,6 +2633,7 @@ dummy_func(
             _PyListIterObject *it = (_PyListIterObject *)iter;
             assert(Py_TYPE(iter) == &PyListIter_Type);
             PyListObject *seq = it->it_seq;
+            DEOPT_IF(seq == NULL);
             DEOPT_IF((size_t)it->it_index >= (size_t)PyList_GET_SIZE(seq));
         }
 
diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h
index 2ca54b6fe9cd38..974555cbba9dd6 100644
--- a/Python/executor_cases.c.h
+++ b/Python/executor_cases.c.h
@@ -2427,6 +2427,7 @@
             _PyListIterObject *it = (_PyListIterObject *)iter;
             assert(Py_TYPE(iter) == &PyListIter_Type);
             PyListObject *seq = it->it_seq;
+            if (seq == NULL) goto deoptimize;
             if ((size_t)it->it_index >= (size_t)PyList_GET_SIZE(seq)) goto 
deoptimize;
             break;
         }
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index 01e67acdc5c0e5..7f46bc8916c8d8 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -2560,7 +2560,7 @@
                 assert(Py_TYPE(iter) == &PyListIter_Type);
                 STAT_INC(FOR_ITER, hit);
                 PyListObject *seq = it->it_seq;
-                if ((size_t)it->it_index >= (size_t)PyList_GET_SIZE(seq)) {
+                if (seq == NULL || (size_t)it->it_index >= 
(size_t)PyList_GET_SIZE(seq)) {
                     it->it_index = -1;
                     #ifndef Py_GIL_DISABLED
                     if (seq != NULL) {

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to