summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
authorPauli Virtanen <pav@iki.fi>2015-11-12 20:20:44 +0200
committerPauli Virtanen <pav@iki.fi>2015-11-12 20:27:16 +0200
commitf2be3a2f822b3f5cf4b706cc2e28f0c169e6d995 (patch)
tree4304f5bdb2533089c0aef074d534cb7f3a82986a /numpy
parent8efc87ec599c0b3eac4e63bea6eda9023d8ed96d (diff)
downloadnumpy-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.c32
-rw-r--r--numpy/core/tests/test_mem_overlap.py28
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()