Branch data Line data Source code
1 : : #ifndef Py_BUILD_CORE_BUILTIN
2 : : # define Py_BUILD_CORE_MODULE 1
3 : : #endif
4 : :
5 : : #include "Python.h"
6 : : // windows.h must be included before pycore internal headers
7 : : #ifdef MS_WIN32
8 : : # include <windows.h>
9 : : #endif
10 : :
11 : : #include "pycore_call.h" // _PyObject_CallNoArgs()
12 : : #include <ffi.h>
13 : : #ifdef MS_WIN32
14 : : # include <malloc.h>
15 : : #endif
16 : : #include "ctypes.h"
17 : :
18 : : /******************************************************************/
19 : : /*
20 : : StdDict - a dictionary subclass, containing additional C accessible fields
21 : :
22 : : XXX blabla more
23 : : */
24 : :
25 : : /* Seems we need this, otherwise we get problems when calling
26 : : * PyDict_SetItem() (ma_lookup is NULL)
27 : : */
28 : : static int
29 : 38 : PyCStgDict_init(StgDictObject *self, PyObject *args, PyObject *kwds)
30 : : {
31 [ - + ]: 38 : if (PyDict_Type.tp_init((PyObject *)self, args, kwds) < 0)
32 : 0 : return -1;
33 : 38 : self->format = NULL;
34 : 38 : self->ndim = 0;
35 : 38 : self->shape = NULL;
36 : 38 : return 0;
37 : : }
38 : :
39 : : static int
40 : 2 : PyCStgDict_clear(StgDictObject *self)
41 : : {
42 [ - + ]: 2 : Py_CLEAR(self->proto);
43 [ - + ]: 2 : Py_CLEAR(self->argtypes);
44 [ - + ]: 2 : Py_CLEAR(self->converters);
45 [ - + ]: 2 : Py_CLEAR(self->restype);
46 [ - + ]: 2 : Py_CLEAR(self->checker);
47 : 2 : return 0;
48 : : }
49 : :
50 : : static void
51 : 2 : PyCStgDict_dealloc(StgDictObject *self)
52 : : {
53 : 2 : PyCStgDict_clear(self);
54 : 2 : PyMem_Free(self->format);
55 : 2 : PyMem_Free(self->shape);
56 : 2 : PyMem_Free(self->ffi_type_pointer.elements);
57 : 2 : PyDict_Type.tp_dealloc((PyObject *)self);
58 : 2 : }
59 : :
60 : : static PyObject *
61 : 0 : PyCStgDict_sizeof(StgDictObject *self, void *unused)
62 : : {
63 : : Py_ssize_t res;
64 : :
65 : 0 : res = _PyDict_SizeOf((PyDictObject *)self);
66 : 0 : res += sizeof(StgDictObject) - sizeof(PyDictObject);
67 [ # # ]: 0 : if (self->format)
68 : 0 : res += strlen(self->format) + 1;
69 : 0 : res += self->ndim * sizeof(Py_ssize_t);
70 [ # # ]: 0 : if (self->ffi_type_pointer.elements)
71 : 0 : res += (self->length + 1) * sizeof(ffi_type *);
72 : 0 : return PyLong_FromSsize_t(res);
73 : : }
74 : :
75 : : int
76 : 0 : PyCStgDict_clone(StgDictObject *dst, StgDictObject *src)
77 : : {
78 : : char *d, *s;
79 : : Py_ssize_t size;
80 : :
81 : 0 : PyCStgDict_clear(dst);
82 : 0 : PyMem_Free(dst->ffi_type_pointer.elements);
83 : 0 : PyMem_Free(dst->format);
84 : 0 : dst->format = NULL;
85 : 0 : PyMem_Free(dst->shape);
86 : 0 : dst->shape = NULL;
87 : 0 : dst->ffi_type_pointer.elements = NULL;
88 : :
89 : 0 : d = (char *)dst;
90 : 0 : s = (char *)src;
91 : 0 : memcpy(d + sizeof(PyDictObject),
92 : 0 : s + sizeof(PyDictObject),
93 : : sizeof(StgDictObject) - sizeof(PyDictObject));
94 : :
95 : 0 : Py_XINCREF(dst->proto);
96 : 0 : Py_XINCREF(dst->argtypes);
97 : 0 : Py_XINCREF(dst->converters);
98 : 0 : Py_XINCREF(dst->restype);
99 : 0 : Py_XINCREF(dst->checker);
100 : :
101 [ # # ]: 0 : if (src->format) {
102 : 0 : dst->format = PyMem_Malloc(strlen(src->format) + 1);
103 [ # # ]: 0 : if (dst->format == NULL) {
104 : 0 : PyErr_NoMemory();
105 : 0 : return -1;
106 : : }
107 : 0 : strcpy(dst->format, src->format);
108 : : }
109 [ # # ]: 0 : if (src->shape) {
110 : 0 : dst->shape = PyMem_Malloc(sizeof(Py_ssize_t) * src->ndim);
111 [ # # ]: 0 : if (dst->shape == NULL) {
112 : 0 : PyErr_NoMemory();
113 : 0 : return -1;
114 : : }
115 : 0 : memcpy(dst->shape, src->shape,
116 : 0 : sizeof(Py_ssize_t) * src->ndim);
117 : : }
118 : :
119 [ # # ]: 0 : if (src->ffi_type_pointer.elements == NULL)
120 : 0 : return 0;
121 : 0 : size = sizeof(ffi_type *) * (src->length + 1);
122 : 0 : dst->ffi_type_pointer.elements = PyMem_Malloc(size);
123 [ # # ]: 0 : if (dst->ffi_type_pointer.elements == NULL) {
124 : 0 : PyErr_NoMemory();
125 : 0 : return -1;
126 : : }
127 : 0 : memcpy(dst->ffi_type_pointer.elements,
128 : 0 : src->ffi_type_pointer.elements,
129 : : size);
130 : 0 : return 0;
131 : : }
132 : :
133 : : static struct PyMethodDef PyCStgDict_methods[] = {
134 : : {"__sizeof__", (PyCFunction)PyCStgDict_sizeof, METH_NOARGS},
135 : : {NULL, NULL} /* sentinel */
136 : : };
137 : :
138 : : PyTypeObject PyCStgDict_Type = {
139 : : PyVarObject_HEAD_INIT(NULL, 0)
140 : : "StgDict",
141 : : sizeof(StgDictObject),
142 : : 0,
143 : : (destructor)PyCStgDict_dealloc, /* tp_dealloc */
144 : : 0, /* tp_vectorcall_offset */
145 : : 0, /* tp_getattr */
146 : : 0, /* tp_setattr */
147 : : 0, /* tp_as_async */
148 : : 0, /* tp_repr */
149 : : 0, /* tp_as_number */
150 : : 0, /* tp_as_sequence */
151 : : 0, /* tp_as_mapping */
152 : : 0, /* tp_hash */
153 : : 0, /* tp_call */
154 : : 0, /* tp_str */
155 : : 0, /* tp_getattro */
156 : : 0, /* tp_setattro */
157 : : 0, /* tp_as_buffer */
158 : : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
159 : : 0, /* tp_doc */
160 : : 0, /* tp_traverse */
161 : : 0, /* tp_clear */
162 : : 0, /* tp_richcompare */
163 : : 0, /* tp_weaklistoffset */
164 : : 0, /* tp_iter */
165 : : 0, /* tp_iternext */
166 : : PyCStgDict_methods, /* tp_methods */
167 : : 0, /* tp_members */
168 : : 0, /* tp_getset */
169 : : 0, /* tp_base */
170 : : 0, /* tp_dict */
171 : : 0, /* tp_descr_get */
172 : : 0, /* tp_descr_set */
173 : : 0, /* tp_dictoffset */
174 : : (initproc)PyCStgDict_init, /* tp_init */
175 : : 0, /* tp_alloc */
176 : : 0, /* tp_new */
177 : : 0, /* tp_free */
178 : : };
179 : :
180 : : /* May return NULL, but does not set an exception! */
181 : : StgDictObject *
182 : 433 : PyType_stgdict(PyObject *obj)
183 : : {
184 : : PyTypeObject *type;
185 : :
186 [ - + ]: 433 : if (!PyType_Check(obj))
187 : 0 : return NULL;
188 : 433 : type = (PyTypeObject *)obj;
189 [ + - + + ]: 433 : if (!type->tp_dict || !PyCStgDict_CheckExact(type->tp_dict))
190 : 2 : return NULL;
191 : 431 : return (StgDictObject *)type->tp_dict;
192 : : }
193 : :
194 : : /* May return NULL, but does not set an exception! */
195 : : /*
196 : : This function should be as fast as possible, so we don't call PyType_stgdict
197 : : above but inline the code, and avoid the PyType_Check().
198 : : */
199 : : StgDictObject *
200 : 0 : PyObject_stgdict(PyObject *self)
201 : : {
202 : 0 : PyTypeObject *type = Py_TYPE(self);
203 [ # # # # ]: 0 : if (!type->tp_dict || !PyCStgDict_CheckExact(type->tp_dict))
204 : 0 : return NULL;
205 : 0 : return (StgDictObject *)type->tp_dict;
206 : : }
207 : :
208 : : /* descr is the descriptor for a field marked as anonymous. Get all the
209 : : _fields_ descriptors from descr->proto, create new descriptors with offset
210 : : and index adjusted, and stuff them into type.
211 : : */
212 : : static int
213 : 0 : MakeFields(PyObject *type, CFieldObject *descr,
214 : : Py_ssize_t index, Py_ssize_t offset)
215 : : {
216 : : Py_ssize_t i;
217 : : PyObject *fields;
218 : : PyObject *fieldlist;
219 : :
220 : 0 : fields = PyObject_GetAttrString(descr->proto, "_fields_");
221 [ # # ]: 0 : if (fields == NULL)
222 : 0 : return -1;
223 : 0 : fieldlist = PySequence_Fast(fields, "_fields_ must be a sequence");
224 : 0 : Py_DECREF(fields);
225 [ # # ]: 0 : if (fieldlist == NULL)
226 : 0 : return -1;
227 : :
228 [ # # # # ]: 0 : for (i = 0; i < PySequence_Fast_GET_SIZE(fieldlist); ++i) {
229 [ # # ]: 0 : PyObject *pair = PySequence_Fast_GET_ITEM(fieldlist, i); /* borrowed */
230 : : PyObject *fname, *ftype, *bits;
231 : : CFieldObject *fdescr;
232 : : CFieldObject *new_descr;
233 : : /* Convert to PyArg_UnpackTuple... */
234 [ # # ]: 0 : if (!PyArg_ParseTuple(pair, "OO|O", &fname, &ftype, &bits)) {
235 : 0 : Py_DECREF(fieldlist);
236 : 0 : return -1;
237 : : }
238 : 0 : fdescr = (CFieldObject *)PyObject_GetAttr(descr->proto, fname);
239 [ # # ]: 0 : if (fdescr == NULL) {
240 : 0 : Py_DECREF(fieldlist);
241 : 0 : return -1;
242 : : }
243 [ # # ]: 0 : if (!Py_IS_TYPE(fdescr, &PyCField_Type)) {
244 : 0 : PyErr_SetString(PyExc_TypeError, "unexpected type");
245 : 0 : Py_DECREF(fdescr);
246 : 0 : Py_DECREF(fieldlist);
247 : 0 : return -1;
248 : : }
249 [ # # ]: 0 : if (fdescr->anonymous) {
250 : 0 : int rc = MakeFields(type, fdescr,
251 : 0 : index + fdescr->index,
252 : 0 : offset + fdescr->offset);
253 : 0 : Py_DECREF(fdescr);
254 [ # # ]: 0 : if (rc == -1) {
255 : 0 : Py_DECREF(fieldlist);
256 : 0 : return -1;
257 : : }
258 : 0 : continue;
259 : : }
260 : 0 : new_descr = (CFieldObject *)PyCField_Type.tp_alloc((PyTypeObject *)&PyCField_Type, 0);
261 [ # # ]: 0 : if (new_descr == NULL) {
262 : 0 : Py_DECREF(fdescr);
263 : 0 : Py_DECREF(fieldlist);
264 : 0 : return -1;
265 : : }
266 : : assert(Py_IS_TYPE(new_descr, &PyCField_Type));
267 : 0 : new_descr->size = fdescr->size;
268 : 0 : new_descr->offset = fdescr->offset + offset;
269 : 0 : new_descr->index = fdescr->index + index;
270 : 0 : new_descr->proto = Py_XNewRef(fdescr->proto);
271 : 0 : new_descr->getfunc = fdescr->getfunc;
272 : 0 : new_descr->setfunc = fdescr->setfunc;
273 : :
274 : 0 : Py_DECREF(fdescr);
275 : :
276 [ # # ]: 0 : if (-1 == PyObject_SetAttr(type, fname, (PyObject *)new_descr)) {
277 : 0 : Py_DECREF(fieldlist);
278 : 0 : Py_DECREF(new_descr);
279 : 0 : return -1;
280 : : }
281 : 0 : Py_DECREF(new_descr);
282 : : }
283 : 0 : Py_DECREF(fieldlist);
284 : 0 : return 0;
285 : : }
286 : :
287 : : /* Iterate over the names in the type's _anonymous_ attribute, if present,
288 : : */
289 : : static int
290 : 0 : MakeAnonFields(PyObject *type)
291 : : {
292 : : PyObject *anon;
293 : : PyObject *anon_names;
294 : : Py_ssize_t i;
295 : :
296 [ # # ]: 0 : if (_PyObject_LookupAttr(type, &_Py_ID(_anonymous_), &anon) < 0) {
297 : 0 : return -1;
298 : : }
299 [ # # ]: 0 : if (anon == NULL) {
300 : 0 : return 0;
301 : : }
302 : 0 : anon_names = PySequence_Fast(anon, "_anonymous_ must be a sequence");
303 : 0 : Py_DECREF(anon);
304 [ # # ]: 0 : if (anon_names == NULL)
305 : 0 : return -1;
306 : :
307 [ # # # # ]: 0 : for (i = 0; i < PySequence_Fast_GET_SIZE(anon_names); ++i) {
308 [ # # ]: 0 : PyObject *fname = PySequence_Fast_GET_ITEM(anon_names, i); /* borrowed */
309 : 0 : CFieldObject *descr = (CFieldObject *)PyObject_GetAttr(type, fname);
310 [ # # ]: 0 : if (descr == NULL) {
311 : 0 : Py_DECREF(anon_names);
312 : 0 : return -1;
313 : : }
314 [ # # ]: 0 : if (!Py_IS_TYPE(descr, &PyCField_Type)) {
315 : 0 : PyErr_Format(PyExc_AttributeError,
316 : : "'%U' is specified in _anonymous_ but not in "
317 : : "_fields_",
318 : : fname);
319 : 0 : Py_DECREF(anon_names);
320 : 0 : Py_DECREF(descr);
321 : 0 : return -1;
322 : : }
323 : 0 : descr->anonymous = 1;
324 : :
325 : : /* descr is in the field descriptor. */
326 [ # # ]: 0 : if (-1 == MakeFields(type, (CFieldObject *)descr,
327 : : ((CFieldObject *)descr)->index,
328 : : ((CFieldObject *)descr)->offset)) {
329 : 0 : Py_DECREF(descr);
330 : 0 : Py_DECREF(anon_names);
331 : 0 : return -1;
332 : : }
333 : 0 : Py_DECREF(descr);
334 : : }
335 : :
336 : 0 : Py_DECREF(anon_names);
337 : 0 : return 0;
338 : : }
339 : :
340 : : /*
341 : : Allocate a memory block for a pep3118 format string, copy prefix (if
342 : : non-null) into it and append `{padding}x` to the end.
343 : : Returns NULL on failure, with the error indicator set.
344 : : */
345 : : char *
346 : 0 : _ctypes_alloc_format_padding(const char *prefix, Py_ssize_t padding)
347 : : {
348 : : /* int64 decimal characters + x + null */
349 : : char buf[19 + 1 + 1];
350 : :
351 : : assert(padding > 0);
352 : :
353 [ # # ]: 0 : if (padding == 1) {
354 : : /* Use x instead of 1x, for brevity */
355 : 0 : return _ctypes_alloc_format_string(prefix, "x");
356 : : }
357 : :
358 : 0 : int ret = PyOS_snprintf(buf, sizeof(buf), "%zdx", padding); (void)ret;
359 : : assert(0 <= ret && ret < (Py_ssize_t)sizeof(buf));
360 : 0 : return _ctypes_alloc_format_string(prefix, buf);
361 : : }
362 : :
363 : : /*
364 : : Retrieve the (optional) _pack_ attribute from a type, the _fields_ attribute,
365 : : and create an StgDictObject. Used for Structure and Union subclasses.
366 : : */
367 : : int
368 : 0 : PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct)
369 : : {
370 : : StgDictObject *stgdict, *basedict;
371 : : Py_ssize_t len, offset, size, align, i;
372 : : Py_ssize_t union_size, total_align, aligned_size;
373 : 0 : Py_ssize_t field_size = 0;
374 : : int bitofs;
375 : : PyObject *tmp;
376 : : int pack;
377 : : Py_ssize_t ffi_ofs;
378 : : int big_endian;
379 : 0 : int arrays_seen = 0;
380 : :
381 [ # # ]: 0 : if (fields == NULL)
382 : 0 : return 0;
383 : :
384 [ # # ]: 0 : if (_PyObject_LookupAttr(type, &_Py_ID(_swappedbytes_), &tmp) < 0) {
385 : 0 : return -1;
386 : : }
387 [ # # ]: 0 : if (tmp) {
388 : 0 : Py_DECREF(tmp);
389 : 0 : big_endian = !PY_BIG_ENDIAN;
390 : : }
391 : : else {
392 : 0 : big_endian = PY_BIG_ENDIAN;
393 : : }
394 : :
395 [ # # ]: 0 : if (_PyObject_LookupAttr(type, &_Py_ID(_pack_), &tmp) < 0) {
396 : 0 : return -1;
397 : : }
398 [ # # ]: 0 : if (tmp) {
399 : 0 : pack = _PyLong_AsInt(tmp);
400 : 0 : Py_DECREF(tmp);
401 [ # # ]: 0 : if (pack < 0) {
402 [ # # # # ]: 0 : if (!PyErr_Occurred() ||
403 [ # # ]: 0 : PyErr_ExceptionMatches(PyExc_TypeError) ||
404 : 0 : PyErr_ExceptionMatches(PyExc_OverflowError))
405 : : {
406 : 0 : PyErr_SetString(PyExc_ValueError,
407 : : "_pack_ must be a non-negative integer");
408 : : }
409 : 0 : return -1;
410 : : }
411 : : }
412 : : else {
413 : : /* Setting `_pack_ = 0` amounts to using the default alignment */
414 : 0 : pack = 0;
415 : : }
416 : :
417 : 0 : len = PySequence_Size(fields);
418 [ # # ]: 0 : if (len == -1) {
419 [ # # ]: 0 : if (PyErr_ExceptionMatches(PyExc_TypeError)) {
420 : 0 : PyErr_SetString(PyExc_TypeError,
421 : : "'_fields_' must be a sequence of pairs");
422 : : }
423 : 0 : return -1;
424 : : }
425 : :
426 : 0 : stgdict = PyType_stgdict(type);
427 [ # # ]: 0 : if (!stgdict) {
428 : 0 : PyErr_SetString(PyExc_TypeError,
429 : : "ctypes state is not initialized");
430 : 0 : return -1;
431 : : }
432 : : /* If this structure/union is already marked final we cannot assign
433 : : _fields_ anymore. */
434 : :
435 [ # # ]: 0 : if (stgdict->flags & DICTFLAG_FINAL) {/* is final ? */
436 : 0 : PyErr_SetString(PyExc_AttributeError,
437 : : "_fields_ is final");
438 : 0 : return -1;
439 : : }
440 : :
441 [ # # ]: 0 : if (stgdict->format) {
442 : 0 : PyMem_Free(stgdict->format);
443 : 0 : stgdict->format = NULL;
444 : : }
445 : :
446 [ # # ]: 0 : if (stgdict->ffi_type_pointer.elements)
447 : 0 : PyMem_Free(stgdict->ffi_type_pointer.elements);
448 : :
449 : 0 : basedict = PyType_stgdict((PyObject *)((PyTypeObject *)type)->tp_base);
450 [ # # ]: 0 : if (basedict) {
451 : 0 : stgdict->flags |= (basedict->flags &
452 : : (TYPEFLAG_HASUNION | TYPEFLAG_HASBITFIELD));
453 : : }
454 [ # # ]: 0 : if (!isStruct) {
455 : 0 : stgdict->flags |= TYPEFLAG_HASUNION;
456 : : }
457 [ # # ]: 0 : if (basedict) {
458 : 0 : size = offset = basedict->size;
459 : 0 : align = basedict->align;
460 : 0 : union_size = 0;
461 [ # # ]: 0 : total_align = align ? align : 1;
462 : 0 : stgdict->ffi_type_pointer.type = FFI_TYPE_STRUCT;
463 [ # # ]: 0 : stgdict->ffi_type_pointer.elements = PyMem_New(ffi_type *, basedict->length + len + 1);
464 [ # # ]: 0 : if (stgdict->ffi_type_pointer.elements == NULL) {
465 : 0 : PyErr_NoMemory();
466 : 0 : return -1;
467 : : }
468 : 0 : memset(stgdict->ffi_type_pointer.elements, 0,
469 : 0 : sizeof(ffi_type *) * (basedict->length + len + 1));
470 [ # # ]: 0 : if (basedict->length > 0) {
471 : 0 : memcpy(stgdict->ffi_type_pointer.elements,
472 : 0 : basedict->ffi_type_pointer.elements,
473 : 0 : sizeof(ffi_type *) * (basedict->length));
474 : : }
475 : 0 : ffi_ofs = basedict->length;
476 : : } else {
477 : 0 : offset = 0;
478 : 0 : size = 0;
479 : 0 : align = 0;
480 : 0 : union_size = 0;
481 : 0 : total_align = 1;
482 : 0 : stgdict->ffi_type_pointer.type = FFI_TYPE_STRUCT;
483 [ # # ]: 0 : stgdict->ffi_type_pointer.elements = PyMem_New(ffi_type *, len + 1);
484 [ # # ]: 0 : if (stgdict->ffi_type_pointer.elements == NULL) {
485 : 0 : PyErr_NoMemory();
486 : 0 : return -1;
487 : : }
488 : 0 : memset(stgdict->ffi_type_pointer.elements, 0,
489 : 0 : sizeof(ffi_type *) * (len + 1));
490 : 0 : ffi_ofs = 0;
491 : : }
492 : :
493 : : assert(stgdict->format == NULL);
494 [ # # ]: 0 : if (isStruct) {
495 : 0 : stgdict->format = _ctypes_alloc_format_string(NULL, "T{");
496 : : } else {
497 : : /* PEP3118 doesn't support union. Use 'B' for bytes. */
498 : 0 : stgdict->format = _ctypes_alloc_format_string(NULL, "B");
499 : : }
500 [ # # ]: 0 : if (stgdict->format == NULL)
501 : 0 : return -1;
502 : :
503 [ # # ]: 0 : for (i = 0; i < len; ++i) {
504 : 0 : PyObject *name = NULL, *desc = NULL;
505 : 0 : PyObject *pair = PySequence_GetItem(fields, i);
506 : : PyObject *prop;
507 : : StgDictObject *dict;
508 : 0 : int bitsize = 0;
509 : :
510 [ # # # # ]: 0 : if (!pair || !PyArg_ParseTuple(pair, "UO|i", &name, &desc, &bitsize)) {
511 : 0 : PyErr_SetString(PyExc_TypeError,
512 : : "'_fields_' must be a sequence of (name, C type) pairs");
513 : 0 : Py_XDECREF(pair);
514 : 0 : return -1;
515 : : }
516 [ # # ]: 0 : if (PyCArrayTypeObject_Check(desc))
517 : 0 : arrays_seen = 1;
518 : 0 : dict = PyType_stgdict(desc);
519 [ # # ]: 0 : if (dict == NULL) {
520 : 0 : Py_DECREF(pair);
521 : 0 : PyErr_Format(PyExc_TypeError,
522 : : "second item in _fields_ tuple (index %zd) must be a C type",
523 : : i);
524 : 0 : return -1;
525 : : }
526 : 0 : stgdict->ffi_type_pointer.elements[ffi_ofs + i] = &dict->ffi_type_pointer;
527 [ # # ]: 0 : if (dict->flags & (TYPEFLAG_ISPOINTER | TYPEFLAG_HASPOINTER))
528 : 0 : stgdict->flags |= TYPEFLAG_HASPOINTER;
529 : 0 : stgdict->flags |= dict->flags & (TYPEFLAG_HASUNION | TYPEFLAG_HASBITFIELD);
530 : 0 : dict->flags |= DICTFLAG_FINAL; /* mark field type final */
531 [ # # ]: 0 : if (PyTuple_Size(pair) == 3) { /* bits specified */
532 : 0 : stgdict->flags |= TYPEFLAG_HASBITFIELD;
533 [ # # # ]: 0 : switch(dict->ffi_type_pointer.type) {
534 : 0 : case FFI_TYPE_UINT8:
535 : : case FFI_TYPE_UINT16:
536 : : case FFI_TYPE_UINT32:
537 : : case FFI_TYPE_SINT64:
538 : : case FFI_TYPE_UINT64:
539 : 0 : break;
540 : :
541 : 0 : case FFI_TYPE_SINT8:
542 : : case FFI_TYPE_SINT16:
543 : : case FFI_TYPE_SINT32:
544 [ # # ]: 0 : if (dict->getfunc != _ctypes_get_fielddesc("c")->getfunc
545 [ # # ]: 0 : && dict->getfunc != _ctypes_get_fielddesc("u")->getfunc
546 : : )
547 : 0 : break;
548 : : /* else fall through */
549 : : default:
550 : 0 : PyErr_Format(PyExc_TypeError,
551 : : "bit fields not allowed for type %s",
552 : 0 : ((PyTypeObject *)desc)->tp_name);
553 : 0 : Py_DECREF(pair);
554 : 0 : return -1;
555 : : }
556 [ # # # # ]: 0 : if (bitsize <= 0 || bitsize > dict->size * 8) {
557 : 0 : PyErr_SetString(PyExc_ValueError,
558 : : "number of bits invalid for bit field");
559 : 0 : Py_DECREF(pair);
560 : 0 : return -1;
561 : : }
562 : : } else
563 : 0 : bitsize = 0;
564 : :
565 [ # # ]: 0 : if (isStruct) {
566 [ # # ]: 0 : const char *fieldfmt = dict->format ? dict->format : "B";
567 : 0 : const char *fieldname = PyUnicode_AsUTF8(name);
568 : : char *ptr;
569 : : Py_ssize_t len;
570 : : char *buf;
571 : 0 : Py_ssize_t last_size = size;
572 : : Py_ssize_t padding;
573 : :
574 [ # # ]: 0 : if (fieldname == NULL)
575 : : {
576 : 0 : Py_DECREF(pair);
577 : 0 : return -1;
578 : : }
579 : :
580 : : /* construct the field now, as `prop->offset` is `offset` with
581 : : corrected alignment */
582 : 0 : prop = PyCField_FromDesc(desc, i,
583 : : &field_size, bitsize, &bitofs,
584 : : &size, &offset, &align,
585 : : pack, big_endian);
586 [ # # ]: 0 : if (prop == NULL) {
587 : 0 : Py_DECREF(pair);
588 : 0 : return -1;
589 : : }
590 : :
591 : : /* number of bytes between the end of the last field and the start
592 : : of this one */
593 : 0 : padding = ((CFieldObject *)prop)->offset - last_size;
594 : :
595 [ # # ]: 0 : if (padding > 0) {
596 : 0 : ptr = stgdict->format;
597 : 0 : stgdict->format = _ctypes_alloc_format_padding(ptr, padding);
598 : 0 : PyMem_Free(ptr);
599 [ # # ]: 0 : if (stgdict->format == NULL) {
600 : 0 : Py_DECREF(pair);
601 : 0 : Py_DECREF(prop);
602 : 0 : return -1;
603 : : }
604 : : }
605 : :
606 : 0 : len = strlen(fieldname) + strlen(fieldfmt);
607 : :
608 : 0 : buf = PyMem_Malloc(len + 2 + 1);
609 [ # # ]: 0 : if (buf == NULL) {
610 : 0 : Py_DECREF(pair);
611 : 0 : Py_DECREF(prop);
612 : 0 : PyErr_NoMemory();
613 : 0 : return -1;
614 : : }
615 : 0 : sprintf(buf, "%s:%s:", fieldfmt, fieldname);
616 : :
617 : 0 : ptr = stgdict->format;
618 [ # # ]: 0 : if (dict->shape != NULL) {
619 : 0 : stgdict->format = _ctypes_alloc_format_string_with_shape(
620 : 0 : dict->ndim, dict->shape, stgdict->format, buf);
621 : : } else {
622 : 0 : stgdict->format = _ctypes_alloc_format_string(stgdict->format, buf);
623 : : }
624 : 0 : PyMem_Free(ptr);
625 : 0 : PyMem_Free(buf);
626 : :
627 [ # # ]: 0 : if (stgdict->format == NULL) {
628 : 0 : Py_DECREF(pair);
629 : 0 : Py_DECREF(prop);
630 : 0 : return -1;
631 : : }
632 : : } else /* union */ {
633 : 0 : size = 0;
634 : 0 : offset = 0;
635 : 0 : align = 0;
636 : 0 : prop = PyCField_FromDesc(desc, i,
637 : : &field_size, bitsize, &bitofs,
638 : : &size, &offset, &align,
639 : : pack, big_endian);
640 [ # # ]: 0 : if (prop == NULL) {
641 : 0 : Py_DECREF(pair);
642 : 0 : return -1;
643 : : }
644 : 0 : union_size = max(size, union_size);
645 : : }
646 : 0 : total_align = max(align, total_align);
647 : :
648 [ # # ]: 0 : if (-1 == PyObject_SetAttr(type, name, prop)) {
649 : 0 : Py_DECREF(prop);
650 : 0 : Py_DECREF(pair);
651 : 0 : return -1;
652 : : }
653 : 0 : Py_DECREF(pair);
654 : 0 : Py_DECREF(prop);
655 : : }
656 : :
657 [ # # ]: 0 : if (!isStruct) {
658 : 0 : size = union_size;
659 : : }
660 : :
661 : : /* Adjust the size according to the alignment requirements */
662 : 0 : aligned_size = ((size + total_align - 1) / total_align) * total_align;
663 : :
664 [ # # ]: 0 : if (isStruct) {
665 : : char *ptr;
666 : : Py_ssize_t padding;
667 : :
668 : : /* Pad up to the full size of the struct */
669 : 0 : padding = aligned_size - size;
670 [ # # ]: 0 : if (padding > 0) {
671 : 0 : ptr = stgdict->format;
672 : 0 : stgdict->format = _ctypes_alloc_format_padding(ptr, padding);
673 : 0 : PyMem_Free(ptr);
674 [ # # ]: 0 : if (stgdict->format == NULL) {
675 : 0 : return -1;
676 : : }
677 : : }
678 : :
679 : 0 : ptr = stgdict->format;
680 : 0 : stgdict->format = _ctypes_alloc_format_string(stgdict->format, "}");
681 : 0 : PyMem_Free(ptr);
682 [ # # ]: 0 : if (stgdict->format == NULL)
683 : 0 : return -1;
684 : : }
685 : :
686 : 0 : stgdict->ffi_type_pointer.alignment = Py_SAFE_DOWNCAST(total_align,
687 : : Py_ssize_t,
688 : : unsigned short);
689 : 0 : stgdict->ffi_type_pointer.size = aligned_size;
690 : :
691 : 0 : stgdict->size = aligned_size;
692 : 0 : stgdict->align = total_align;
693 : 0 : stgdict->length = len; /* ADD ffi_ofs? */
694 : :
695 : : #define MAX_STRUCT_SIZE 16
696 : :
697 [ # # # # ]: 0 : if (arrays_seen && (size <= MAX_STRUCT_SIZE)) {
698 : : /*
699 : : * See bpo-22273. Arrays are normally treated as pointers, which is
700 : : * fine when an array name is being passed as parameter, but not when
701 : : * passing structures by value that contain arrays. On 64-bit Linux,
702 : : * small structures passed by value are passed in registers, and in
703 : : * order to do this, libffi needs to know the true type of the array
704 : : * members of structs. Treating them as pointers breaks things.
705 : : *
706 : : * By small structures, we mean ones that are 16 bytes or less. In that
707 : : * case, there can't be more than 16 elements after unrolling arrays,
708 : : * as we (will) disallow bitfields. So we can collect the true ffi_type
709 : : * values in a fixed-size local array on the stack and, if any arrays
710 : : * were seen, replace the ffi_type_pointer.elements with a more
711 : : * accurate set, to allow libffi to marshal them into registers
712 : : * correctly. It means one more loop over the fields, but if we got
713 : : * here, the structure is small, so there aren't too many of those.
714 : : *
715 : : * Although the passing in registers is specific to 64-bit Linux, the
716 : : * array-in-struct vs. pointer problem is general. But we restrict the
717 : : * type transformation to small structs nonetheless.
718 : : *
719 : : * Note that although a union may be small in terms of memory usage, it
720 : : * could contain many overlapping declarations of arrays, e.g.
721 : : *
722 : : * union {
723 : : * unsigned int_8 foo [16];
724 : : * unsigned uint_8 bar [16];
725 : : * unsigned int_16 baz[8];
726 : : * unsigned uint_16 bozz[8];
727 : : * unsigned int_32 fizz[4];
728 : : * unsigned uint_32 buzz[4];
729 : : * }
730 : : *
731 : : * which is still only 16 bytes in size. We need to convert this into
732 : : * the following equivalent for libffi:
733 : : *
734 : : * union {
735 : : * struct { int_8 e1; int_8 e2; ... int_8 e_16; } f1;
736 : : * struct { uint_8 e1; uint_8 e2; ... uint_8 e_16; } f2;
737 : : * struct { int_16 e1; int_16 e2; ... int_16 e_8; } f3;
738 : : * struct { uint_16 e1; uint_16 e2; ... uint_16 e_8; } f4;
739 : : * struct { int_32 e1; int_32 e2; ... int_32 e_4; } f5;
740 : : * struct { uint_32 e1; uint_32 e2; ... uint_32 e_4; } f6;
741 : : * }
742 : : *
743 : : * So the struct/union needs setting up as follows: all non-array
744 : : * elements copied across as is, and all array elements replaced with
745 : : * an equivalent struct which has as many fields as the array has
746 : : * elements, plus one NULL pointer.
747 : : */
748 : :
749 : 0 : Py_ssize_t num_ffi_type_pointers = 0; /* for the dummy fields */
750 : 0 : Py_ssize_t num_ffi_types = 0; /* for the dummy structures */
751 : : size_t alloc_size; /* total bytes to allocate */
752 : : void *type_block; /* to hold all the type information needed */
753 : : ffi_type **element_types; /* of this struct/union */
754 : : ffi_type **dummy_types; /* of the dummy struct elements */
755 : : ffi_type *structs; /* point to struct aliases of arrays */
756 : : Py_ssize_t element_index; /* index into element_types for this */
757 : 0 : Py_ssize_t dummy_index = 0; /* index into dummy field pointers */
758 : 0 : Py_ssize_t struct_index = 0; /* index into dummy structs */
759 : :
760 : : /* first pass to see how much memory to allocate */
761 [ # # ]: 0 : for (i = 0; i < len; ++i) {
762 : : PyObject *name, *desc;
763 : 0 : PyObject *pair = PySequence_GetItem(fields, i);
764 : : StgDictObject *dict;
765 : 0 : int bitsize = 0;
766 : :
767 [ # # ]: 0 : if (pair == NULL) {
768 : 0 : return -1;
769 : : }
770 [ # # ]: 0 : if (!PyArg_ParseTuple(pair, "UO|i", &name, &desc, &bitsize)) {
771 : 0 : PyErr_SetString(PyExc_TypeError,
772 : : "'_fields_' must be a sequence of (name, C type) pairs");
773 : 0 : Py_DECREF(pair);
774 : 0 : return -1;
775 : : }
776 : 0 : dict = PyType_stgdict(desc);
777 [ # # ]: 0 : if (dict == NULL) {
778 : 0 : Py_DECREF(pair);
779 : 0 : PyErr_Format(PyExc_TypeError,
780 : : "second item in _fields_ tuple (index %zd) must be a C type",
781 : : i);
782 : 0 : return -1;
783 : : }
784 [ # # ]: 0 : if (!PyCArrayTypeObject_Check(desc)) {
785 : : /* Not an array. Just need an ffi_type pointer. */
786 : 0 : num_ffi_type_pointers++;
787 : : }
788 : : else {
789 : : /* It's an array. */
790 : 0 : Py_ssize_t length = dict->length;
791 : : StgDictObject *edict;
792 : :
793 : 0 : edict = PyType_stgdict(dict->proto);
794 [ # # ]: 0 : if (edict == NULL) {
795 : 0 : Py_DECREF(pair);
796 : 0 : PyErr_Format(PyExc_TypeError,
797 : : "second item in _fields_ tuple (index %zd) must be a C type",
798 : : i);
799 : 0 : return -1;
800 : : }
801 : : /*
802 : : * We need one extra ffi_type to hold the struct, and one
803 : : * ffi_type pointer per array element + one for a NULL to
804 : : * mark the end.
805 : : */
806 : 0 : num_ffi_types++;
807 : 0 : num_ffi_type_pointers += length + 1;
808 : : }
809 : 0 : Py_DECREF(pair);
810 : : }
811 : :
812 : : /*
813 : : * At this point, we know we need storage for some ffi_types and some
814 : : * ffi_type pointers. We'll allocate these in one block.
815 : : * There are three sub-blocks of information: the ffi_type pointers to
816 : : * this structure/union's elements, the ffi_type_pointers to the
817 : : * dummy fields standing in for array elements, and the
818 : : * ffi_types representing the dummy structures.
819 : : */
820 : 0 : alloc_size = (ffi_ofs + 1 + len + num_ffi_type_pointers) * sizeof(ffi_type *) +
821 : : num_ffi_types * sizeof(ffi_type);
822 : 0 : type_block = PyMem_Malloc(alloc_size);
823 : :
824 [ # # ]: 0 : if (type_block == NULL) {
825 : 0 : PyErr_NoMemory();
826 : 0 : return -1;
827 : : }
828 : : /*
829 : : * the first block takes up ffi_ofs + len + 1 which is the pointers *
830 : : * for this struct/union. The second block takes up
831 : : * num_ffi_type_pointers, so the sum of these is ffi_ofs + len + 1 +
832 : : * num_ffi_type_pointers as allocated above. The last bit is the
833 : : * num_ffi_types structs.
834 : : */
835 : 0 : element_types = (ffi_type **) type_block;
836 : 0 : dummy_types = &element_types[ffi_ofs + len + 1];
837 : 0 : structs = (ffi_type *) &dummy_types[num_ffi_type_pointers];
838 : :
839 [ # # ]: 0 : if (num_ffi_types > 0) {
840 : 0 : memset(structs, 0, num_ffi_types * sizeof(ffi_type));
841 : : }
842 [ # # # # ]: 0 : if (ffi_ofs && (basedict != NULL)) {
843 : 0 : memcpy(element_types,
844 : 0 : basedict->ffi_type_pointer.elements,
845 : : ffi_ofs * sizeof(ffi_type *));
846 : : }
847 : 0 : element_index = ffi_ofs;
848 : :
849 : : /* second pass to actually set the type pointers */
850 [ # # ]: 0 : for (i = 0; i < len; ++i) {
851 : : PyObject *name, *desc;
852 : 0 : PyObject *pair = PySequence_GetItem(fields, i);
853 : : StgDictObject *dict;
854 : 0 : int bitsize = 0;
855 : :
856 [ # # ]: 0 : if (pair == NULL) {
857 : 0 : PyMem_Free(type_block);
858 : 0 : return -1;
859 : : }
860 : : /* In theory, we made this call in the first pass, so it *shouldn't*
861 : : * fail. However, you never know, and the code above might change
862 : : * later - keeping the check in here is a tad defensive but it
863 : : * will affect program size only slightly and performance hardly at
864 : : * all.
865 : : */
866 [ # # ]: 0 : if (!PyArg_ParseTuple(pair, "UO|i", &name, &desc, &bitsize)) {
867 : 0 : PyErr_SetString(PyExc_TypeError,
868 : : "'_fields_' must be a sequence of (name, C type) pairs");
869 : 0 : Py_DECREF(pair);
870 : 0 : PyMem_Free(type_block);
871 : 0 : return -1;
872 : : }
873 : 0 : dict = PyType_stgdict(desc);
874 : : /* Possibly this check could be avoided, but see above comment. */
875 [ # # ]: 0 : if (dict == NULL) {
876 : 0 : Py_DECREF(pair);
877 : 0 : PyMem_Free(type_block);
878 : 0 : PyErr_Format(PyExc_TypeError,
879 : : "second item in _fields_ tuple (index %zd) must be a C type",
880 : : i);
881 : 0 : return -1;
882 : : }
883 : : assert(element_index < (ffi_ofs + len)); /* will be used below */
884 [ # # ]: 0 : if (!PyCArrayTypeObject_Check(desc)) {
885 : : /* Not an array. Just copy over the element ffi_type. */
886 : 0 : element_types[element_index++] = &dict->ffi_type_pointer;
887 : : }
888 : : else {
889 : 0 : Py_ssize_t length = dict->length;
890 : : StgDictObject *edict;
891 : :
892 : 0 : edict = PyType_stgdict(dict->proto);
893 [ # # ]: 0 : if (edict == NULL) {
894 : 0 : Py_DECREF(pair);
895 : 0 : PyMem_Free(type_block);
896 : 0 : PyErr_Format(PyExc_TypeError,
897 : : "second item in _fields_ tuple (index %zd) must be a C type",
898 : : i);
899 : 0 : return -1;
900 : : }
901 : 0 : element_types[element_index++] = &structs[struct_index];
902 : 0 : structs[struct_index].size = length * edict->ffi_type_pointer.size;
903 : 0 : structs[struct_index].alignment = edict->ffi_type_pointer.alignment;
904 : 0 : structs[struct_index].type = FFI_TYPE_STRUCT;
905 : 0 : structs[struct_index].elements = &dummy_types[dummy_index];
906 : 0 : ++struct_index;
907 : : /* Copy over the element's type, length times. */
908 [ # # ]: 0 : while (length > 0) {
909 : : assert(dummy_index < (num_ffi_type_pointers));
910 : 0 : dummy_types[dummy_index++] = &edict->ffi_type_pointer;
911 : 0 : length--;
912 : : }
913 : : assert(dummy_index < (num_ffi_type_pointers));
914 : 0 : dummy_types[dummy_index++] = NULL;
915 : : }
916 : 0 : Py_DECREF(pair);
917 : : }
918 : :
919 : 0 : element_types[element_index] = NULL;
920 : : /*
921 : : * Replace the old elements with the new, taking into account
922 : : * base class elements where necessary.
923 : : */
924 : : assert(stgdict->ffi_type_pointer.elements);
925 : 0 : PyMem_Free(stgdict->ffi_type_pointer.elements);
926 : 0 : stgdict->ffi_type_pointer.elements = element_types;
927 : : }
928 : :
929 : : /* We did check that this flag was NOT set above, it must not
930 : : have been set until now. */
931 [ # # ]: 0 : if (stgdict->flags & DICTFLAG_FINAL) {
932 : 0 : PyErr_SetString(PyExc_AttributeError,
933 : : "Structure or union cannot contain itself");
934 : 0 : return -1;
935 : : }
936 : 0 : stgdict->flags |= DICTFLAG_FINAL;
937 : :
938 : 0 : return MakeAnonFields(type);
939 : : }
|