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 = self->ob_type;
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_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_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_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 #ifdef CTYPES_UNICODE
542                     && dict->getfunc != _ctypes_get_fielddesc("u")->getfunc
543 #endif
544                     )
545                     break;
546                 /* else fall through */
547             default:
548                 PyErr_Format(PyExc_TypeError,
549                              "bit fields not allowed for type %s",
550                              ((PyTypeObject *)desc)->tp_name);
551                 Py_DECREF(pair);
552                 return -1;
553             }
554             if (bitsize <= 0 || bitsize > dict->size * 8) {
555                 PyErr_SetString(PyExc_ValueError,
556                                 "number of bits invalid for bit field");
557                 Py_DECREF(pair);
558                 return -1;
559             }
560         } else
561             bitsize = 0;
562 
563         if (isStruct && !isPacked) {
564             const char *fieldfmt = dict->format ? dict->format : "B";
565             const char *fieldname = PyUnicode_AsUTF8(name);
566             char *ptr;
567             Py_ssize_t len;
568             char *buf;
569 
570             if (fieldname == NULL)
571             {
572                 Py_DECREF(pair);
573                 return -1;
574             }
575 
576             len = strlen(fieldname) + strlen(fieldfmt);
577 
578             buf = PyMem_Malloc(len + 2 + 1);
579             if (buf == NULL) {
580                 Py_DECREF(pair);
581                 PyErr_NoMemory();
582                 return -1;
583             }
584             sprintf(buf, "%s:%s:", fieldfmt, fieldname);
585 
586             ptr = stgdict->format;
587             if (dict->shape != NULL) {
588                 stgdict->format = _ctypes_alloc_format_string_with_shape(
589                     dict->ndim, dict->shape, stgdict->format, buf);
590             } else {
591                 stgdict->format = _ctypes_alloc_format_string(stgdict->format, buf);
592             }
593             PyMem_Free(ptr);
594             PyMem_Free(buf);
595 
596             if (stgdict->format == NULL) {
597                 Py_DECREF(pair);
598                 return -1;
599             }
600         }
601 
602         if (isStruct) {
603             prop = PyCField_FromDesc(desc, i,
604                                    &field_size, bitsize, &bitofs,
605                                    &size, &offset, &align,
606                                    pack, big_endian);
607         } else /* union */ {
608             size = 0;
609             offset = 0;
610             align = 0;
611             prop = PyCField_FromDesc(desc, i,
612                                    &field_size, bitsize, &bitofs,
613                                    &size, &offset, &align,
614                                    pack, big_endian);
615             union_size = max(size, union_size);
616         }
617         total_align = max(align, total_align);
618 
619         if (!prop) {
620             Py_DECREF(pair);
621             return -1;
622         }
623         if (-1 == PyObject_SetAttr(type, name, prop)) {
624             Py_DECREF(prop);
625             Py_DECREF(pair);
626             return -1;
627         }
628         Py_DECREF(pair);
629         Py_DECREF(prop);
630     }
631 #undef realdict
632 
633     if (isStruct && !isPacked) {
634         char *ptr = stgdict->format;
635         stgdict->format = _ctypes_alloc_format_string(stgdict->format, "}");
636         PyMem_Free(ptr);
637         if (stgdict->format == NULL)
638             return -1;
639     }
640 
641     if (!isStruct)
642         size = union_size;
643 
644     /* Adjust the size according to the alignment requirements */
645     size = ((size + total_align - 1) / total_align) * total_align;
646 
647     stgdict->ffi_type_pointer.alignment = Py_SAFE_DOWNCAST(total_align,
648                                                            Py_ssize_t,
649                                                            unsigned short);
650     stgdict->ffi_type_pointer.size = size;
651 
652     stgdict->size = size;
653     stgdict->align = total_align;
654     stgdict->length = len;      /* ADD ffi_ofs? */
655 
656 #define MAX_STRUCT_SIZE 16
657 
658     if (arrays_seen && (size <= MAX_STRUCT_SIZE)) {
659         /*
660          * See bpo-22273. Arrays are normally treated as pointers, which is
661          * fine when an array name is being passed as parameter, but not when
662          * passing structures by value that contain arrays. On 64-bit Linux,
663          * small structures passed by value are passed in registers, and in
664          * order to do this, libffi needs to know the true type of the array
665          * members of structs. Treating them as pointers breaks things.
666          *
667          * By small structures, we mean ones that are 16 bytes or less. In that
668          * case, there can't be more than 16 elements after unrolling arrays,
669          * as we (will) disallow bitfields. So we can collect the true ffi_type
670          * values in a fixed-size local array on the stack and, if any arrays
671          * were seen, replace the ffi_type_pointer.elements with a more
672          * accurate set, to allow libffi to marshal them into registers
673          * correctly. It means one more loop over the fields, but if we got
674          * here, the structure is small, so there aren't too many of those.
675          *
676          * Although the passing in registers is specific to 64-bit Linux, the
677          * array-in-struct vs. pointer problem is general. But we restrict the
678          * type transformation to small structs nonetheless.
679          *
680          * Note that although a union may be small in terms of memory usage, it
681          * could contain many overlapping declarations of arrays, e.g.
682          *
683          * union {
684          *     unsigned int_8 foo [16];
685          *     unsigned uint_8 bar [16];
686          *     unsigned int_16 baz[8];
687          *     unsigned uint_16 bozz[8];
688          *     unsigned int_32 fizz[4];
689          *     unsigned uint_32 buzz[4];
690          * }
691          *
692          * which is still only 16 bytes in size. We need to convert this into
693          * the following equivalent for libffi:
694          *
695          * union {
696          *     struct { int_8 e1; int_8 e2; ... int_8 e_16; } f1;
697          *     struct { uint_8 e1; uint_8 e2; ... uint_8 e_16; } f2;
698          *     struct { int_16 e1; int_16 e2; ... int_16 e_8; } f3;
699          *     struct { uint_16 e1; uint_16 e2; ... uint_16 e_8; } f4;
700          *     struct { int_32 e1; int_32 e2; ... int_32 e_4; } f5;
701          *     struct { uint_32 e1; uint_32 e2; ... uint_32 e_4; } f6;
702          * }
703          *
704          * So the struct/union needs setting up as follows: all non-array
705          * elements copied across as is, and all array elements replaced with
706          * an equivalent struct which has as many fields as the array has
707          * elements, plus one NULL pointer.
708          */
709 
710         Py_ssize_t num_ffi_type_pointers = 0;  /* for the dummy fields */
711         Py_ssize_t num_ffi_types = 0;  /* for the dummy structures */
712         size_t alloc_size;  /* total bytes to allocate */
713         void *type_block;  /* to hold all the type information needed */
714         ffi_type **element_types;  /* of this struct/union */
715         ffi_type **dummy_types;  /* of the dummy struct elements */
716         ffi_type *structs;  /* point to struct aliases of arrays */
717         Py_ssize_t element_index;  /* index into element_types for this */
718         Py_ssize_t dummy_index = 0; /* index into dummy field pointers */
719         Py_ssize_t struct_index = 0; /* index into dummy structs */
720 
721         /* first pass to see how much memory to allocate */
722         for (i = 0; i < len; ++i) {
723             PyObject *name, *desc;
724             PyObject *pair = PySequence_GetItem(fields, i);
725             StgDictObject *dict;
726             int bitsize = 0;
727 
728             if (pair == NULL) {
729                 return -1;
730             }
731             if (!PyArg_ParseTuple(pair, "UO|i", &name, &desc, &bitsize)) {
732                 PyErr_SetString(PyExc_TypeError,
733                     "'_fields_' must be a sequence of (name, C type) pairs");
734                 Py_DECREF(pair);
735                 return -1;
736             }
737             dict = PyType_stgdict(desc);
738             if (dict == NULL) {
739                 Py_DECREF(pair);
740                 PyErr_Format(PyExc_TypeError,
741                     "second item in _fields_ tuple (index %zd) must be a C type",
742                     i);
743                 return -1;
744             }
745             if (!PyCArrayTypeObject_Check(desc)) {
746                 /* Not an array. Just need an ffi_type pointer. */
747                 num_ffi_type_pointers++;
748             }
749             else {
750                 /* It's an array. */
751                 Py_ssize_t length = dict->length;
752                 StgDictObject *edict;
753 
754                 edict = PyType_stgdict(dict->proto);
755                 if (edict == NULL) {
756                     Py_DECREF(pair);
757                     PyErr_Format(PyExc_TypeError,
758                         "second item in _fields_ tuple (index %zd) must be a C type",
759                         i);
760                     return -1;
761                 }
762                 /*
763                  * We need one extra ffi_type to hold the struct, and one
764                  * ffi_type pointer per array element + one for a NULL to
765                  * mark the end.
766                  */
767                 num_ffi_types++;
768                 num_ffi_type_pointers += length + 1;
769             }
770             Py_DECREF(pair);
771         }
772 
773         /*
774          * At this point, we know we need storage for some ffi_types and some
775          * ffi_type pointers. We'll allocate these in one block.
776          * There are three sub-blocks of information: the ffi_type pointers to
777          * this structure/union's elements, the ffi_type_pointers to the
778          * dummy fields standing in for array elements, and the
779          * ffi_types representing the dummy structures.
780          */
781         alloc_size = (ffi_ofs + 1 + len + num_ffi_type_pointers) * sizeof(ffi_type *) +
782                         num_ffi_types * sizeof(ffi_type);
783         type_block = PyMem_Malloc(alloc_size);
784 
785         if (type_block == NULL) {
786             PyErr_NoMemory();
787             return -1;
788         }
789         /*
790          * the first block takes up ffi_ofs + len + 1 which is the pointers *
791          * for this struct/union. The second block takes up
792          * num_ffi_type_pointers, so the sum of these is ffi_ofs + len + 1 +
793          * num_ffi_type_pointers as allocated above. The last bit is the
794          * num_ffi_types structs.
795          */
796         element_types = (ffi_type **) type_block;
797         dummy_types = &element_types[ffi_ofs + len + 1];
798         structs = (ffi_type *) &dummy_types[num_ffi_type_pointers];
799 
800         if (num_ffi_types > 0) {
801             memset(structs, 0, num_ffi_types * sizeof(ffi_type));
802         }
803         if (ffi_ofs && (basedict != NULL)) {
804             memcpy(element_types,
805                 basedict->ffi_type_pointer.elements,
806                 ffi_ofs * sizeof(ffi_type *));
807         }
808         element_index = ffi_ofs;
809 
810         /* second pass to actually set the type pointers */
811         for (i = 0; i < len; ++i) {
812             PyObject *name, *desc;
813             PyObject *pair = PySequence_GetItem(fields, i);
814             StgDictObject *dict;
815             int bitsize = 0;
816 
817             if (pair == NULL) {
818                 PyMem_Free(type_block);
819                 return -1;
820             }
821             /* In theory, we made this call in the first pass, so it *shouldn't*
822              * fail. However, you never know, and the code above might change
823              * later - keeping the check in here is a tad defensive but it
824              * will affect program size only slightly and performance hardly at
825              * all.
826              */
827             if (!PyArg_ParseTuple(pair, "UO|i", &name, &desc, &bitsize)) {
828                 PyErr_SetString(PyExc_TypeError,
829                                 "'_fields_' must be a sequence of (name, C type) pairs");
830                 Py_DECREF(pair);
831                 PyMem_Free(type_block);
832                 return -1;
833             }
834             dict = PyType_stgdict(desc);
835             /* Possibly this check could be avoided, but see above comment. */
836             if (dict == NULL) {
837                 Py_DECREF(pair);
838                 PyMem_Free(type_block);
839                 PyErr_Format(PyExc_TypeError,
840                              "second item in _fields_ tuple (index %zd) must be a C type",
841                              i);
842                 return -1;
843             }
844             assert(element_index < (ffi_ofs + len)); /* will be used below */
845             if (!PyCArrayTypeObject_Check(desc)) {
846                 /* Not an array. Just copy over the element ffi_type. */
847                 element_types[element_index++] = &dict->ffi_type_pointer;
848             }
849             else {
850                 Py_ssize_t length = dict->length;
851                 StgDictObject *edict;
852 
853                 edict = PyType_stgdict(dict->proto);
854                 if (edict == NULL) {
855                     Py_DECREF(pair);
856                     PyMem_Free(type_block);
857                     PyErr_Format(PyExc_TypeError,
858                                  "second item in _fields_ tuple (index %zd) must be a C type",
859                                  i);
860                     return -1;
861                 }
862                 element_types[element_index++] = &structs[struct_index];
863                 structs[struct_index].size = length * edict->ffi_type_pointer.size;
864                 structs[struct_index].alignment = edict->ffi_type_pointer.alignment;
865                 structs[struct_index].type = FFI_TYPE_STRUCT;
866                 structs[struct_index].elements = &dummy_types[dummy_index];
867                 ++struct_index;
868                 /* Copy over the element's type, length times. */
869                 while (length > 0) {
870                     assert(dummy_index < (num_ffi_type_pointers));
871                     dummy_types[dummy_index++] = &edict->ffi_type_pointer;
872                     length--;
873                 }
874                 assert(dummy_index < (num_ffi_type_pointers));
875                 dummy_types[dummy_index++] = NULL;
876             }
877             Py_DECREF(pair);
878         }
879 
880         element_types[element_index] = NULL;
881         /*
882          * Replace the old elements with the new, taking into account
883          * base class elements where necessary.
884          */
885         assert(stgdict->ffi_type_pointer.elements);
886         PyMem_Free(stgdict->ffi_type_pointer.elements);
887         stgdict->ffi_type_pointer.elements = element_types;
888     }
889 
890     /* We did check that this flag was NOT set above, it must not
891        have been set until now. */
892     if (stgdict->flags & DICTFLAG_FINAL) {
893         PyErr_SetString(PyExc_AttributeError,
894                         "Structure or union cannot contain itself");
895         return -1;
896     }
897     stgdict->flags |= DICTFLAG_FINAL;
898 
899     return MakeAnonFields(type);
900 }
901