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