From 29b3c321376c18c9cf764c083bf96f18f684b50d Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Tue, 6 Feb 2018 22:58:25 -0800 Subject: [PATCH] bpo-32782: PEP3118 itemsize of an empty ctypes array should not be 0 The itemsize returned in a memoryview of a ctypes array should be computed from the item type, not by dividing the total size by the length and assuming that the length is not zero. --- Lib/ctypes/test/test_pep3118.py | 2 + .../2018-02-06-23-21-13.bpo-32782.EJVSfR.rst | 3 ++ Modules/_ctypes/_ctypes.c | 44 ++++++++++++++++--- 3 files changed, 44 insertions(+), 5 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2018-02-06-23-21-13.bpo-32782.EJVSfR.rst diff --git a/Lib/ctypes/test/test_pep3118.py b/Lib/ctypes/test/test_pep3118.py index 81e8ca7638fdeb..efffc80a66fcb8 100644 --- a/Lib/ctypes/test/test_pep3118.py +++ b/Lib/ctypes/test/test_pep3118.py @@ -176,7 +176,9 @@ class Complete(Structure): ## arrays and pointers (c_double * 4, "ndim == 0) { + /* scalar is its own item */ + return dict; + } + else { + /* follow _type_, eliminating a dimension */ + PyObject *type_attr; + StgDictObject *item_dict; + + type_attr = PyDict_GetItemString((PyObject *)dict, "_type_"); + if (!type_attr) { + PyErr_SetString(PyExc_AttributeError, + "class must define a '_type_' attribute"); + return NULL; + } + + item_dict = PyType_stgdict(type_attr); + if (!item_dict) { + PyErr_SetString(PyExc_TypeError, + "_type_ must have storage info"); + return NULL; + } + + return PyCData_item_stgdict(item_dict); + } +} + static int PyCData_NewGetBuffer(PyObject *myself, Py_buffer *view, int flags) { CDataObject *self = (CDataObject *)myself; StgDictObject *dict = PyObject_stgdict(myself); + StgDictObject *item_dict; Py_ssize_t i; if (view == NULL) return 0; @@ -2613,12 +2648,11 @@ static int PyCData_NewGetBuffer(PyObject *myself, Py_buffer *view, int flags) view->format = dict->format ? dict->format : "B"; view->ndim = dict->ndim; view->shape = dict->shape; - view->itemsize = self->b_size; - if (view->itemsize) { - for (i = 0; i < view->ndim; ++i) { - view->itemsize /= dict->shape[i]; - } + item_dict = PyCData_item_stgdict(dict); + if (item_dict == NULL) { + return -1; } + view->itemsize = item_dict->size; view->strides = NULL; view->suboffsets = NULL; view->internal = NULL;