Skip to content

Commit 3f38914

Browse files
Fix crash in array.fromlist with reentrant __index__
1 parent 6181b69 commit 3f38914

2 files changed

Lines changed: 28 additions & 0 deletions

File tree

Lib/test/test_array.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,25 @@ 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+
lst = []
81+
e = Evil(lst)
82+
lst.append(e)
83+
del e
84+
a = array.array(typecode)
85+
with self.assertRaises(TypeError):
86+
a.fromlist(lst)
87+
88+
7089

7190
# Machine format codes.
7291
#

Modules/arraymodule.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,10 @@ 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+
PyObject *orig_v = v;
412+
Py_INCREF(orig_v);
411413
v = _PyNumber_Index(v);
414+
Py_DECREF(orig_v);
412415
if (NULL == v) {
413416
return -1;
414417
}
@@ -468,7 +471,10 @@ 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)) {
474+
PyObject *orig_v = v;
475+
Py_INCREF(orig_v);
471476
v = _PyNumber_Index(v);
477+
Py_DECREF(orig_v);
472478
if (NULL == v) {
473479
return -1;
474480
}
@@ -521,7 +527,10 @@ 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)) {
530+
PyObject *orig_v = v;
531+
Py_INCREF(orig_v);
524532
v = _PyNumber_Index(v);
533+
Py_DECREF(orig_v);
525534
if (NULL == v) {
526535
return -1;
527536
}

0 commit comments

Comments
 (0)