]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-144128: Fix crash in array.fromlist with reentrant __index__ (#144138)
authorPriyanshu Singh <priyanshu2282@gmail.com>
Mon, 26 Jan 2026 12:13:49 +0000 (17:43 +0530)
committerGitHub <noreply@github.com>
Mon, 26 Jan 2026 12:13:49 +0000 (13:13 +0100)
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>
Lib/test/test_array.py
Misc/NEWS.d/next/Library/2026-01-22-10-18-17.gh-issue-144128.akwY06.rst [new file with mode: 0644]
Modules/arraymodule.c

index 83b3c978da3581d6b4255b392174223fa0b9978a..b49df029f0326f7691a13c442c31e0b4d4323b36 100755 (executable)
@@ -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.
 #
diff --git a/Misc/NEWS.d/next/Library/2026-01-22-10-18-17.gh-issue-144128.akwY06.rst b/Misc/NEWS.d/next/Library/2026-01-22-10-18-17.gh-issue-144128.akwY06.rst
new file mode 100644 (file)
index 0000000..4010695
--- /dev/null
@@ -0,0 +1,2 @@
+Fix a crash in :meth:`array.array.fromlist` when an element's :meth:`~object.__index__` method mutates\r
+the input list during conversion.\r
index 729e085c19f006d01290b044ac924ae56ebd8ccf..5769a796b18902b8e8455e6d23485910ed994c56 100644 (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);