diff options
author | Sebastian Berg <sebastian@sipsolutions.net> | 2013-10-24 02:22:48 +0200 |
---|---|---|
committer | Sebastian Berg <sebastian@sipsolutions.net> | 2013-10-24 02:36:01 +0200 |
commit | 6e5f0c1231af4958acfa8aa4cf3dfea404acbe9c (patch) | |
tree | dfeb77e6ab1931d4701ed75d55172fff0c90190b /numpy/core | |
parent | 77ecefbbae4892f45ffed0119ca3dab28a4d1f65 (diff) | |
download | numpy-6e5f0c1231af4958acfa8aa4cf3dfea404acbe9c.tar.gz |
MAINT|BUG: Some small refcounting fixes
Diffstat (limited to 'numpy/core')
-rw-r--r-- | numpy/core/src/multiarray/nditer_constr.c | 37 | ||||
-rw-r--r-- | numpy/core/src/multiarray/number.c | 5 | ||||
-rw-r--r-- | numpy/core/src/umath/test_rational.c.src | 3 | ||||
-rw-r--r-- | numpy/core/tests/test_regression.py | 10 |
4 files changed, 32 insertions, 23 deletions
diff --git a/numpy/core/src/multiarray/nditer_constr.c b/numpy/core/src/multiarray/nditer_constr.c index 1b2708619..a12457a1e 100644 --- a/numpy/core/src/multiarray/nditer_constr.c +++ b/numpy/core/src/multiarray/nditer_constr.c @@ -1161,11 +1161,7 @@ npyiter_prepare_operands(int nop, PyArrayObject **op_in, /* Check the readonly/writeonly flags, and fill in op_itflags */ if (!npyiter_check_per_op_flags(op_flags[iop], &op_itflags[iop])) { - for (i = 0; i <= iop; ++i) { - Py_XDECREF(op[i]); - Py_XDECREF(op_dtype[i]); - } - return 0; + goto fail_iop; } /* Extract the operand which is for masked iteration */ @@ -1174,11 +1170,7 @@ npyiter_prepare_operands(int nop, PyArrayObject **op_in, PyErr_SetString(PyExc_ValueError, "Only one iterator operand may receive an " "ARRAYMASK flag"); - for (i = 0; i <= iop; ++i) { - Py_XDECREF(op[i]); - Py_XDECREF(op_dtype[i]); - } - return 0; + goto fail_iop; } maskop = iop; @@ -1199,11 +1191,7 @@ npyiter_prepare_operands(int nop, PyArrayObject **op_in, &op_dtype[iop], flags, op_flags[iop], &op_itflags[iop])) { - for (i = 0; i <= iop; ++i) { - Py_XDECREF(op[i]); - Py_XDECREF(op_dtype[i]); - } - return 0; + goto fail_iop; } } @@ -1217,13 +1205,9 @@ npyiter_prepare_operands(int nop, PyArrayObject **op_in, } } if (all_null) { - for (i = 0; i < nop; ++i) { - Py_XDECREF(op[i]); - Py_XDECREF(op_dtype[i]); - } PyErr_SetString(PyExc_ValueError, "At least one iterator operand must be non-NULL"); - return 0; + goto fail_nop; } } @@ -1232,17 +1216,26 @@ npyiter_prepare_operands(int nop, PyArrayObject **op_in, "An iterator operand was flagged as WRITEMASKED, " "but no ARRAYMASK operand was given to supply " "the mask"); - return 0; + goto fail_nop; } else if (!any_writemasked_ops && maskop >= 0) { PyErr_SetString(PyExc_ValueError, "An iterator operand was flagged as the ARRAYMASK, " "but no WRITEMASKED operands were given to use " "the mask"); - return 0; + goto fail_nop; } return 1; + + fail_nop: + iop = nop; + fail_iop: + for (i = 0; i < iop; ++i) { + Py_XDECREF(op[i]); + Py_XDECREF(op_dtype[i]); + } + return 0; } static const char * diff --git a/numpy/core/src/multiarray/number.c b/numpy/core/src/multiarray/number.c index 2ad65bbe8..c8a7c9c7e 100644 --- a/numpy/core/src/multiarray/number.c +++ b/numpy/core/src/multiarray/number.c @@ -771,6 +771,7 @@ array_int(PyArrayObject *v) PyDataType_REFCHK(PyArray_DESCR((PyArrayObject *)pv))) { PyErr_SetString(PyExc_TypeError, "object array may be self-referencing"); + Py_DECREF(pv); return NULL; } @@ -812,6 +813,7 @@ array_float(PyArrayObject *v) PyDataType_REFCHK(PyArray_DESCR((PyArrayObject *)pv))) { PyErr_SetString(PyExc_TypeError, "object array may be self-referencing"); + Py_DECREF(pv); return NULL; } pv2 = Py_TYPE(pv)->tp_as_number->nb_float(pv); @@ -849,6 +851,7 @@ array_long(PyArrayObject *v) PyDataType_REFCHK(PyArray_DESCR((PyArrayObject *)pv))) { PyErr_SetString(PyExc_TypeError, "object array may be self-referencing"); + Py_DECREF(pv); return NULL; } pv2 = Py_TYPE(pv)->tp_as_number->nb_long(pv); @@ -884,6 +887,7 @@ array_oct(PyArrayObject *v) PyDataType_REFCHK(PyArray_DESCR((PyArrayObject *)pv))) { PyErr_SetString(PyExc_TypeError, "object array may be self-referencing"); + Py_DECREF(pv); return NULL; } pv2 = Py_TYPE(pv)->tp_as_number->nb_oct(pv); @@ -919,6 +923,7 @@ array_hex(PyArrayObject *v) PyDataType_REFCHK(PyArray_DESCR((PyArrayObject *)pv))) { PyErr_SetString(PyExc_TypeError, "object array may be self-referencing"); + Py_DECREF(pv); return NULL; } pv2 = Py_TYPE(pv)->tp_as_number->nb_hex(pv); diff --git a/numpy/core/src/umath/test_rational.c.src b/numpy/core/src/umath/test_rational.c.src index 1650dd1d3..d8f90f9e5 100644 --- a/numpy/core/src/umath/test_rational.c.src +++ b/numpy/core/src/umath/test_rational.c.src @@ -1242,12 +1242,15 @@ PyMODINIT_FUNC inittest_rational(void) { PyErr_Format(PyExc_AssertionError, \ "ufunc %s takes %d arguments, our loop takes %ld", \ #name, ufunc->nargs, sizeof(_types)/sizeof(int)); \ + Py_DECREF(ufunc); \ goto fail; \ } \ if (PyUFunc_RegisterLoopForType((PyUFuncObject*)ufunc, npy_rational, \ rational_ufunc_##name, _types, 0) < 0) { \ + Py_DECREF(ufunc); \ goto fail; \ } \ + Py_DECREF(ufunc); \ } #define REGISTER_UFUNC_BINARY_RATIONAL(name) \ REGISTER_UFUNC(name, {npy_rational, npy_rational, npy_rational}) diff --git a/numpy/core/tests/test_regression.py b/numpy/core/tests/test_regression.py index 02cf1b8df..b98746e1b 100644 --- a/numpy/core/tests/test_regression.py +++ b/numpy/core/tests/test_regression.py @@ -1654,6 +1654,14 @@ class TestRegression(TestCase): assert_raises(TypeError, oct, a) assert_raises(TypeError, hex, a) + # Test the same for a circular reference. + b = np.array(a, dtype=object) + a[()] = b + assert_raises(TypeError, int, a) + # Numpy has no tp_traverse currently, so circular references + # cannot be detected. So resolve it: + a[()] = 0 + # This was causing a to become like the above a = np.array(0, dtype=object) a[...] += 1 @@ -1661,7 +1669,7 @@ class TestRegression(TestCase): def test_object_array_self_copy(self): # An object array being copied into itself DECREF'ed before INCREF'ing - # causing segmentation faults (gh-3787) + # causing segmentation faults (gh-3787) a = np.array(object(), dtype=object) np.copyto(a, a) assert_equal(sys.getrefcount(a[()]), 2) |