From c0b2a807ff9ce7d2c0c83ee808678eb841aa9778 Mon Sep 17 00:00:00 2001 From: Thomas Heller Date: Tue, 15 Jul 2008 17:03:08 +0000 Subject: Issue #3258: Fix an assertion error (in debug build) and a crash (in release build) when the format string of a pointer to an incomplete structure is created. --- Lib/ctypes/test/test_pep3118.py | 20 ++++++++++++++++++++ Modules/_ctypes/_ctypes.c | 13 ++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/Lib/ctypes/test/test_pep3118.py b/Lib/ctypes/test/test_pep3118.py index cf628d8..119b0ad 100644 --- a/Lib/ctypes/test/test_pep3118.py +++ b/Lib/ctypes/test/test_pep3118.py @@ -33,6 +33,8 @@ class memoryview(object): def normalize(format): # Remove current endian specifier and white space from a format # string + if format is None: + return "" format = format.replace(OTHER_ENDIAN, THIS_ENDIAN) return re.sub(r"\s", "", format) @@ -105,6 +107,14 @@ class EmptyStruct(Structure): class aUnion(Union): _fields_ = [("a", c_int)] +class Incomplete(Structure): + pass + +class Complete(Structure): + pass +PComplete = POINTER(Complete) +Complete._fields_ = [("a", c_int)] + ################################################################ # # This table contains format strings as they look on little endian @@ -162,6 +172,16 @@ native_types = [ # the pep does't support unions (aUnion, "B", None, aUnion), + ## pointer to incomplete structure + (Incomplete, "B", None, Incomplete), + (POINTER(Incomplete), "&B", None, POINTER(Incomplete)), + + # 'Complete' is a structure that starts incomplete, but is completed after the + # pointer type to it has been created. + (Complete, "T{tp_dict); result->tp_dict = (PyObject *)dict; + dict->format = alloc_format_string(NULL, "B"); + if (dict->format == NULL) { + Py_DECREF(result); + return NULL; + } dict->paramfunc = StructUnionType_paramfunc; @@ -907,7 +912,13 @@ PointerType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) if (proto) { StgDictObject *itemdict = PyType_stgdict(proto); assert(itemdict); - stgdict->format = alloc_format_string("&", itemdict->format); + /* If itemdict->format is NULL, then this is a pointer to an + incomplete type. We create a generic format string + 'pointer to bytes' in this case. XXX Better would be to + fix the format string later... + */ + stgdict->format = alloc_format_string("&", + itemdict->format ? itemdict->format : "B"); if (stgdict->format == NULL) { Py_DECREF((PyObject *)stgdict); return NULL; -- cgit v0.12