From f4e3ca9ad1735fba4f85d828ed4e99f6ac8557df Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Tue, 6 Feb 2018 22:58:25 -0800 Subject: [PATCH 1/2] 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 | 49 ++++++++++++++++--- 3 files changed, 47 insertions(+), 7 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); - Py_ssize_t i; + StgDictObject *item_dict; if (view == NULL) return 0; @@ -2613,12 +2649,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; From dd2069f5c9ca3856389a8f48c04db70ebda1d6b8 Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Thu, 6 Jun 2019 20:20:34 -0700 Subject: [PATCH 2/2] bpo-32782: Avoid touching python attributes when the C attribute is available. --- Modules/_ctypes/_ctypes.c | 50 +++++++++++++-------------------------- 1 file changed, 16 insertions(+), 34 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index fc3c6c8df55041..ea4d0f9f936b07 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -2596,38 +2596,23 @@ static PyMemberDef PyCData_members[] = { { NULL }, }; -/* - Get the StgDictObject corresponding to a single item of a multidimensional - array. - Takes and returns a borrowed reference. -*/ -static StgDictObject * -PyCData_item_stgdict(StgDictObject *dict) +/* Find the innermost type of an array type, returning a borrowed reference */ +static PyObject * +PyCData_item_type(PyObject *type) { - if (dict->ndim == 0) { - /* scalar is its own item */ - return dict; + if (PyCArrayTypeObject_Check(type)) { + StgDictObject *stg_dict; + PyObject *elem_type; + + /* asserts used here as these are all guaranteed by construction */ + stg_dict = PyType_stgdict(type); + assert(stg_dict); + elem_type = stg_dict->proto; + assert(elem_type); + return PyCData_item_type(elem_type); } 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); + return type; } } @@ -2636,7 +2621,8 @@ PyCData_NewGetBuffer(PyObject *myself, Py_buffer *view, int flags) { CDataObject *self = (CDataObject *)myself; StgDictObject *dict = PyObject_stgdict(myself); - StgDictObject *item_dict; + PyObject *item_type = PyCData_item_type((PyObject*)Py_TYPE(myself)); + StgDictObject *item_dict = PyType_stgdict(item_type); if (view == NULL) return 0; @@ -2649,10 +2635,6 @@ PyCData_NewGetBuffer(PyObject *myself, Py_buffer *view, int flags) view->format = dict->format ? dict->format : "B"; view->ndim = dict->ndim; view->shape = dict->shape; - item_dict = PyCData_item_stgdict(dict); - if (item_dict == NULL) { - return -1; - } view->itemsize = item_dict->size; view->strides = NULL; view->suboffsets = NULL; pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy