Skip to content

Commit f6be10a

Browse files
Do not report ndim > 1 without the shape
PyBUF_SIMPLE requests crashed on a multidimensional array: ndim > 1 implies shape != NULL (see PyBuffer_IsContiguous()). The buffer is C contiguous, so it can be exposed as flat. Also, only a multidimensional array is not Fortran contiguous, and BufferError is more appropriate than TypeError. Clear the strides when the shape which they point into is freed.
1 parent 41371ae commit f6be10a

1 file changed

Lines changed: 19 additions & 6 deletions

File tree

Modules/_ctypes/_ctypes.c

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -502,8 +502,10 @@ ctype_free_stginfo_members(StgInfo *info)
502502
info->ffi_type_pointer.elements = NULL;
503503
PyMem_Free(info->format);
504504
info->format = NULL;
505+
/* The strides point into the shape allocation. */
505506
PyMem_Free(info->shape);
506507
info->shape = NULL;
508+
info->strides = NULL;
507509
ctype_clear_stginfo(info);
508510
}
509511

@@ -3134,9 +3136,9 @@ PyCData_NewGetBuffer(PyObject *myself, Py_buffer *view, int flags)
31343136
}
31353137
assert(item_info);
31363138

3137-
if ((flags & PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS) {
3138-
view->obj = NULL;
3139-
PyErr_Format(PyExc_TypeError, "Fortran contiguous buffer is not supported");
3139+
if (info->ndim > 1 && (flags & PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS) {
3140+
PyErr_SetString(PyExc_BufferError,
3141+
"ctypes array is not Fortran contiguous");
31403142
return -1;
31413143
}
31423144

@@ -3151,10 +3153,21 @@ PyCData_NewGetBuffer(PyObject *myself, Py_buffer *view, int flags)
31513153
else {
31523154
view->format = NULL;
31533155
}
3154-
view->ndim = info->ndim;
3155-
view->shape = ((flags & PyBUF_ND) == PyBUF_ND) ? info->shape : NULL;
3156+
if ((flags & PyBUF_ND) == PyBUF_ND) {
3157+
view->ndim = info->ndim;
3158+
view->shape = info->shape;
3159+
}
3160+
else {
3161+
/* The buffer is C contiguous, so it can be exposed as flat.
3162+
Keep ndim <= 1: ndim > 1 implies shape != NULL, see
3163+
PyBuffer_IsContiguous(). */
3164+
view->ndim = info->ndim ? 1 : 0;
3165+
view->shape = NULL;
3166+
}
31563167
view->itemsize = item_info->size;
3157-
view->strides = ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) ? info->strides : NULL;
3168+
/* PyBUF_STRIDES implies PyBUF_ND. */
3169+
view->strides = ((flags & PyBUF_STRIDES) == PyBUF_STRIDES)
3170+
? info->strides : NULL;
31583171
view->suboffsets = NULL;
31593172
view->internal = NULL;
31603173
return 0;

0 commit comments

Comments
 (0)