From 19e1acb1ee1a9e242865a5f8a7502dc609b709ef Mon Sep 17 00:00:00 2001 From: priyanshu2282-cyber Date: Tue, 13 Jan 2026 11:59:15 +0530 Subject: [PATCH 1/9] gh-142883: avoid calling stale numeric slot after __index__ --- Objects/typeobject.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 7f5149aeece12b..775f76dfbf04bf 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -9714,6 +9714,7 @@ wrap_indexargfunc(PyObject *self, PyObject *args, void *wrapped) ssizeargfunc func = (ssizeargfunc)wrapped; PyObject* o; Py_ssize_t i; + PyTypeObject *type_before = Py_TYPE(self); if (!check_num_args(args, 1)) return NULL; @@ -9721,6 +9722,11 @@ wrap_indexargfunc(PyObject *self, PyObject *args, void *wrapped) i = PyNumber_AsSsize_t(o, PyExc_OverflowError); if (i == -1 && PyErr_Occurred()) return NULL; + if (Py_TYPE(self) != type_before) { + PyErr_SetString(PyExc_TypeError, + "object mutated during numeric operation"); + return NULL; + } return (*func)(self, i); } From f41021e2908c2f08fdc5dcbb1c27357d835916f1 Mon Sep 17 00:00:00 2001 From: priyanshu2282-cyber Date: Tue, 13 Jan 2026 12:00:14 +0530 Subject: [PATCH 2/9] test_numeric_tower: add regression test for __index__ mutation --- Lib/test/test_numeric_tower.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/Lib/test/test_numeric_tower.py b/Lib/test/test_numeric_tower.py index 337682d6bac96c..fe4d08e0b04716 100644 --- a/Lib/test/test_numeric_tower.py +++ b/Lib/test/test_numeric_tower.py @@ -225,6 +225,29 @@ def test_complex(self): self.assertRaises(TypeError, op, z, v) self.assertRaises(TypeError, op, v, z) +class IndexMutationDuringNumericOpTest(unittest.TestCase): + + def test_index_mutates_lhs_type_during_operation(self): + import array + class Good(array.array): + pass + + class Hide(type): + def mro(cls): + return (cls, object) + + class Bad(Good, metaclass=Hide): + pass + + arr = Good('b', b'x') + + class Count: + def __index__(self): + arr.__class__ = Bad + return 2 + + with self.assertRaises(TypeError): + arr * Count() if __name__ == '__main__': unittest.main() From c70d8a878c0e7a78242efe1a2199c26e1d2620f4 Mon Sep 17 00:00:00 2001 From: priyanshu2282-cyber Date: Tue, 13 Jan 2026 12:24:54 +0530 Subject: [PATCH 3/9] NEWS: fix crash when __index__ changes array class --- .../next/Core_and_Builtins/2026-01-13-array-index-crash.rst | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-01-13-array-index-crash.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-13-array-index-crash.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-01-13-array-index-crash.rst new file mode 100644 index 00000000000000..0c662ced800b52 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-01-13-array-index-crash.rst @@ -0,0 +1,3 @@ +Fixed a crash during array multiplication when __index__ changes the array’s +class while the operation is in progress. + From fc92210451fb047412b5225c7e72143ec9bc49c0 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Tue, 13 Jan 2026 07:08:21 +0000 Subject: [PATCH 4/9] =?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 --- .../2026-01-13-07-08-20.gh-issue-142883.Ko9RA-.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-01-13-07-08-20.gh-issue-142883.Ko9RA-.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-13-07-08-20.gh-issue-142883.Ko9RA-.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-01-13-07-08-20.gh-issue-142883.Ko9RA-.rst new file mode 100644 index 00000000000000..eb61d27b157038 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-01-13-07-08-20.gh-issue-142883.Ko9RA-.rst @@ -0,0 +1,2 @@ +Fixed a crash during array multiplication when ``__index__`` changes the +array’s class while the operation is in progress. From 4ad938d49d4a2ba2b1ec82e83f4a015bf3a7b81d Mon Sep 17 00:00:00 2001 From: priyanshu2282-cyber Date: Tue, 13 Jan 2026 12:40:51 +0530 Subject: [PATCH 5/9] NEWS: remove manually added entry --- .../next/Core_and_Builtins/2026-01-13-array-index-crash.rst | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-01-13-array-index-crash.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-13-array-index-crash.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-01-13-array-index-crash.rst deleted file mode 100644 index 0c662ced800b52..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-13-array-index-crash.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fixed a crash during array multiplication when __index__ changes the array’s -class while the operation is in progress. - From e444a1fb91fe0c5cc56fc791da77addaf9480868 Mon Sep 17 00:00:00 2001 From: priyanshu2282-cyber Date: Tue, 13 Jan 2026 13:33:52 +0530 Subject: [PATCH 6/9] Fix trailing whitespace in test_numeric_tower --- Lib/test/test_numeric_tower.py | 1 - 1 file changed, 1 deletion(-) diff --git a/Lib/test/test_numeric_tower.py b/Lib/test/test_numeric_tower.py index fe4d08e0b04716..f3c0254dd508f9 100644 --- a/Lib/test/test_numeric_tower.py +++ b/Lib/test/test_numeric_tower.py @@ -226,7 +226,6 @@ def test_complex(self): self.assertRaises(TypeError, op, v, z) class IndexMutationDuringNumericOpTest(unittest.TestCase): - def test_index_mutates_lhs_type_during_operation(self): import array From 5db847766cb07b76994f4c529ffa13f69acbbad2 Mon Sep 17 00:00:00 2001 From: Priyanshu Singh Date: Tue, 13 Jan 2026 19:52:14 +0530 Subject: [PATCH 7/9] Update Lib/test/test_numeric_tower.py Co-authored-by: AN Long --- Lib/test/test_numeric_tower.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Lib/test/test_numeric_tower.py b/Lib/test/test_numeric_tower.py index f3c0254dd508f9..78e37945e641ba 100644 --- a/Lib/test/test_numeric_tower.py +++ b/Lib/test/test_numeric_tower.py @@ -225,6 +225,7 @@ def test_complex(self): self.assertRaises(TypeError, op, z, v) self.assertRaises(TypeError, op, v, z) + class IndexMutationDuringNumericOpTest(unittest.TestCase): def test_index_mutates_lhs_type_during_operation(self): import array From 4b1f1ac2fd9ddd9908e4b6a84aa27c61b3ce4372 Mon Sep 17 00:00:00 2001 From: Priyanshu Singh Date: Tue, 13 Jan 2026 19:52:47 +0530 Subject: [PATCH 8/9] Update Lib/test/test_numeric_tower.py Co-authored-by: AN Long --- Lib/test/test_numeric_tower.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Lib/test/test_numeric_tower.py b/Lib/test/test_numeric_tower.py index 78e37945e641ba..7313c26c9fad84 100644 --- a/Lib/test/test_numeric_tower.py +++ b/Lib/test/test_numeric_tower.py @@ -249,5 +249,7 @@ def __index__(self): with self.assertRaises(TypeError): arr * Count() + + if __name__ == '__main__': unittest.main() From a610d9f38b906c0066e6b07ca71c7414e4759808 Mon Sep 17 00:00:00 2001 From: priyanshu2282-cyber Date: Tue, 13 Jan 2026 22:08:49 +0530 Subject: [PATCH 9/9] INCREF type before calling __index__ --- Objects/typeobject.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 775f76dfbf04bf..c83c16d97a7f43 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -9715,18 +9715,25 @@ wrap_indexargfunc(PyObject *self, PyObject *args, void *wrapped) PyObject* o; Py_ssize_t i; PyTypeObject *type_before = Py_TYPE(self); + Py_INCREF(type_before); - if (!check_num_args(args, 1)) + if (!check_num_args(args, 1)){ + Py_DECREF(type_before); return NULL; + } o = PyTuple_GET_ITEM(args, 0); i = PyNumber_AsSsize_t(o, PyExc_OverflowError); - if (i == -1 && PyErr_Occurred()) + if (i == -1 && PyErr_Occurred()){ + Py_DECREF(type_before); return NULL; + } if (Py_TYPE(self) != type_before) { + Py_DECREF(type_before); PyErr_SetString(PyExc_TypeError, "object mutated during numeric operation"); return NULL; } + Py_DECREF(type_before); return (*func)(self, i); }