Skip to content

Commit decb25e

Browse files
priyanshu2282-cyberblurb-it[bot]ZeroIntensityvstinner
authored
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>
1 parent 9982147 commit decb25e

File tree

3 files changed

+34
-6
lines changed

3 files changed

+34
-6
lines changed

Lib/test/test_array.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,23 @@ def test_empty(self):
6767
a += a
6868
self.assertEqual(len(a), 0)
6969

70+
def test_fromlist_reentrant_index_mutation(self):
71+
72+
class Evil:
73+
def __init__(self, lst):
74+
self.lst = lst
75+
def __index__(self):
76+
self.lst.clear()
77+
return "not an int"
78+
79+
for typecode in ('I', 'L', 'Q'):
80+
with self.subTest(typecode=typecode):
81+
lst = []
82+
lst.append(Evil(lst))
83+
a = array.array(typecode)
84+
with self.assertRaises(TypeError):
85+
a.fromlist(lst)
86+
7087

7188
# Machine format codes.
7289
#
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix a crash in :meth:`array.array.fromlist` when an element's :meth:`~object.__index__` method mutates
2+
the input list during conversion.

Modules/arraymodule.c

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -408,10 +408,13 @@ II_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
408408
int do_decref = 0; /* if nb_int was called */
409409

410410
if (!PyLong_Check(v)) {
411-
v = _PyNumber_Index(v);
412-
if (NULL == v) {
411+
Py_INCREF(v);
412+
PyObject *res = _PyNumber_Index(v);
413+
Py_DECREF(v);
414+
if (NULL == res) {
413415
return -1;
414416
}
417+
v = res;
415418
do_decref = 1;
416419
}
417420
x = PyLong_AsUnsignedLong(v);
@@ -468,10 +471,13 @@ LL_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
468471
int do_decref = 0; /* if nb_int was called */
469472

470473
if (!PyLong_Check(v)) {
471-
v = _PyNumber_Index(v);
472-
if (NULL == v) {
474+
Py_INCREF(v);
475+
PyObject *res = _PyNumber_Index(v);
476+
Py_DECREF(v);
477+
if (NULL == res) {
473478
return -1;
474479
}
480+
v = res;
475481
do_decref = 1;
476482
}
477483
x = PyLong_AsUnsignedLong(v);
@@ -521,10 +527,13 @@ QQ_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
521527
int do_decref = 0; /* if nb_int was called */
522528

523529
if (!PyLong_Check(v)) {
524-
v = _PyNumber_Index(v);
525-
if (NULL == v) {
530+
Py_INCREF(v);
531+
PyObject *res = _PyNumber_Index(v);
532+
Py_DECREF(v);
533+
if (NULL == res) {
526534
return -1;
527535
}
536+
v = res;
528537
do_decref = 1;
529538
}
530539
x = PyLong_AsUnsignedLongLong(v);

0 commit comments

Comments
 (0)