8000 BUG: Fix reference counting · numpy/numpy@8c4e556 · GitHub
[go: up one dir, main page]

Skip to content

Commit 8c4e556

Browse files
committed
BUG: Fix reference counting
1 parent 3a0ad85 commit 8c4e556

File tree

1 file changed

+24
-5
lines changed

1 file changed

+24
-5
lines changed

numpy/core/src/multiarray/mapping.c

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,15 @@ PyArray_MapIterSwapAxes(PyArrayMapIterObject *mit, PyArrayObject **ret, int getm
139139
*ret = (PyArrayObject *)new;
140140
}
141141

142+
NPY_NO_EXPORT NPY_INLINE void
143+
multi_DECREF(PyObject **objects, npy_intp n)
144+
{
145+
npy_intp i;
146+
for (i = 0; i < n; i++) {
147+
Py_DECREF(objects[i]);
148+
}
149+
}
150+
142151
/**
143152
* Turn an index argument into a c-array of `PyObject *`s, one for each index.
144153
*
@@ -158,7 +167,7 @@ PyArray_MapIterSwapAxes(PyArrayMapIterObject *mit, PyArrayObject **ret, int getm
158167
* @param index The index object, which may or may not be a tuple. This is a
159168
* borrowed reference.
160169
* @param result An empty buffer of 2*NPY_MAXDIMS PyObject* to write each
161-
* index component to. The references written are borrowed.
170+
* index component to. The references written are new..
162171
* This function will in some cases clobber the array beyond
163172
* the last item unpacked.
164173
*
@@ -180,6 +189,7 @@ unpack_indices(PyObject *index, PyObject *result[2*NPY_MAXDIMS])
180189
}
181190
for (i = 0; i < n; i++) {
182191
result[i] = PyTuple_GET_ITEM(index, i);
192+
Py_INCREF(result[i]);
183193
}
184194
return n;
185195
}
@@ -196,6 +206,7 @@ unpack_indices(PyObject *index, PyObject *result[2*NPY_MAXDIMS])
196206
|| PyArray_Check(index)
197207
|| !PySequence_Check(index)) {
198208

209+
Py_INCREF(index);
199210
result[0] = index;
200211
return 1;
201212
}
@@ -214,8 +225,10 @@ unpack_indices(PyObject *index, PyObject *result[2*NPY_MAXDIMS])
214225
for (i = 0; i < n; i++) {
215226
result[i] = PySequence_GetItem(index, i);
216227
if (result[i] == NULL) {
228+
multi_DECREF(result, i);
217229
return -1;
218230
}
231+
Py_INCREF(result[i]);
219232
}
220233
return n;
221234
}
@@ -233,13 +246,15 @@ unpack_indices(PyObject *index, PyObject *result[2*NPY_MAXDIMS])
233246
n = PySequence_Size(index);
234247
if (n < 0) {
235248
PyErr_Clear();
249+
Py_INCREF(index);
236250
result[0] = index;
237251
return 1;
238252
}
239253

240254
/* for some reason, anything that's long but not too long is turned into
241255
* a single index. The *2 is missing here for backward-compatibility. */
242256
if (n >= NPY_MAXDIMS) {
257+
Py_INCREF(index);
243258
result[0] = index;
244259
return 1;
245260
}
@@ -253,13 +268,15 @@ unpack_indices(PyObject *index, PyObject *result[2*NPY_MAXDIMS])
253268
if (commit_to_unpack) {
254269
/* propagate errors */
255270
if (tmp_obj == NULL) {
271+
multi_DECREF(result, i);
256272
return -1;
257273
}
258274
}
259275
else {
260276
/* if getitem fails (unusual) before we've committed, then
261277
* commit to not unpacking */
262278
if (tmp_obj == NULL) {
279+
multi_DECREF(result, i);
263280
PyErr_Clear();
264281
break;
265282
}
@@ -273,18 +290,18 @@ unpack_indices(PyObject *index, PyObject *result[2*NPY_MAXDIMS])
273290
commit_to_unpack = 1;
274291
}
275292
}
276-
277-
Py_DECREF(tmp_obj);
278293
}
279294

280295
/* unpacking was the right thing to do, and we already did it */
281296
if (commit_to_unpack) {
282297
return n;
283298
}
284-
285299
/* got to the end, never found an indication that we should have unpacked */
286300
else {
287-
/* we already filled result, but it doesn't matter */
301+
/* we already filled result, so empty it first */
302+
multi_DECREF(result, n);
303+
304+
Py_INCREF(index);
288305
result[0] = index;
289306
return 1;
290307
}
@@ -757,13 +774,15 @@ prepare_index(PyArrayObject *self, PyObject *index,
757774
*ndim = new_ndim + fancy_ndim;
758775
*out_fancy_ndim = fancy_ndim;
759776

777+
multi_DECREF(raw_indices, index_ndim);
760778

761779
return index_type;
762780

763781
failed_building_indices:
764782
for (i=0; i < curr_idx; i++) {
765783
Py_XDECREF(indices[i].object);
766784
}
785+
multi_DECREF(raw_indices, index_ndim);
767786
return -1;
768787
}
769788

0 commit comments

Comments
 (0)
0