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