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