summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Wieser <wieser.eric@gmail.com>2017-02-13 23:23:10 +0000
committerCharles Harris <charlesr.harris@gmail.com>2017-03-04 11:48:51 -0700
commit91374d117e1dea50467a14c0d697690ee9630c1b (patch)
tree897631645391999a4b5efe3fb387e65a7525c01f
parent20e89a4e855875d24e96b7877fb22258eaeae5b7 (diff)
downloadnumpy-91374d117e1dea50467a14c0d697690ee9630c1b.tar.gz
BUG: Fixed undefined behavior when __array_wrap__ returns None
Now `None` is treated like any other return value, rather than a command to segfault.
-rw-r--r--numpy/core/src/umath/ufunc_object.c4
-rw-r--r--numpy/core/tests/test_umath.py13
2 files changed, 14 insertions, 3 deletions
diff --git a/numpy/core/src/umath/ufunc_object.c b/numpy/core/src/umath/ufunc_object.c
index 62024d2e3..69fb255fa 100644
--- a/numpy/core/src/umath/ufunc_object.c
+++ b/numpy/core/src/umath/ufunc_object.c
@@ -4395,6 +4395,7 @@ ufunc_generic_call(PyUFuncObject *ufunc, PyObject *args, PyObject *kwds)
continue;
}
res = PyObject_CallFunction(wrap, "O(OOi)", mps[j], ufunc, args, i);
+ /* Handle __array_wrap__ that does not accept a context argument */
if (res == NULL && PyErr_ExceptionMatches(PyExc_TypeError)) {
PyErr_Clear();
res = PyObject_CallFunctionObjArgs(wrap, mps[j], NULL);
@@ -4403,9 +4404,6 @@ ufunc_generic_call(PyUFuncObject *ufunc, PyObject *args, PyObject *kwds)
if (res == NULL) {
goto fail;
}
- else if (res == Py_None) {
- Py_DECREF(res);
- }
else {
Py_DECREF(mps[j]);
retobj[i] = res;
diff --git a/numpy/core/tests/test_umath.py b/numpy/core/tests/test_umath.py
index 4c0243559..6fea832c9 100644
--- a/numpy/core/tests/test_umath.py
+++ b/numpy/core/tests/test_umath.py
@@ -1379,6 +1379,19 @@ class TestSpecialMethods(TestCase):
a = A()
self.assertRaises(RuntimeError, ncu.maximum, a, a)
+ def test_none_wrap(self):
+ # Tests that issue #8507 is resolved. Previously, this would segfault
+
+ class A(object):
+ def __array__(self):
+ return np.zeros(1)
+
+ def __array_wrap__(self, arr, context=None):
+ return None
+
+ a = A()
+ assert_equal(ncu.maximum(a, a), None)
+
def test_default_prepare(self):
class with_wrap(object):