diff --git a/Lib/test/test_numeric_tower.py b/Lib/test/test_numeric_tower.py index 337682d6bac96c..7313c26c9fad84 100644 --- a/Lib/test/test_numeric_tower.py +++ b/Lib/test/test_numeric_tower.py @@ -226,5 +226,30 @@ 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 + + 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() 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. diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 7f5149aeece12b..c83c16d97a7f43 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -9714,13 +9714,26 @@ wrap_indexargfunc(PyObject *self, PyObject *args, void *wrapped) ssizeargfunc func = (ssizeargfunc)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); }