Skip to content

Commit

Permalink
BUG: Fix ticket #1588/gh issue #398, refcount error in clip
Browse files Browse the repository at this point in the history
This patch enforces a strict dichotomy for the variables 'indescr'
and 'newdescr', so they are either NULL, or they own a reference.
Following the consequences of this allowed the reference error
to be tracked down.
  • Loading branch information
mwiebe authored and certik committed Sep 12, 2012
1 parent f65ff87 commit 7b5dba0
Showing 1 changed file with 17 additions and 9 deletions.
26 changes: 17 additions & 9 deletions numpy/core/src/multiarray/calculation.c
Expand Up @@ -895,7 +895,7 @@ PyArray_Clip(PyArrayObject *self, PyObject *min, PyObject *max, PyArrayObject *o
PyArrayObject *maxa = NULL;
PyArrayObject *mina = NULL;
PyArrayObject *newout = NULL, *newin = NULL;
PyArray_Descr *indescr, *newdescr;
PyArray_Descr *indescr = NULL, *newdescr = NULL;
char *max_data, *min_data;
PyObject *zero;

Expand All @@ -922,23 +922,24 @@ PyArray_Clip(PyArrayObject *self, PyObject *min, PyObject *max, PyArrayObject *o
/* Use the fast scalar clip function */

/* First we need to figure out the correct type */
indescr = NULL;
if (min != NULL) {
indescr = PyArray_DescrFromObject(min, NULL);
if (indescr == NULL) {
return NULL;
goto fail;
}
}
if (max != NULL) {
newdescr = PyArray_DescrFromObject(max, indescr);
Py_XDECREF(indescr);
indescr = NULL;
if (newdescr == NULL) {
return NULL;
goto fail;
}
}
else {
/* Steal the reference */
newdescr = indescr;
indescr = NULL;
}


Expand All @@ -950,8 +951,12 @@ PyArray_Clip(PyArrayObject *self, PyObject *min, PyObject *max, PyArrayObject *o
if (PyArray_ScalarKind(newdescr->type_num, NULL) >
PyArray_ScalarKind(PyArray_DESCR(self)->type_num, NULL)) {
indescr = PyArray_PromoteTypes(newdescr, PyArray_DESCR(self));
if (indescr == NULL) {
goto fail;
}
func = indescr->f->fastclip;
if (func == NULL) {
Py_DECREF(indescr);
return _slow_array_clip(self, min, max, out);
}
}
Expand All @@ -960,11 +965,13 @@ PyArray_Clip(PyArrayObject *self, PyObject *min, PyObject *max, PyArrayObject *o
Py_INCREF(indescr);
}
Py_DECREF(newdescr);
newdescr = NULL;

if (!PyDataType_ISNOTSWAPPED(indescr)) {
PyArray_Descr *descr2;
descr2 = PyArray_DescrNewByteorder(indescr, '=');
Py_DECREF(indescr);
indescr = NULL;
if (descr2 == NULL) {
goto fail;
}
Expand All @@ -973,16 +980,13 @@ PyArray_Clip(PyArrayObject *self, PyObject *min, PyObject *max, PyArrayObject *o

/* Convert max to an array */
if (max != NULL) {
Py_INCREF(indescr);
maxa = (PyArrayObject *)PyArray_FromAny(max, indescr, 0, 0,
NPY_ARRAY_DEFAULT, NULL);
if (maxa == NULL) {
return NULL;
goto fail;
}
}
else {
/* Side-effect of PyArray_FromAny */
Py_DECREF(indescr);
}

/*
* If we are unsigned, then make sure min is not < 0
Expand Down Expand Up @@ -1147,6 +1151,8 @@ PyArray_Clip(PyArrayObject *self, PyObject *min, PyObject *max, PyArrayObject *o
func(PyArray_DATA(newin), PyArray_SIZE(newin), min_data, max_data, PyArray_DATA(newout));

/* Clean up temporary variables */
Py_XDECREF(indescr);
Py_XDECREF(newdescr);
Py_XDECREF(mina);
Py_XDECREF(maxa);
Py_DECREF(newin);
Expand All @@ -1155,6 +1161,8 @@ PyArray_Clip(PyArrayObject *self, PyObject *min, PyObject *max, PyArrayObject *o
return (PyObject *)out;

fail:
Py_XDECREF(indescr);
Py_XDECREF(newdescr);
Py_XDECREF(maxa);
Py_XDECREF(mina);
Py_XDECREF(newin);
Expand Down

0 comments on commit 7b5dba0

Please sign in to comment.