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

* gh-115733: Fix crash involving exhausted iterator

* Add blurb
This commit is contained in:
Sam Gross 2024-02-20 15:18:44 -05:00 committed by GitHub
parent 494739e1f7
commit 520403ed4c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 13 additions and 5 deletions

View File

@ -562,3 +562,8 @@ class CommonTest(seq_tests.CommonTest):
self.assertEqual(list(exhit), []) self.assertEqual(list(exhit), [])
self.assertEqual(list(empit), [9]) self.assertEqual(list(empit), [9])
self.assertEqual(a, self.type2test([1, 2, 3, 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)

View File

@ -0,0 +1 @@
Fix crash when calling ``next()`` on exhausted list iterators.

View File

@ -3537,13 +3537,13 @@ listreviter_next(PyObject *self)
{ {
listreviterobject *it = (listreviterobject *)self; listreviterobject *it = (listreviterobject *)self;
assert(it != NULL); assert(it != NULL);
PyListObject *seq = it->it_seq;
assert(PyList_Check(seq));
Py_ssize_t index = LOAD_SSIZE(it->it_index); Py_ssize_t index = LOAD_SSIZE(it->it_index);
if (index < 0) { if (index < 0) {
return NULL; return NULL;
} }
PyListObject *seq = it->it_seq;
assert(PyList_Check(seq));
PyObject *item = list_get_item_ref(seq, index); PyObject *item = list_get_item_ref(seq, index);
if (item != NULL) { if (item != NULL) {
STORE_SSIZE(it->it_index, index - 1); STORE_SSIZE(it->it_index, index - 1);

View File

@ -2612,7 +2612,7 @@ dummy_func(
assert(Py_TYPE(iter) == &PyListIter_Type); assert(Py_TYPE(iter) == &PyListIter_Type);
STAT_INC(FOR_ITER, hit); STAT_INC(FOR_ITER, hit);
PyListObject *seq = it->it_seq; 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; it->it_index = -1;
#ifndef Py_GIL_DISABLED #ifndef Py_GIL_DISABLED
if (seq != NULL) { if (seq != NULL) {
@ -2633,6 +2633,7 @@ 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;
DEOPT_IF(seq == NULL);
DEOPT_IF((size_t)it->it_index >= (size_t)PyList_GET_SIZE(seq)); DEOPT_IF((size_t)it->it_index >= (size_t)PyList_GET_SIZE(seq));
} }

View File

@ -2427,6 +2427,7 @@
_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) goto deoptimize;
if ((size_t)it->it_index >= (size_t)PyList_GET_SIZE(seq)) goto deoptimize; if ((size_t)it->it_index >= (size_t)PyList_GET_SIZE(seq)) goto deoptimize;
break; break;
} }

View File

@ -2560,7 +2560,7 @@
assert(Py_TYPE(iter) == &PyListIter_Type); assert(Py_TYPE(iter) == &PyListIter_Type);
STAT_INC(FOR_ITER, hit); STAT_INC(FOR_ITER, hit);
PyListObject *seq = it->it_seq; 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; it->it_index = -1;
#ifndef Py_GIL_DISABLED #ifndef Py_GIL_DISABLED
if (seq != NULL) { if (seq != NULL) {