Thanks to visit codestin.com
Credit goes to github.com

Skip to content

segfault in _IsWriteable when data is not owned #481

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wence- opened this issue Oct 8, 2012 · 2 comments · Fixed by #13463
Closed

segfault in _IsWriteable when data is not owned #481

wence- opened this issue Oct 8, 2012 · 2 comments · Fixed by #13463
Labels

Comments

@wence-
Copy link

wence- commented Oct 8, 2012

The following, albeit slightly contrived, example causes a segfault in _IsWriteable.

foo.pyx:

from libc.stdlib cimport malloc
import numpy as np
cimport numpy as np

np.import_array()

def test(n):

    cdef np.npy_intp _n = n
    cdef void * data

    data = <void *>malloc(_n * sizeof(double))

    return np.PyArray_SimpleNewFromData(1, &_n, np.NPY_DOUBLE, data)

test.py:

import pyximport
pyximport.install()
import foo

a = foo.test(10)
b = a.reshape((5,2))
b.setflags(write=True)

python test.py -> segmentation fault

Here's _IsWriteable (with unnecessary bits removed).

NPY_NO_EXPORT npy_bool
_IsWriteable(PyArrayObject *ap)
{
    PyObject *base=PyArray_BASE(ap);
....
    /* If we own our own data, then no-problem */
    if ((base == NULL) || (PyArray_FLAGS(ap) & NPY_ARRAY_OWNDATA)) {
        return NPY_TRUE;
    }
 ....
    while(PyArray_Check(base)) {
        if (PyArray_CHKFLAGS((PyArrayObject *)base, NPY_ARRAY_OWNDATA)) {
            return (npy_bool) (PyArray_ISWRITEABLE((PyArrayObject *)base));
        }
        base = PyArray_BASE((PyArrayObject *)base);
    }

...
}

a.setflags(write=True) works because

ap == a
base == NULL

and we hit the first condition (base is NULL or we own the data)

b.setflags(write=True) doesn't work because
ap == b
base == a
b.flags['OWNDATA'] == False

so we go into the loop:
base doesn't own the data either, so we try and find the base of a, which is NULL, and PyArray_Check(NULL) is a segfault.

I think the fix is

diff --git a/numpy/core/src/multiarray/common.c b/numpy/core/src/multiarray/common.c
index 7b8177c..60a58f6 100644
--- a/numpy/core/src/multiarray/common.c
+++ b/numpy/core/src/multiarray/common.c
@@ -628,6 +628,9 @@ _IsWriteable(PyArrayObject *ap)
             return (npy_bool) (PyArray_ISWRITEABLE((PyArrayObject *)base));
         }
         base = PyArray_BASE((PyArrayObject *)base);
+        if (!base) {
+            return NPY_TRUE;
+        }
     }

     /*

But I'm not sure which of returning True or False is correct.

@wence-
Copy link
Author

wence- commented Nov 3, 2017

Still broken, FWIW.

@mattip
Copy link
Member

mattip commented Jan 10, 2018

It seems there are many places that PyArray_Check can be called on a NULL value. Just in arrayobject.c there are PyArray_Size and PyArray_ElementStrides.

Is it worth considering always checking for NULL in PyArray_Check ?

seberg added a commit to seberg/numpy that referenced this issue May 16, 2019
This also deprecates setting a non-writeable array to writeable if
that array does not own its data (and has no base object to check if
the memory may be writeable). (Deprecation on Python side only)

Closes numpygh-481
charris pushed a commit to charris/numpy that referenced this issue May 24, 2019
This also deprecates setting a non-writeable array to writeable if
that array does not own its data (and has no base object to check if
the memory may be writeable). (Deprecation on Python side only)

Closes numpygh-481
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants