(root)/
Python-3.12.0/
Modules/
_ctypes/
stgdict.c
       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  }