Home | History | Annotate | Download | only in _ctypes
      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
     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
     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
     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 int
     52 PyCStgDict_clone(StgDictObject *dst, StgDictObject *src)
     53 {
     54     char *d, *s;
     55     Py_ssize_t size;
     56 
     57     PyCStgDict_clear(dst);
     58     PyMem_Free(dst->ffi_type_pointer.elements);
     59     PyMem_Free(dst->format);
     60     dst->format = NULL;
     61     PyMem_Free(dst->shape);
     62     dst->shape = NULL;
     63     dst->ffi_type_pointer.elements = NULL;
     64 
     65     d = (char *)dst;
     66     s = (char *)src;
     67     memcpy(d + sizeof(PyDictObject),
     68            s + sizeof(PyDictObject),
     69            sizeof(StgDictObject) - sizeof(PyDictObject));
     70 
     71     Py_XINCREF(dst->proto);
     72     Py_XINCREF(dst->argtypes);
     73     Py_XINCREF(dst->converters);
     74     Py_XINCREF(dst->restype);
     75     Py_XINCREF(dst->checker);
     76 
     77     if (src->format) {
     78         dst->format = PyMem_Malloc(strlen(src->format) + 1);
     79         if (dst->format == NULL) {
     80             PyErr_NoMemory();
     81             return -1;
     82         }
     83         strcpy(dst->format, src->format);
     84     }
     85     if (src->shape) {
     86         dst->shape = PyMem_Malloc(sizeof(Py_ssize_t) * src->ndim);
     87         if (dst->shape == NULL) {
     88             PyErr_NoMemory();
     89             return -1;
     90         }
     91         memcpy(dst->shape, src->shape,
     92                sizeof(Py_ssize_t) * src->ndim);
     93     }
     94 
     95     if (src->ffi_type_pointer.elements == NULL)
     96         return 0;
     97     size = sizeof(ffi_type *) * (src->length + 1);
     98     dst->ffi_type_pointer.elements = PyMem_Malloc(size);
     99     if (dst->ffi_type_pointer.elements == NULL) {
    100         PyErr_NoMemory();
    101         return -1;
    102     }
    103     memcpy(dst->ffi_type_pointer.elements,
    104            src->ffi_type_pointer.elements,
    105            size);
    106     return 0;
    107 }
    108 
    109 PyTypeObject PyCStgDict_Type = {
    110     PyVarObject_HEAD_INIT(NULL, 0)
    111     "StgDict",
    112     sizeof(StgDictObject),
    113     0,
    114     (destructor)PyCStgDict_dealloc,             /* tp_dealloc */
    115     0,                                          /* tp_print */
    116     0,                                          /* tp_getattr */
    117     0,                                          /* tp_setattr */
    118     0,                                          /* tp_compare */
    119     0,                                          /* tp_repr */
    120     0,                                          /* tp_as_number */
    121     0,                                          /* tp_as_sequence */
    122     0,                                          /* tp_as_mapping */
    123     0,                                          /* tp_hash */
    124     0,                                          /* tp_call */
    125     0,                                          /* tp_str */
    126     0,                                          /* tp_getattro */
    127     0,                                          /* tp_setattro */
    128     0,                                          /* tp_as_buffer */
    129     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
    130     0,                                          /* tp_doc */
    131     0,                                          /* tp_traverse */
    132     0,                                          /* tp_clear */
    133     0,                                          /* tp_richcompare */
    134     0,                                          /* tp_weaklistoffset */
    135     0,                                          /* tp_iter */
    136     0,                                          /* tp_iternext */
    137     0,                                          /* tp_methods */
    138     0,                                          /* tp_members */
    139     0,                                          /* tp_getset */
    140     0,                                          /* tp_base */
    141     0,                                          /* tp_dict */
    142     0,                                          /* tp_descr_get */
    143     0,                                          /* tp_descr_set */
    144     0,                                          /* tp_dictoffset */
    145     (initproc)PyCStgDict_init,                          /* tp_init */
    146     0,                                          /* tp_alloc */
    147     0,                                          /* tp_new */
    148     0,                                          /* tp_free */
    149 };
    150 
    151 /* May return NULL, but does not set an exception! */
    152 StgDictObject *
    153 PyType_stgdict(PyObject *obj)
    154 {
    155     PyTypeObject *type;
    156 
    157     if (!PyType_Check(obj))
    158         return NULL;
    159     type = (PyTypeObject *)obj;
    160     if (!PyType_HasFeature(type, Py_TPFLAGS_HAVE_CLASS))
    161         return NULL;
    162     if (!type->tp_dict || !PyCStgDict_CheckExact(type->tp_dict))
    163         return NULL;
    164     return (StgDictObject *)type->tp_dict;
    165 }
    166 
    167 /* May return NULL, but does not set an exception! */
    168 /*
    169   This function should be as fast as possible, so we don't call PyType_stgdict
    170   above but inline the code, and avoid the PyType_Check().
    171 */
    172 StgDictObject *
    173 PyObject_stgdict(PyObject *self)
    174 {
    175     PyTypeObject *type = self->ob_type;
    176     if (!PyType_HasFeature(type, Py_TPFLAGS_HAVE_CLASS))
    177         return NULL;
    178     if (!type->tp_dict || !PyCStgDict_CheckExact(type->tp_dict))
    179         return NULL;
    180     return (StgDictObject *)type->tp_dict;
    181 }
    182 
    183 /* descr is the descriptor for a field marked as anonymous.  Get all the
    184  _fields_ descriptors from descr->proto, create new descriptors with offset
    185  and index adjusted, and stuff them into type.
    186  */
    187 static int
    188 MakeFields(PyObject *type, CFieldObject *descr,
    189            Py_ssize_t index, Py_ssize_t offset)
    190 {
    191     Py_ssize_t i;
    192     PyObject *fields;
    193     PyObject *fieldlist;
    194 
    195     fields = PyObject_GetAttrString(descr->proto, "_fields_");
    196     if (fields == NULL)
    197         return -1;
    198     fieldlist = PySequence_Fast(fields, "_fields_ must be a sequence");
    199     Py_DECREF(fields);
    200     if (fieldlist == NULL)
    201         return -1;
    202 
    203     for (i = 0; i < PySequence_Fast_GET_SIZE(fieldlist); ++i) {
    204         PyObject *pair = PySequence_Fast_GET_ITEM(fieldlist, i); /* borrowed */
    205         PyObject *fname, *ftype, *bits;
    206         CFieldObject *fdescr;
    207         CFieldObject *new_descr;
    208         /* Convert to PyArg_UnpackTuple... */
    209         if (!PyArg_ParseTuple(pair, "OO|O", &fname, &ftype, &bits)) {
    210             Py_DECREF(fieldlist);
    211             return -1;
    212         }
    213         fdescr = (CFieldObject *)PyObject_GetAttr(descr->proto, fname);
    214         if (fdescr == NULL) {
    215             Py_DECREF(fieldlist);
    216             return -1;
    217         }
    218         if (Py_TYPE(fdescr) != &PyCField_Type) {
    219             PyErr_SetString(PyExc_TypeError, "unexpected type");
    220             Py_DECREF(fdescr);
    221             Py_DECREF(fieldlist);
    222             return -1;
    223         }
    224         if (fdescr->anonymous) {
    225             int rc = MakeFields(type, fdescr,
    226                                 index + fdescr->index,
    227                                 offset + fdescr->offset);
    228             Py_DECREF(fdescr);
    229             if (rc == -1) {
    230                 Py_DECREF(fieldlist);
    231                 return -1;
    232             }
    233             continue;
    234         }
    235         new_descr = (CFieldObject *)PyObject_CallObject((PyObject *)&PyCField_Type, NULL);
    236         if (new_descr == NULL) {
    237             Py_DECREF(fdescr);
    238             Py_DECREF(fieldlist);
    239             return -1;
    240         }
    241         assert(Py_TYPE(new_descr) == &PyCField_Type);
    242         new_descr->size = fdescr->size;
    243         new_descr->offset = fdescr->offset + offset;
    244         new_descr->index = fdescr->index + index;
    245         new_descr->proto = fdescr->proto;
    246         Py_XINCREF(new_descr->proto);
    247         new_descr->getfunc = fdescr->getfunc;
    248         new_descr->setfunc = fdescr->setfunc;
    249 
    250         Py_DECREF(fdescr);
    251 
    252         if (-1 == PyObject_SetAttr(type, fname, (PyObject *)new_descr)) {
    253             Py_DECREF(fieldlist);
    254             Py_DECREF(new_descr);
    255             return -1;
    256         }
    257         Py_DECREF(new_descr);
    258     }
    259     Py_DECREF(fieldlist);
    260     return 0;
    261 }
    262 
    263 /* Iterate over the names in the type's _anonymous_ attribute, if present,
    264  */
    265 static int
    266 MakeAnonFields(PyObject *type)
    267 {
    268     PyObject *anon;
    269     PyObject *anon_names;
    270     Py_ssize_t i;
    271 
    272     anon = PyObject_GetAttrString(type, "_anonymous_");
    273     if (anon == NULL) {
    274         PyErr_Clear();
    275         return 0;
    276     }
    277     anon_names = PySequence_Fast(anon, "_anonymous_ must be a sequence");
    278     Py_DECREF(anon);
    279     if (anon_names == NULL)
    280         return -1;
    281 
    282     for (i = 0; i < PySequence_Fast_GET_SIZE(anon_names); ++i) {
    283         PyObject *fname = PySequence_Fast_GET_ITEM(anon_names, i); /* borrowed */
    284         CFieldObject *descr = (CFieldObject *)PyObject_GetAttr(type, fname);
    285         if (descr == NULL) {
    286             Py_DECREF(anon_names);
    287             return -1;
    288         }
    289         assert(Py_TYPE(descr) == &PyCField_Type);
    290         descr->anonymous = 1;
    291 
    292         /* descr is in the field descriptor. */
    293         if (-1 == MakeFields(type, (CFieldObject *)descr,
    294                              ((CFieldObject *)descr)->index,
    295                              ((CFieldObject *)descr)->offset)) {
    296             Py_DECREF(descr);
    297             Py_DECREF(anon_names);
    298             return -1;
    299         }
    300         Py_DECREF(descr);
    301     }
    302 
    303     Py_DECREF(anon_names);
    304     return 0;
    305 }
    306 
    307 /*
    308   Retrive the (optional) _pack_ attribute from a type, the _fields_ attribute,
    309   and create an StgDictObject.  Used for Structure and Union subclasses.
    310 */
    311 int
    312 PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct)
    313 {
    314     StgDictObject *stgdict, *basedict;
    315     Py_ssize_t len, offset, size, align, i;
    316     Py_ssize_t union_size, total_align;
    317     Py_ssize_t field_size = 0;
    318     int bitofs;
    319     PyObject *isPacked;
    320     int pack = 0;
    321     Py_ssize_t ffi_ofs;
    322     int big_endian;
    323 
    324     /* HACK Alert: I cannot be bothered to fix ctypes.com, so there has to
    325        be a way to use the old, broken sematics: _fields_ are not extended
    326        but replaced in subclasses.
    327 
    328        XXX Remove this in ctypes 1.0!
    329     */
    330     int use_broken_old_ctypes_semantics;
    331 
    332     if (fields == NULL)
    333         return 0;
    334 
    335 #ifdef WORDS_BIGENDIAN
    336     big_endian = PyObject_HasAttrString(type, "_swappedbytes_") ? 0 : 1;
    337 #else
    338     big_endian = PyObject_HasAttrString(type, "_swappedbytes_") ? 1 : 0;
    339 #endif
    340 
    341     use_broken_old_ctypes_semantics = \
    342         PyObject_HasAttrString(type, "_use_broken_old_ctypes_structure_semantics_");
    343 
    344     isPacked = PyObject_GetAttrString(type, "_pack_");
    345     if (isPacked) {
    346         pack = _PyInt_AsInt(isPacked);
    347         if (pack < 0 || PyErr_Occurred()) {
    348             Py_XDECREF(isPacked);
    349             PyErr_SetString(PyExc_ValueError,
    350                             "_pack_ must be a non-negative integer");
    351             return -1;
    352         }
    353         Py_DECREF(isPacked);
    354     } else
    355         PyErr_Clear();
    356 
    357     len = PySequence_Length(fields);
    358     if (len == -1) {
    359         PyErr_SetString(PyExc_TypeError,
    360                         "'_fields_' must be a sequence of pairs");
    361         return -1;
    362     }
    363 
    364     stgdict = PyType_stgdict(type);
    365     if (!stgdict)
    366         return -1;
    367     /* If this structure/union is already marked final we cannot assign
    368        _fields_ anymore. */
    369 
    370     if (stgdict->flags & DICTFLAG_FINAL) {/* is final ? */
    371         PyErr_SetString(PyExc_AttributeError,
    372                         "_fields_ is final");
    373         return -1;
    374     }
    375 
    376     if (stgdict->format) {
    377         PyMem_Free(stgdict->format);
    378         stgdict->format = NULL;
    379     }
    380 
    381     if (stgdict->ffi_type_pointer.elements)
    382         PyMem_Free(stgdict->ffi_type_pointer.elements);
    383 
    384     basedict = PyType_stgdict((PyObject *)((PyTypeObject *)type)->tp_base);
    385     if (basedict && !use_broken_old_ctypes_semantics) {
    386         size = offset = basedict->size;
    387         align = basedict->align;
    388         union_size = 0;
    389         total_align = align ? align : 1;
    390         stgdict->ffi_type_pointer.type = FFI_TYPE_STRUCT;
    391         stgdict->ffi_type_pointer.elements = PyMem_New(ffi_type *, basedict->length + len + 1);
    392         if (stgdict->ffi_type_pointer.elements == NULL) {
    393             PyErr_NoMemory();
    394             return -1;
    395         }
    396         memset(stgdict->ffi_type_pointer.elements, 0,
    397                sizeof(ffi_type *) * (basedict->length + len + 1));
    398         if (basedict->length > 0) {
    399             memcpy(stgdict->ffi_type_pointer.elements,
    400                    basedict->ffi_type_pointer.elements,
    401                    sizeof(ffi_type *) * (basedict->length));
    402         }
    403         ffi_ofs = basedict->length;
    404     } else {
    405         offset = 0;
    406         size = 0;
    407         align = 0;
    408         union_size = 0;
    409         total_align = 1;
    410         stgdict->ffi_type_pointer.type = FFI_TYPE_STRUCT;
    411         stgdict->ffi_type_pointer.elements = PyMem_New(ffi_type *, len + 1);
    412         if (stgdict->ffi_type_pointer.elements == NULL) {
    413             PyErr_NoMemory();
    414             return -1;
    415         }
    416         memset(stgdict->ffi_type_pointer.elements, 0,
    417                sizeof(ffi_type *) * (len + 1));
    418         ffi_ofs = 0;
    419     }
    420 
    421     assert(stgdict->format == NULL);
    422     if (isStruct && !isPacked) {
    423         stgdict->format = _ctypes_alloc_format_string(NULL, "T{");
    424     } else {
    425         /* PEP3118 doesn't support union, or packed structures (well,
    426            only standard packing, but we dont support the pep for
    427            that). Use 'B' for bytes. */
    428         stgdict->format = _ctypes_alloc_format_string(NULL, "B");
    429     }
    430 
    431 #define realdict ((PyObject *)&stgdict->dict)
    432     for (i = 0; i < len; ++i) {
    433         PyObject *name = NULL, *desc = NULL;
    434         PyObject *pair = PySequence_GetItem(fields, i);
    435         PyObject *prop;
    436         StgDictObject *dict;
    437         int bitsize = 0;
    438 
    439         if (!pair || !PyArg_ParseTuple(pair, "OO|i", &name, &desc, &bitsize)) {
    440             PyErr_SetString(PyExc_AttributeError,
    441                             "'_fields_' must be a sequence of pairs");
    442             Py_XDECREF(pair);
    443             return -1;
    444         }
    445         dict = PyType_stgdict(desc);
    446         if (dict == NULL) {
    447             Py_DECREF(pair);
    448             PyErr_Format(PyExc_TypeError,
    449 #if (PY_VERSION_HEX < 0x02050000)
    450                          /* Compatibility no longer strictly required */
    451                          "second item in _fields_ tuple (index %d) must be a C type",
    452 #else
    453                          "second item in _fields_ tuple (index %zd) must be a C type",
    454 #endif
    455                          i);
    456             return -1;
    457         }
    458         stgdict->ffi_type_pointer.elements[ffi_ofs + i] = &dict->ffi_type_pointer;
    459         if (dict->flags & (TYPEFLAG_ISPOINTER | TYPEFLAG_HASPOINTER))
    460             stgdict->flags |= TYPEFLAG_HASPOINTER;
    461         dict->flags |= DICTFLAG_FINAL; /* mark field type final */
    462         if (PyTuple_Size(pair) == 3) { /* bits specified */
    463             switch(dict->ffi_type_pointer.type) {
    464             case FFI_TYPE_UINT8:
    465             case FFI_TYPE_UINT16:
    466             case FFI_TYPE_UINT32:
    467             case FFI_TYPE_SINT64:
    468             case FFI_TYPE_UINT64:
    469                 break;
    470 
    471             case FFI_TYPE_SINT8:
    472             case FFI_TYPE_SINT16:
    473             case FFI_TYPE_SINT32:
    474                 if (dict->getfunc != _ctypes_get_fielddesc("c")->getfunc
    475 #ifdef CTYPES_UNICODE
    476                     && dict->getfunc != _ctypes_get_fielddesc("u")->getfunc
    477 #endif
    478                     )
    479                     break;
    480                 /* else fall through */
    481             default:
    482                 PyErr_Format(PyExc_TypeError,
    483                              "bit fields not allowed for type %s",
    484                              ((PyTypeObject *)desc)->tp_name);
    485                 Py_DECREF(pair);
    486                 return -1;
    487             }
    488             if (bitsize <= 0 || bitsize > dict->size * 8) {
    489                 PyErr_SetString(PyExc_ValueError,
    490                                 "number of bits invalid for bit field");
    491                 Py_DECREF(pair);
    492                 return -1;
    493             }
    494         } else
    495             bitsize = 0;
    496         if (isStruct && !isPacked) {
    497             char *fieldfmt = dict->format ? dict->format : "B";
    498             char *fieldname = PyString_AsString(name);
    499             char *ptr;
    500             Py_ssize_t len;
    501             char *buf;
    502 
    503             if (fieldname == NULL)
    504             {
    505                 PyErr_Format(PyExc_TypeError,
    506                              "structure field name must be string not %s",
    507                              name->ob_type->tp_name);
    508 
    509                 Py_DECREF(pair);
    510                 return -1;
    511             }
    512 
    513             len = strlen(fieldname) + strlen(fieldfmt);
    514 
    515             buf = PyMem_Malloc(len + 2 + 1);
    516             if (buf == NULL) {
    517                 Py_DECREF(pair);
    518                 PyErr_NoMemory();
    519                 return -1;
    520             }
    521             sprintf(buf, "%s:%s:", fieldfmt, fieldname);
    522 
    523             ptr = stgdict->format;
    524             if (dict->shape != NULL) {
    525                 stgdict->format = _ctypes_alloc_format_string_with_shape(
    526                     dict->ndim, dict->shape, stgdict->format, buf);
    527             } else {
    528                 stgdict->format = _ctypes_alloc_format_string(stgdict->format, buf);
    529             }
    530             PyMem_Free(ptr);
    531             PyMem_Free(buf);
    532 
    533             if (stgdict->format == NULL) {
    534                 Py_DECREF(pair);
    535                 return -1;
    536             }
    537         }
    538         if (isStruct) {
    539             prop = PyCField_FromDesc(desc, i,
    540                                    &field_size, bitsize, &bitofs,
    541                                    &size, &offset, &align,
    542                                    pack, big_endian);
    543         } else /* union */ {
    544             size = 0;
    545             offset = 0;
    546             align = 0;
    547             prop = PyCField_FromDesc(desc, i,
    548                                    &field_size, bitsize, &bitofs,
    549                                    &size, &offset, &align,
    550                                    pack, big_endian);
    551             union_size = max(size, union_size);
    552         }
    553         total_align = max(align, total_align);
    554 
    555         if (!prop) {
    556             Py_DECREF(pair);
    557             return -1;
    558         }
    559         if (-1 == PyObject_SetAttr(type, name, prop)) {
    560             Py_DECREF(prop);
    561             Py_DECREF(pair);
    562             return -1;
    563         }
    564         Py_DECREF(pair);
    565         Py_DECREF(prop);
    566     }
    567 #undef realdict
    568 
    569     if (isStruct && !isPacked) {
    570         char *ptr = stgdict->format;
    571         stgdict->format = _ctypes_alloc_format_string(stgdict->format, "}");
    572         PyMem_Free(ptr);
    573         if (stgdict->format == NULL)
    574             return -1;
    575     }
    576 
    577     if (!isStruct)
    578         size = union_size;
    579 
    580     /* Adjust the size according to the alignment requirements */
    581     size = ((size + total_align - 1) / total_align) * total_align;
    582 
    583     stgdict->ffi_type_pointer.alignment = Py_SAFE_DOWNCAST(total_align,
    584                                                            Py_ssize_t,
    585                                                            unsigned short);
    586     stgdict->ffi_type_pointer.size = size;
    587 
    588     stgdict->size = size;
    589     stgdict->align = total_align;
    590     stgdict->length = len;      /* ADD ffi_ofs? */
    591 
    592     /* We did check that this flag was NOT set above, it must not
    593        have been set until now. */
    594     if (stgdict->flags & DICTFLAG_FINAL) {
    595         PyErr_SetString(PyExc_AttributeError,
    596                         "Structure or union cannot contain itself");
    597         return -1;
    598     }
    599     stgdict->flags |= DICTFLAG_FINAL;
    600 
    601     return MakeAnonFields(type);
    602 }
    603