Skip to content


Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP


segfault in _IsWriteable when data is not owned #481

wence- opened this Issue · 0 comments

1 participant


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


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


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)

import pyximport
import foo

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

python -> 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- wence- referenced this issue in OP2/PyOP2

Setflags fix #82

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.