diff options
| author | Pauli Virtanen <pav@iki.fi> | 2015-11-12 20:20:44 +0200 |
|---|---|---|
| committer | Pauli Virtanen <pav@iki.fi> | 2015-11-12 20:27:16 +0200 |
| commit | f2be3a2f822b3f5cf4b706cc2e28f0c169e6d995 (patch) | |
| tree | 4304f5bdb2533089c0aef074d534cb7f3a82986a /numpy | |
| parent | 8efc87ec599c0b3eac4e63bea6eda9023d8ed96d (diff) | |
| download | numpy-f2be3a2f822b3f5cf4b706cc2e28f0c169e6d995.tar.gz | |
BUG: don't use PyArray_Converter in may_share_memory
The converter function has NPY_ARRAY_CARRAY enabled, which can cause
false negatives for non-ndarray inputs.
Fixes gh-5604
Diffstat (limited to 'numpy')
| -rw-r--r-- | numpy/core/src/multiarray/multiarraymodule.c | 32 | ||||
| -rw-r--r-- | numpy/core/tests/test_mem_overlap.py | 28 |
2 files changed, 56 insertions, 4 deletions
diff --git a/numpy/core/src/multiarray/multiarraymodule.c b/numpy/core/src/multiarray/multiarraymodule.c index 486fdbc9b..b9d79029e 100644 --- a/numpy/core/src/multiarray/multiarraymodule.c +++ b/numpy/core/src/multiarray/multiarraymodule.c @@ -3992,6 +3992,8 @@ static PyObject * array_shares_memory_impl(PyObject *args, PyObject *kwds, Py_ssize_t default_max_work, int raise_exceptions) { + PyObject * self_obj = NULL; + PyObject * other_obj = NULL; PyArrayObject * self = NULL; PyArrayObject * other = NULL; PyObject *max_work_obj = NULL; @@ -4004,13 +4006,35 @@ array_shares_memory_impl(PyObject *args, PyObject *kwds, Py_ssize_t default_max_ max_work = default_max_work; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&O&|O", kwlist, - PyArray_Converter, &self, - PyArray_Converter, &other, - &max_work_obj)) { + if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|O", kwlist, + &self_obj, &other_obj, &max_work_obj)) { return NULL; } + if (PyArray_Check(self_obj)) { + self = (PyArrayObject*)self_obj; + Py_INCREF(self); + } + else { + /* Use FromAny to enable checking overlap for objects exposing array + interfaces etc. */ + self = (PyArrayObject*)PyArray_FromAny(self_obj, NULL, 0, 0, 0, NULL); + if (self == NULL) { + goto fail; + } + } + + if (PyArray_Check(other_obj)) { + other = (PyArrayObject*)other_obj; + Py_INCREF(other); + } + else { + other = (PyArrayObject*)PyArray_FromAny(other_obj, NULL, 0, 0, 0, NULL); + if (other == NULL) { + goto fail; + } + } + if (max_work_obj == NULL || max_work_obj == Py_None) { /* noop */ } diff --git a/numpy/core/tests/test_mem_overlap.py b/numpy/core/tests/test_mem_overlap.py index 728cc675d..8d39fa4c0 100644 --- a/numpy/core/tests/test_mem_overlap.py +++ b/numpy/core/tests/test_mem_overlap.py @@ -482,5 +482,33 @@ def test_internal_overlap_fuzz(): no_overlap += 1 +def test_non_ndarray_inputs(): + # Regression check for gh-5604 + + class MyArray(object): + def __init__(self, data): + self.data = data + + @property + def __array_interface__(self): + return self.data.__array_interface__ + + class MyArray2(object): + def __init__(self, data): + self.data = data + + def __array__(self): + return self.data + + for cls in [MyArray, MyArray2]: + x = np.arange(5) + + assert_(np.may_share_memory(cls(x[::2]), x[1::2])) + assert_(not np.shares_memory(cls(x[::2]), x[1::2])) + + assert_(np.shares_memory(cls(x[1::3]), x[::2])) + assert_(np.may_share_memory(cls(x[1::3]), x[::2])) + + if __name__ == "__main__": run_module_suite() |
