summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPauli Virtanen <pav@iki.fi>2017-01-19 23:15:00 +0100
committerPauli Virtanen <pav@iki.fi>2017-01-19 23:15:00 +0100
commitd4a5f2c5b0c491ba9dfd603487bf3d3dce7320b5 (patch)
tree23a1750901117a26756d4eaa94efca52b73045ec
parentff436f9fd44cb9ebb64a6b6e6a59e6f988481672 (diff)
downloadnumpy-d4a5f2c5b0c491ba9dfd603487bf3d3dce7320b5.tar.gz
BUG: umath: correct treatment of __array_prepare__
prepare_ufunc_output is allowed to replace the array, because we check that it's still a view. Also if COPY_IF_OVERLAP made updateifcopy of op[i], the data will be reflected in the array from __array_prepare__. The is-a-view check is only bare-bones, but it was so since 61d45eee
-rw-r--r--numpy/core/src/umath/ufunc_object.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/numpy/core/src/umath/ufunc_object.c b/numpy/core/src/umath/ufunc_object.c
index bed395fc4..8de0537cc 100644
--- a/numpy/core/src/umath/ufunc_object.c
+++ b/numpy/core/src/umath/ufunc_object.c
@@ -1791,8 +1791,8 @@ execute_fancy_ufunc_loop(PyUFuncObject *ufunc,
for (i = nin; i < nop; ++i) {
PyArrayObject *op_tmp;
- /* Prepare_ufunc_output may decref & replace pointer */
- op_tmp = op_it[i];
+ /* prepare_ufunc_output may decref & replace pointer */
+ op_tmp = op[i];
Py_INCREF(op_tmp);
if (prepare_ufunc_output(ufunc, &op_tmp,
@@ -1801,7 +1801,8 @@ execute_fancy_ufunc_loop(PyUFuncObject *ufunc,
return -1;
}
- if (PyArray_BYTES(op_tmp) != PyArray_BYTES(op_it[i])) {
+ /* Validate that the prepare_ufunc_output didn't mess with pointers */
+ if (PyArray_BYTES(op_tmp) != PyArray_BYTES(op[i])) {
PyErr_SetString(PyExc_ValueError,
"The __array_prepare__ functions modified the data "
"pointer addresses in an invalid fashion");
@@ -1809,6 +1810,13 @@ execute_fancy_ufunc_loop(PyUFuncObject *ufunc,
NpyIter_Deallocate(iter);
return -1;
}
+
+ /*
+ * Put the updated operand back and undo the DECREF above. If
+ * COPY_IF_OVERLAP made a temporary copy, the output will be copied in
+ * by UPDATEIFCOPY even if op[i] was changed.
+ */
+ op[i] = op_tmp;
Py_DECREF(op_tmp);
}