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