gh-144128: Fix crash in array.fromlist with reentrant __index__ (#144138)

Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
Co-authored-by: Peter Bierma <zintensitydev@gmail.com>
Co-authored-by: Victor Stinner <vstinner@python.org>
This commit is contained in:
Priyanshu Singh 2026-01-26 17:43:49 +05:30 committed by GitHub
parent 9982147433
commit decb25e8f0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 34 additions and 6 deletions

View File

@ -67,6 +67,23 @@ class MiscTest(unittest.TestCase):
a += a
self.assertEqual(len(a), 0)
def test_fromlist_reentrant_index_mutation(self):
class Evil:
def __init__(self, lst):
self.lst = lst
def __index__(self):
self.lst.clear()
return "not an int"
for typecode in ('I', 'L', 'Q'):
with self.subTest(typecode=typecode):
lst = []
lst.append(Evil(lst))
a = array.array(typecode)
with self.assertRaises(TypeError):
a.fromlist(lst)
# Machine format codes.
#

View File

@ -0,0 +1,2 @@
Fix a crash in :meth:`array.array.fromlist` when an element's :meth:`~object.__index__` method mutates
the input list during conversion.

View File

@ -408,10 +408,13 @@ II_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
int do_decref = 0; /* if nb_int was called */
if (!PyLong_Check(v)) {
v = _PyNumber_Index(v);
if (NULL == v) {
Py_INCREF(v);
PyObject *res = _PyNumber_Index(v);
Py_DECREF(v);
if (NULL == res) {
return -1;
}
v = res;
do_decref = 1;
}
x = PyLong_AsUnsignedLong(v);
@ -468,10 +471,13 @@ LL_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
int do_decref = 0; /* if nb_int was called */
if (!PyLong_Check(v)) {
v = _PyNumber_Index(v);
if (NULL == v) {
Py_INCREF(v);
PyObject *res = _PyNumber_Index(v);
Py_DECREF(v);
if (NULL == res) {
return -1;
}
v = res;
do_decref = 1;
}
x = PyLong_AsUnsignedLong(v);
@ -521,10 +527,13 @@ QQ_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
int do_decref = 0; /* if nb_int was called */
if (!PyLong_Check(v)) {
v = _PyNumber_Index(v);
if (NULL == v) {
Py_INCREF(v);
PyObject *res = _PyNumber_Index(v);
Py_DECREF(v);
if (NULL == res) {
return -1;
}
v = res;
do_decref = 1;
}
x = PyLong_AsUnsignedLongLong(v);