diff options
| author | Pauli Virtanen <pav@iki.fi> | 2017-01-19 23:15:00 +0100 |
|---|---|---|
| committer | Pauli Virtanen <pav@iki.fi> | 2017-01-19 23:15:00 +0100 |
| commit | d4a5f2c5b0c491ba9dfd603487bf3d3dce7320b5 (patch) | |
| tree | 23a1750901117a26756d4eaa94efca52b73045ec | |
| parent | ff436f9fd44cb9ebb64a6b6e6a59e6f988481672 (diff) | |
| download | numpy-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.c | 14 |
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); } |
