Skip to content

Commit 3fcdc95

Browse files
committed
ctypes: Fix set_type() to update format string for incomplete pointer types
1 parent 2f8705d commit 3fcdc95

File tree

1 file changed

+30
-21
lines changed

1 file changed

+30
-21
lines changed

Modules/_ctypes/_ctypes.c

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1266,6 +1266,32 @@ PyCPointerType_SetProto(ctypes_state *st, PyObject *self, StgInfo *stginfo, PyOb
12661266
return 0;
12671267
}
12681268

1269+
// Set the format string for a pointer type based on its element type.
1270+
static int
1271+
PyCPointerType_SetFormat(ctypes_state *st, StgInfo *stginfo, PyObject *proto)
1272+
{
1273+
StgInfo *iteminfo;
1274+
if (PyStgInfo_FromType(st, proto, &iteminfo) < 0) {
1275+
return -1;
1276+
}
1277+
assert(iteminfo); // PyCPointerType_SetProto already verified this
1278+
1279+
const char *current_format = iteminfo->format ? iteminfo->format : "B";
1280+
char *new_format;
1281+
if (iteminfo->shape != NULL) {
1282+
new_format = _ctypes_alloc_format_string_with_shape(
1283+
iteminfo->ndim, iteminfo->shape, "&", current_format);
1284+
} else {
1285+
new_format = _ctypes_alloc_format_string("&", current_format);
1286+
}
1287+
if (new_format == NULL) {
1288+
return -1;
1289+
}
1290+
PyMem_Free(stginfo->format);
1291+
stginfo->format = new_format;
1292+
return 0;
1293+
}
1294+
12691295
static PyCArgObject *
12701296
PyCPointerType_paramfunc(ctypes_state *st, CDataObject *self)
12711297
{
@@ -1314,35 +1340,15 @@ PyCPointerType_init(PyObject *self, PyObject *args, PyObject *kwds)
13141340
return -1;
13151341
}
13161342
if (proto) {
1317-
const char *current_format;
13181343
if (PyCPointerType_SetProto(st, self, stginfo, proto) < 0) {
13191344
Py_DECREF(proto);
13201345
return -1;
13211346
}
1322-
StgInfo *iteminfo;
1323-
if (PyStgInfo_FromType(st, proto, &iteminfo) < 0) {
1347+
if (PyCPointerType_SetFormat(st, stginfo, proto) < 0) {
13241348
Py_DECREF(proto);
13251349
return -1;
13261350
}
1327-
/* PyCPointerType_SetProto has verified proto has a stginfo. */
1328-
assert(iteminfo);
1329-
/* If iteminfo->format is NULL, then this is a pointer to an
1330-
incomplete type. We create a generic format string
1331-
'pointer to bytes' in this case. XXX Better would be to
1332-
fix the format string later...
1333-
*/
1334-
current_format = iteminfo->format ? iteminfo->format : "B";
1335-
if (iteminfo->shape != NULL) {
1336-
/* pointer to an array: the shape needs to be prefixed */
1337-
stginfo->format = _ctypes_alloc_format_string_with_shape(
1338-
iteminfo->ndim, iteminfo->shape, "&", current_format);
1339-
} else {
1340-
stginfo->format = _ctypes_alloc_format_string("&", current_format);
1341-
}
13421351
Py_DECREF(proto);
1343-
if (stginfo->format == NULL) {
1344-
return -1;
1345-
}
13461352
}
13471353

13481354
return 0;
@@ -1376,6 +1382,9 @@ PyCPointerType_set_type_impl(PyTypeObject *self, PyTypeObject *cls,
13761382
if (PyCPointerType_SetProto(st, (PyObject *)self, info, type) < 0) {
13771383
return NULL;
13781384
}
1385+
if (PyCPointerType_SetFormat(st, info, type) < 0) {
1386+
return NULL;
1387+
}
13791388
if (PyObject_SetAttr((PyObject *)self, &_Py_ID(_type_), type) < 0) {
13801389
return NULL;
13811390
}

0 commit comments

Comments
 (0)