Skip to content

Commit 1649c1b

Browse files
author
Stefan Krah
committed
Issue #14181: Preserve backwards compatibility for getbufferprocs that a) do
not adhere to the new documentation and b) manage to clobber view->obj before returning failure.
1 parent bf6c7ec commit 1649c1b

3 files changed

Lines changed: 22 additions & 15 deletions

File tree

Lib/test/test_buffer.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3609,6 +3609,12 @@ def test_memoryview_from_static_exporter(self):
36093609
lst=lst)
36103610
del x, y, z, m
36113611

3612+
def test_memoryview_getbuffer_undefined(self):
3613+
3614+
# getbufferproc does not adhere to the new documentation
3615+
nd = ndarray([1,2,3], [3], flags=ND_GETBUF_FAIL|ND_GETBUF_UNDEFINED)
3616+
self.assertRaises(BufferError, memoryview, nd)
3617+
36123618
def test_issue_7385(self):
36133619
x = ndarray([1,2,3], shape=[3], flags=ND_GETBUF_FAIL)
36143620
self.assertRaises(BufferError, memoryview, x)

Modules/_testbuffer.c

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -44,23 +44,21 @@ static PyTypeObject NDArray_Type;
4444
#define ADJUST_PTR(ptr, suboffsets) \
4545
(HAVE_PTR(suboffsets) ? *((char**)ptr) + suboffsets[0] : ptr)
4646

47+
/* Default: NumPy style (strides), read-only, no var-export, C-style layout */
48+
#define ND_DEFAULT 0x000
4749
/* User configurable flags for the ndarray */
48-
#define ND_VAREXPORT 0x001 /* change layout while buffers are exported */
49-
50+
#define ND_VAREXPORT 0x001 /* change layout while buffers are exported */
5051
/* User configurable flags for each base buffer */
51-
#define ND_WRITABLE 0x002 /* mark base buffer as writable */
52-
#define ND_FORTRAN 0x004 /* Fortran contiguous layout */
53-
#define ND_SCALAR 0x008 /* scalar: ndim = 0 */
54-
#define ND_PIL 0x010 /* convert to PIL-style array (suboffsets) */
55-
#define ND_GETBUF_FAIL 0x020 /* test issue 7385 */
56-
#define ND_REDIRECT 0x040 /* redirect buffer requests */
57-
58-
/* Default: NumPy style (strides), read-only, no var-export, C-style layout */
59-
#define ND_DEFAULT 0x0
60-
52+
#define ND_WRITABLE 0x002 /* mark base buffer as writable */
53+
#define ND_FORTRAN 0x004 /* Fortran contiguous layout */
54+
#define ND_SCALAR 0x008 /* scalar: ndim = 0 */
55+
#define ND_PIL 0x010 /* convert to PIL-style array (suboffsets) */
56+
#define ND_REDIRECT 0x020 /* redirect buffer requests */
57+
#define ND_GETBUF_FAIL 0x040 /* trigger getbuffer failure */
58+
#define ND_GETBUF_UNDEFINED 0x080 /* undefined view.obj */
6159
/* Internal flags for the base buffer */
62-
#define ND_C 0x080 /* C contiguous layout (default) */
63-
#define ND_OWN_ARRAYS 0x100 /* consumer owns arrays */
60+
#define ND_C 0x100 /* C contiguous layout (default) */
61+
#define ND_OWN_ARRAYS 0x200 /* consumer owns arrays */
6462

6563
/* ndarray properties */
6664
#define ND_IS_CONSUMER(nd) \
@@ -1449,6 +1447,8 @@ ndarray_getbuf(NDArrayObject *self, Py_buffer *view, int flags)
14491447
if (baseflags & ND_GETBUF_FAIL) {
14501448
PyErr_SetString(PyExc_BufferError,
14511449
"ND_GETBUF_FAIL: forced test exception");
1450+
if (baseflags & ND_GETBUF_UNDEFINED)
1451+
view->obj = (PyObject *)0x1; /* wrong but permitted in <= 3.2 */
14521452
return -1;
14531453
}
14541454

@@ -2782,6 +2782,7 @@ PyInit__testbuffer(void)
27822782
PyModule_AddIntConstant(m, "ND_SCALAR", ND_SCALAR);
27832783
PyModule_AddIntConstant(m, "ND_PIL", ND_PIL);
27842784
PyModule_AddIntConstant(m, "ND_GETBUF_FAIL", ND_GETBUF_FAIL);
2785+
PyModule_AddIntConstant(m, "ND_GETBUF_UNDEFINED", ND_GETBUF_UNDEFINED);
27852786
PyModule_AddIntConstant(m, "ND_REDIRECT", ND_REDIRECT);
27862787

27872788
PyModule_AddIntConstant(m, "PyBUF_SIMPLE", PyBUF_SIMPLE);

Objects/memoryobject.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ _PyManagedBuffer_FromObject(PyObject *base)
8686
return NULL;
8787

8888
if (PyObject_GetBuffer(base, &mbuf->master, PyBUF_FULL_RO) < 0) {
89-
/* mbuf->master.obj must be NULL. */
89+
mbuf->master.obj = NULL;
9090
Py_DECREF(mbuf);
9191
return NULL;
9292
}

0 commit comments

Comments
 (0)