From 520403ed4cdf4890d63403c9cf01ac63233f5ef4 Mon Sep 17 00:00:00 2001 From: Sam Gross Date: Tue, 20 Feb 2024 15:18:44 -0500 Subject: gh-115733: Fix crash involving exhausted list iterator (#115740) * gh-115733: Fix crash involving exhausted iterator * Add blurb --- Lib/test/list_tests.py | 5 +++++ .../2024-02-20-18-49-02.gh-issue-115733.51Zb85.rst | 1 + Objects/listobject.c | 6 +++--- Python/bytecodes.c | 3 ++- Python/executor_cases.c.h | 1 + Python/generated_cases.c.h | 2 +- 6 files changed, 13 insertions(+), 5 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2024-02-20-18-49-02.gh-issue-115733.51Zb85.rst diff --git a/Lib/test/list_tests.py b/Lib/test/list_tests.py index d9ab21d..26118e1 100644 --- a/Lib/test/list_tests.py +++ b/Lib/test/list_tests.py @@ -562,3 +562,8 @@ class CommonTest(seq_tests.CommonTest): 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 0000000..5cbb2920 --- /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 eb46626..b079702 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 9d790a9..5835b80 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 2ca54b6..974555c 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 01e67ac..7f46bc8 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) { -- cgit v0.12