From 7831074d519212f2d68d4fea7d355f4fdd1b9436 Mon Sep 17 00:00:00 2001 From: Tomasz Pytel Date: Fri, 17 Jan 2025 16:29:48 -0500 Subject: [PATCH 1/7] gh-128961: fix array iterator segfault on __setstate__ --- Lib/test/test_array.py | 6 ++++++ Modules/arraymodule.c | 13 ++++++++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_array.py b/Lib/test/test_array.py index f621f343eb062a..c8044dcfa7f9d1 100755 --- a/Lib/test/test_array.py +++ b/Lib/test/test_array.py @@ -1665,5 +1665,11 @@ def test_tolist(self, size): self.assertEqual(ls[:8], list(example[:8])) self.assertEqual(ls[-8:], list(example[-8:])) + def test_gh_128961(self): + a = array.array('i') + it = iter(a) + list(it) + it.__setstate__(0) + if __name__ == "__main__": unittest.main() diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index b80c964f20d65e..cfab5912314e7a 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -3090,11 +3090,14 @@ array_arrayiterator___setstate__(arrayiterobject *self, PyObject *state) Py_ssize_t index = PyLong_AsSsize_t(state); if (index == -1 && PyErr_Occurred()) return NULL; - if (index < 0) - index = 0; - else if (index > Py_SIZE(self->ao)) - index = Py_SIZE(self->ao); /* iterator exhausted */ - self->index = index; + arrayobject *ao = self->ao; + // if (ao != NULL) { + if (index < 0) + index = 0; + else if (index > Py_SIZE(ao)) + index = Py_SIZE(ao); /* iterator exhausted */ + self->index = index; + // } Py_RETURN_NONE; } From 3975683a43c71b0a3571bba1bed0ed1ae393e13e Mon Sep 17 00:00:00 2001 From: Tomasz Pytel Date: Fri, 17 Jan 2025 16:32:25 -0500 Subject: [PATCH 2/7] oops --- Modules/arraymodule.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index cfab5912314e7a..88f19cba75a9ef 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -3091,13 +3091,13 @@ array_arrayiterator___setstate__(arrayiterobject *self, PyObject *state) if (index == -1 && PyErr_Occurred()) return NULL; arrayobject *ao = self->ao; - // if (ao != NULL) { + if (ao != NULL) { if (index < 0) index = 0; else if (index > Py_SIZE(ao)) index = Py_SIZE(ao); /* iterator exhausted */ self->index = index; - // } + } Py_RETURN_NONE; } From 3f9bd66522ad7afb3aef2701a9aaba86f15b46d4 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Fri, 17 Jan 2025 21:33:12 +0000 Subject: [PATCH 3/7] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Library/2025-01-17-21-33-11.gh-issue-128961.XwvyIZ.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2025-01-17-21-33-11.gh-issue-128961.XwvyIZ.rst diff --git a/Misc/NEWS.d/next/Library/2025-01-17-21-33-11.gh-issue-128961.XwvyIZ.rst b/Misc/NEWS.d/next/Library/2025-01-17-21-33-11.gh-issue-128961.XwvyIZ.rst new file mode 100644 index 00000000000000..8291fb156a86a7 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-01-17-21-33-11.gh-issue-128961.XwvyIZ.rst @@ -0,0 +1 @@ +fix crash on array iterator when setting state when exhausted From e7f00dc0bbbe40c864d646c87b0bdc72f39f9d2f Mon Sep 17 00:00:00 2001 From: Tomasz Pytel Date: Fri, 17 Jan 2025 16:57:11 -0500 Subject: [PATCH 4/7] nit picked --- Modules/arraymodule.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index 88f19cba75a9ef..fdbb0f0e8d6691 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -3092,10 +3092,12 @@ array_arrayiterator___setstate__(arrayiterobject *self, PyObject *state) return NULL; arrayobject *ao = self->ao; if (ao != NULL) { - if (index < 0) + if (index < 0) { index = 0; - else if (index > Py_SIZE(ao)) + } + else if (index > Py_SIZE(ao)) { index = Py_SIZE(ao); /* iterator exhausted */ + } self->index = index; } Py_RETURN_NONE; From d6610b77716c71b07eaf8cc6b79d5156df1321ea Mon Sep 17 00:00:00 2001 From: Tomasz Pytel Date: Fri, 17 Jan 2025 17:08:33 -0500 Subject: [PATCH 5/7] upgrade words --- .../next/Library/2025-01-17-21-33-11.gh-issue-128961.XwvyIZ.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2025-01-17-21-33-11.gh-issue-128961.XwvyIZ.rst b/Misc/NEWS.d/next/Library/2025-01-17-21-33-11.gh-issue-128961.XwvyIZ.rst index 8291fb156a86a7..9c985df77743da 100644 --- a/Misc/NEWS.d/next/Library/2025-01-17-21-33-11.gh-issue-128961.XwvyIZ.rst +++ b/Misc/NEWS.d/next/Library/2025-01-17-21-33-11.gh-issue-128961.XwvyIZ.rst @@ -1 +1 @@ -fix crash on array iterator when setting state when exhausted +Fix a crash when setting state on an exhausted :class:`array.array` iterator. From 8eab735e46d3ad83d78fb57c1427055a0f588a49 Mon Sep 17 00:00:00 2001 From: Tomasz Pytel Date: Fri, 17 Jan 2025 18:05:27 -0500 Subject: [PATCH 6/7] test raise StopIteration after gh-128961 --- Lib/test/test_array.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Lib/test/test_array.py b/Lib/test/test_array.py index c8044dcfa7f9d1..862c3836988cef 100755 --- a/Lib/test/test_array.py +++ b/Lib/test/test_array.py @@ -1670,6 +1670,7 @@ def test_gh_128961(self): it = iter(a) list(it) it.__setstate__(0) + self.assertRaises(StopIteration, lambda: next(it)) if __name__ == "__main__": unittest.main() From 2accb876df0083c55207e6e19f8f05ce7c584ed6 Mon Sep 17 00:00:00 2001 From: Tomasz Pytel Date: Fri, 17 Jan 2025 18:17:58 -0500 Subject: [PATCH 7/7] requested tweaks --- Lib/test/test_array.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_array.py b/Lib/test/test_array.py index 862c3836988cef..58ea89c4fac833 100755 --- a/Lib/test/test_array.py +++ b/Lib/test/test_array.py @@ -1670,7 +1670,8 @@ def test_gh_128961(self): it = iter(a) list(it) it.__setstate__(0) - self.assertRaises(StopIteration, lambda: next(it)) + self.assertRaises(StopIteration, next, it) + if __name__ == "__main__": unittest.main()