Branch data Line data Source code
1 : : /*
2 : : * History: First version dated from 3/97, derived from my SCMLIB version
3 : : * for win16.
4 : : */
5 : : /*
6 : : * Related Work:
7 : : * - calldll http://www.nightmare.com/software.html
8 : : * - libffi http://sourceware.cygnus.com/libffi/
9 : : * - ffcall http://clisp.cons.org/~haible/packages-ffcall.html
10 : : * and, of course, Don Beaudry's MESS package, but this is more ctypes
11 : : * related.
12 : : */
13 : :
14 : :
15 : : /*
16 : : How are functions called, and how are parameters converted to C ?
17 : :
18 : : 1. _ctypes.c::PyCFuncPtr_call receives an argument tuple 'inargs' and a
19 : : keyword dictionary 'kwds'.
20 : :
21 : : 2. After several checks, _build_callargs() is called which returns another
22 : : tuple 'callargs'. This may be the same tuple as 'inargs', a slice of
23 : : 'inargs', or a completely fresh tuple, depending on several things (is it a
24 : : COM method?, are 'paramflags' available?).
25 : :
26 : : 3. _build_callargs also calculates bitarrays containing indexes into
27 : : the callargs tuple, specifying how to build the return value(s) of
28 : : the function.
29 : :
30 : : 4. _ctypes_callproc is then called with the 'callargs' tuple. _ctypes_callproc first
31 : : allocates two arrays. The first is an array of 'struct argument' items, the
32 : : second array has 'void *' entries.
33 : :
34 : : 5. If 'converters' are present (converters is a sequence of argtypes'
35 : : from_param methods), for each item in 'callargs' converter is called and the
36 : : result passed to ConvParam. If 'converters' are not present, each argument
37 : : is directly passed to ConvParm.
38 : :
39 : : 6. For each arg, ConvParam stores the contained C data (or a pointer to it,
40 : : for structures) into the 'struct argument' array.
41 : :
42 : : 7. Finally, a loop fills the 'void *' array so that each item points to the
43 : : data contained in or pointed to by the 'struct argument' array.
44 : :
45 : : 8. The 'void *' argument array is what _call_function_pointer
46 : : expects. _call_function_pointer then has very little to do - only some
47 : : libffi specific stuff, then it calls ffi_call.
48 : :
49 : : So, there are 4 data structures holding processed arguments:
50 : : - the inargs tuple (in PyCFuncPtr_call)
51 : : - the callargs tuple (in PyCFuncPtr_call)
52 : : - the 'struct arguments' array
53 : : - the 'void *' array
54 : :
55 : : */
56 : :
57 : : #ifndef Py_BUILD_CORE_BUILTIN
58 : : # define Py_BUILD_CORE_MODULE 1
59 : : #endif
60 : : #define NEEDS_PY_IDENTIFIER
61 : :
62 : : #include "Python.h"
63 : : #include "structmember.h" // PyMemberDef
64 : :
65 : : #include <stdbool.h>
66 : :
67 : : #ifdef MS_WIN32
68 : : #include <windows.h>
69 : : #include <tchar.h>
70 : : #else
71 : : #include "ctypes_dlfcn.h"
72 : : #endif
73 : :
74 : : #ifdef __APPLE__
75 : : #include <mach-o/dyld.h>
76 : : #endif
77 : :
78 : : #ifdef MS_WIN32
79 : : #include <malloc.h>
80 : : #endif
81 : :
82 : : #include <ffi.h>
83 : : #include "ctypes.h"
84 : : #ifdef HAVE_ALLOCA_H
85 : : /* AIX needs alloca.h for alloca() */
86 : : #include <alloca.h>
87 : : #endif
88 : :
89 : : #ifdef _Py_MEMORY_SANITIZER
90 : : #include <sanitizer/msan_interface.h>
91 : : #endif
92 : :
93 : : #if defined(_DEBUG) || defined(__MINGW32__)
94 : : /* Don't use structured exception handling on Windows if this is defined.
95 : : MingW, AFAIK, doesn't support it.
96 : : */
97 : : #define DONT_USE_SEH
98 : : #endif
99 : :
100 : : #define CTYPES_CAPSULE_NAME_PYMEM "_ctypes pymem"
101 : :
102 : 2 : static void pymem_destructor(PyObject *ptr)
103 : : {
104 : 2 : void *p = PyCapsule_GetPointer(ptr, CTYPES_CAPSULE_NAME_PYMEM);
105 [ + - ]: 2 : if (p) {
106 : 2 : PyMem_Free(p);
107 : : }
108 : 2 : }
109 : :
110 : : /*
111 : : ctypes maintains thread-local storage that has space for two error numbers:
112 : : private copies of the system 'errno' value and, on Windows, the system error code
113 : : accessed by the GetLastError() and SetLastError() api functions.
114 : :
115 : : Foreign functions created with CDLL(..., use_errno=True), when called, swap
116 : : the system 'errno' value with the private copy just before the actual
117 : : function call, and swapped again immediately afterwards. The 'use_errno'
118 : : parameter defaults to False, in this case 'ctypes_errno' is not touched.
119 : :
120 : : On Windows, foreign functions created with CDLL(..., use_last_error=True) or
121 : : WinDLL(..., use_last_error=True) swap the system LastError value with the
122 : : ctypes private copy.
123 : :
124 : : The values are also swapped immediately before and after ctypes callback
125 : : functions are called, if the callbacks are constructed using the new
126 : : optional use_errno parameter set to True: CFUNCTYPE(..., use_errno=TRUE) or
127 : : WINFUNCTYPE(..., use_errno=True).
128 : :
129 : : New ctypes functions are provided to access the ctypes private copies from
130 : : Python:
131 : :
132 : : - ctypes.set_errno(value) and ctypes.set_last_error(value) store 'value' in
133 : : the private copy and returns the previous value.
134 : :
135 : : - ctypes.get_errno() and ctypes.get_last_error() returns the current ctypes
136 : : private copies value.
137 : : */
138 : :
139 : : /*
140 : : This function creates and returns a thread-local Python object that has
141 : : space to store two integer error numbers; once created the Python object is
142 : : kept alive in the thread state dictionary as long as the thread itself.
143 : : */
144 : : PyObject *
145 : 8 : _ctypes_get_errobj(int **pspace)
146 : : {
147 : 8 : PyObject *dict = PyThreadState_GetDict();
148 : : PyObject *errobj;
149 : : static PyObject *error_object_name;
150 [ - + ]: 8 : if (dict == NULL) {
151 : 0 : PyErr_SetString(PyExc_RuntimeError,
152 : : "cannot get thread state");
153 : 0 : return NULL;
154 : : }
155 [ + + ]: 8 : if (error_object_name == NULL) {
156 : 1 : error_object_name = PyUnicode_InternFromString("ctypes.error_object");
157 [ - + ]: 1 : if (error_object_name == NULL)
158 : 0 : return NULL;
159 : : }
160 : 8 : errobj = PyDict_GetItemWithError(dict, error_object_name);
161 [ + + ]: 8 : if (errobj) {
162 [ - + ]: 6 : if (!PyCapsule_IsValid(errobj, CTYPES_CAPSULE_NAME_PYMEM)) {
163 : 0 : PyErr_SetString(PyExc_RuntimeError,
164 : : "ctypes.error_object is an invalid capsule");
165 : 0 : return NULL;
166 : : }
167 : 6 : Py_INCREF(errobj);
168 : : }
169 [ + - ]: 2 : else if (!PyErr_Occurred()) {
170 : 2 : void *space = PyMem_Calloc(2, sizeof(int));
171 [ - + ]: 2 : if (space == NULL)
172 : 0 : return NULL;
173 : 2 : errobj = PyCapsule_New(space, CTYPES_CAPSULE_NAME_PYMEM, pymem_destructor);
174 [ - + ]: 2 : if (errobj == NULL) {
175 : 0 : PyMem_Free(space);
176 : 0 : return NULL;
177 : : }
178 [ - + ]: 2 : if (-1 == PyDict_SetItem(dict, error_object_name,
179 : : errobj)) {
180 : 0 : Py_DECREF(errobj);
181 : 0 : return NULL;
182 : : }
183 : : }
184 : : else {
185 : 0 : return NULL;
186 : : }
187 : 8 : *pspace = (int *)PyCapsule_GetPointer(errobj, CTYPES_CAPSULE_NAME_PYMEM);
188 : 8 : return errobj;
189 : : }
190 : :
191 : : static PyObject *
192 : 4 : get_error_internal(PyObject *self, PyObject *args, int index)
193 : : {
194 : : int *space;
195 : 4 : PyObject *errobj = _ctypes_get_errobj(&space);
196 : : PyObject *result;
197 : :
198 [ - + ]: 4 : if (errobj == NULL)
199 : 0 : return NULL;
200 : 4 : result = PyLong_FromLong(space[index]);
201 : 4 : Py_DECREF(errobj);
202 : 4 : return result;
203 : : }
204 : :
205 : : static PyObject *
206 : 3 : set_error_internal(PyObject *self, PyObject *args, int index)
207 : : {
208 : : int new_errno, old_errno;
209 : : PyObject *errobj;
210 : : int *space;
211 : :
212 [ - + ]: 3 : if (!PyArg_ParseTuple(args, "i", &new_errno)) {
213 : 0 : return NULL;
214 : : }
215 : 3 : errobj = _ctypes_get_errobj(&space);
216 [ - + ]: 3 : if (errobj == NULL)
217 : 0 : return NULL;
218 : 3 : old_errno = space[index];
219 : 3 : space[index] = new_errno;
220 : 3 : Py_DECREF(errobj);
221 : 3 : return PyLong_FromLong(old_errno);
222 : : }
223 : :
224 : : static PyObject *
225 : 4 : get_errno(PyObject *self, PyObject *args)
226 : : {
227 [ - + ]: 4 : if (PySys_Audit("ctypes.get_errno", NULL) < 0) {
228 : 0 : return NULL;
229 : : }
230 : 4 : return get_error_internal(self, args, 0);
231 : : }
232 : :
233 : : static PyObject *
234 : 3 : set_errno(PyObject *self, PyObject *args)
235 : : {
236 [ - + ]: 3 : if (PySys_Audit("ctypes.set_errno", "O", args) < 0) {
237 : 0 : return NULL;
238 : : }
239 : 3 : return set_error_internal(self, args, 0);
240 : : }
241 : :
242 : : #ifdef MS_WIN32
243 : :
244 : : static PyObject *
245 : : get_last_error(PyObject *self, PyObject *args)
246 : : {
247 : : if (PySys_Audit("ctypes.get_last_error", NULL) < 0) {
248 : : return NULL;
249 : : }
250 : : return get_error_internal(self, args, 1);
251 : : }
252 : :
253 : : static PyObject *
254 : : set_last_error(PyObject *self, PyObject *args)
255 : : {
256 : : if (PySys_Audit("ctypes.set_last_error", "O", args) < 0) {
257 : : return NULL;
258 : : }
259 : : return set_error_internal(self, args, 1);
260 : : }
261 : :
262 : : static WCHAR *FormatError(DWORD code)
263 : : {
264 : : WCHAR *lpMsgBuf;
265 : : DWORD n;
266 : : n = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
267 : : FORMAT_MESSAGE_FROM_SYSTEM |
268 : : FORMAT_MESSAGE_IGNORE_INSERTS,
269 : : NULL,
270 : : code,
271 : : MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
272 : : (LPWSTR) &lpMsgBuf,
273 : : 0,
274 : : NULL);
275 : : if (n) {
276 : : while (iswspace(lpMsgBuf[n-1]))
277 : : --n;
278 : : lpMsgBuf[n] = L'\0'; /* rstrip() */
279 : : }
280 : : return lpMsgBuf;
281 : : }
282 : :
283 : : #ifndef DONT_USE_SEH
284 : : static void SetException(DWORD code, EXCEPTION_RECORD *pr)
285 : : {
286 : : if (PySys_Audit("ctypes.seh_exception", "I", code) < 0) {
287 : : /* An exception was set by the audit hook */
288 : : return;
289 : : }
290 : :
291 : : /* The 'code' is a normal win32 error code so it could be handled by
292 : : PyErr_SetFromWindowsErr(). However, for some errors, we have additional
293 : : information not included in the error code. We handle those here and
294 : : delegate all others to the generic function. */
295 : : switch (code) {
296 : : case EXCEPTION_ACCESS_VIOLATION:
297 : : /* The thread attempted to read from or write
298 : : to a virtual address for which it does not
299 : : have the appropriate access. */
300 : : if (pr->ExceptionInformation[0] == 0)
301 : : PyErr_Format(PyExc_OSError,
302 : : "exception: access violation reading %p",
303 : : pr->ExceptionInformation[1]);
304 : : else
305 : : PyErr_Format(PyExc_OSError,
306 : : "exception: access violation writing %p",
307 : : pr->ExceptionInformation[1]);
308 : : break;
309 : :
310 : : case EXCEPTION_BREAKPOINT:
311 : : /* A breakpoint was encountered. */
312 : : PyErr_SetString(PyExc_OSError,
313 : : "exception: breakpoint encountered");
314 : : break;
315 : :
316 : : case EXCEPTION_DATATYPE_MISALIGNMENT:
317 : : /* The thread attempted to read or write data that is
318 : : misaligned on hardware that does not provide
319 : : alignment. For example, 16-bit values must be
320 : : aligned on 2-byte boundaries, 32-bit values on
321 : : 4-byte boundaries, and so on. */
322 : : PyErr_SetString(PyExc_OSError,
323 : : "exception: datatype misalignment");
324 : : break;
325 : :
326 : : case EXCEPTION_SINGLE_STEP:
327 : : /* A trace trap or other single-instruction mechanism
328 : : signaled that one instruction has been executed. */
329 : : PyErr_SetString(PyExc_OSError,
330 : : "exception: single step");
331 : : break;
332 : :
333 : : case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
334 : : /* The thread attempted to access an array element
335 : : that is out of bounds, and the underlying hardware
336 : : supports bounds checking. */
337 : : PyErr_SetString(PyExc_OSError,
338 : : "exception: array bounds exceeded");
339 : : break;
340 : :
341 : : case EXCEPTION_FLT_DENORMAL_OPERAND:
342 : : /* One of the operands in a floating-point operation
343 : : is denormal. A denormal value is one that is too
344 : : small to represent as a standard floating-point
345 : : value. */
346 : : PyErr_SetString(PyExc_OSError,
347 : : "exception: floating-point operand denormal");
348 : : break;
349 : :
350 : : case EXCEPTION_FLT_DIVIDE_BY_ZERO:
351 : : /* The thread attempted to divide a floating-point
352 : : value by a floating-point divisor of zero. */
353 : : PyErr_SetString(PyExc_OSError,
354 : : "exception: float divide by zero");
355 : : break;
356 : :
357 : : case EXCEPTION_FLT_INEXACT_RESULT:
358 : : /* The result of a floating-point operation cannot be
359 : : represented exactly as a decimal fraction. */
360 : : PyErr_SetString(PyExc_OSError,
361 : : "exception: float inexact");
362 : : break;
363 : :
364 : : case EXCEPTION_FLT_INVALID_OPERATION:
365 : : /* This exception represents any floating-point
366 : : exception not included in this list. */
367 : : PyErr_SetString(PyExc_OSError,
368 : : "exception: float invalid operation");
369 : : break;
370 : :
371 : : case EXCEPTION_FLT_OVERFLOW:
372 : : /* The exponent of a floating-point operation is
373 : : greater than the magnitude allowed by the
374 : : corresponding type. */
375 : : PyErr_SetString(PyExc_OSError,
376 : : "exception: float overflow");
377 : : break;
378 : :
379 : : case EXCEPTION_FLT_STACK_CHECK:
380 : : /* The stack overflowed or underflowed as the result
381 : : of a floating-point operation. */
382 : : PyErr_SetString(PyExc_OSError,
383 : : "exception: stack over/underflow");
384 : : break;
385 : :
386 : : case EXCEPTION_STACK_OVERFLOW:
387 : : /* The stack overflowed or underflowed as the result
388 : : of a floating-point operation. */
389 : : PyErr_SetString(PyExc_OSError,
390 : : "exception: stack overflow");
391 : : break;
392 : :
393 : : case EXCEPTION_FLT_UNDERFLOW:
394 : : /* The exponent of a floating-point operation is less
395 : : than the magnitude allowed by the corresponding
396 : : type. */
397 : : PyErr_SetString(PyExc_OSError,
398 : : "exception: float underflow");
399 : : break;
400 : :
401 : : case EXCEPTION_INT_DIVIDE_BY_ZERO:
402 : : /* The thread attempted to divide an integer value by
403 : : an integer divisor of zero. */
404 : : PyErr_SetString(PyExc_OSError,
405 : : "exception: integer divide by zero");
406 : : break;
407 : :
408 : : case EXCEPTION_INT_OVERFLOW:
409 : : /* The result of an integer operation caused a carry
410 : : out of the most significant bit of the result. */
411 : : PyErr_SetString(PyExc_OSError,
412 : : "exception: integer overflow");
413 : : break;
414 : :
415 : : case EXCEPTION_PRIV_INSTRUCTION:
416 : : /* The thread attempted to execute an instruction
417 : : whose operation is not allowed in the current
418 : : machine mode. */
419 : : PyErr_SetString(PyExc_OSError,
420 : : "exception: privileged instruction");
421 : : break;
422 : :
423 : : case EXCEPTION_NONCONTINUABLE_EXCEPTION:
424 : : /* The thread attempted to continue execution after a
425 : : noncontinuable exception occurred. */
426 : : PyErr_SetString(PyExc_OSError,
427 : : "exception: nocontinuable");
428 : : break;
429 : :
430 : : default:
431 : : PyErr_SetFromWindowsErr(code);
432 : : break;
433 : : }
434 : : }
435 : :
436 : : static DWORD HandleException(EXCEPTION_POINTERS *ptrs,
437 : : DWORD *pdw, EXCEPTION_RECORD *record)
438 : : {
439 : : *pdw = ptrs->ExceptionRecord->ExceptionCode;
440 : : *record = *ptrs->ExceptionRecord;
441 : : /* We don't want to catch breakpoint exceptions, they are used to attach
442 : : * a debugger to the process.
443 : : */
444 : : if (*pdw == EXCEPTION_BREAKPOINT)
445 : : return EXCEPTION_CONTINUE_SEARCH;
446 : : return EXCEPTION_EXECUTE_HANDLER;
447 : : }
448 : : #endif
449 : :
450 : : static PyObject *
451 : : check_hresult(PyObject *self, PyObject *args)
452 : : {
453 : : HRESULT hr;
454 : : if (!PyArg_ParseTuple(args, "i", &hr))
455 : : return NULL;
456 : : if (FAILED(hr))
457 : : return PyErr_SetFromWindowsErr(hr);
458 : : return PyLong_FromLong(hr);
459 : : }
460 : :
461 : : #endif
462 : :
463 : : /**************************************************************/
464 : :
465 : : PyCArgObject *
466 : 18024 : PyCArgObject_new(void)
467 : : {
468 : : PyCArgObject *p;
469 : 18024 : p = PyObject_New(PyCArgObject, &PyCArg_Type);
470 [ - + ]: 18024 : if (p == NULL)
471 : 0 : return NULL;
472 : 18024 : p->pffi_type = NULL;
473 : 18024 : p->tag = '\0';
474 : 18024 : p->obj = NULL;
475 : 18024 : memset(&p->value, 0, sizeof(p->value));
476 : 18024 : return p;
477 : : }
478 : :
479 : : static void
480 : 18024 : PyCArg_dealloc(PyCArgObject *self)
481 : : {
482 : 18024 : Py_XDECREF(self->obj);
483 : 18024 : PyObject_Free(self);
484 : 18024 : }
485 : :
486 : : static int
487 : 5 : is_literal_char(unsigned char c)
488 : : {
489 [ + + + - : 5 : return c < 128 && _PyUnicode_IsPrintable(c) && c != '\\' && c != '\'';
+ - + - ]
490 : : }
491 : :
492 : : static PyObject *
493 : 22 : PyCArg_repr(PyCArgObject *self)
494 : : {
495 [ + + + + : 22 : switch(self->tag) {
- + + +
+ ]
496 : 2 : case 'b':
497 : : case 'B':
498 : 2 : return PyUnicode_FromFormat("<cparam '%c' (%d)>",
499 : 2 : self->tag, self->value.b);
500 : 2 : case 'h':
501 : : case 'H':
502 : 2 : return PyUnicode_FromFormat("<cparam '%c' (%d)>",
503 : 2 : self->tag, self->value.h);
504 : 2 : case 'i':
505 : : case 'I':
506 : 2 : return PyUnicode_FromFormat("<cparam '%c' (%d)>",
507 : 2 : self->tag, self->value.i);
508 : 4 : case 'l':
509 : : case 'L':
510 : 4 : return PyUnicode_FromFormat("<cparam '%c' (%ld)>",
511 : 4 : self->tag, self->value.l);
512 : :
513 : 0 : case 'q':
514 : : case 'Q':
515 : 0 : return PyUnicode_FromFormat("<cparam '%c' (%lld)>",
516 : 0 : self->tag, self->value.q);
517 : 3 : case 'd':
518 : : case 'f': {
519 [ + + ]: 3 : PyObject *f = PyFloat_FromDouble((self->tag == 'f') ? self->value.f : self->value.d);
520 [ - + ]: 3 : if (f == NULL) {
521 : 0 : return NULL;
522 : : }
523 : 3 : PyObject *result = PyUnicode_FromFormat("<cparam '%c' (%R)>", self->tag, f);
524 : 3 : Py_DECREF(f);
525 : 3 : return result;
526 : : }
527 : 2 : case 'c':
528 [ + + ]: 2 : if (is_literal_char((unsigned char)self->value.c)) {
529 : 1 : return PyUnicode_FromFormat("<cparam '%c' ('%c')>",
530 : 1 : self->tag, self->value.c);
531 : : }
532 : : else {
533 : 1 : return PyUnicode_FromFormat("<cparam '%c' ('\\x%02x')>",
534 : 1 : self->tag, (unsigned char)self->value.c);
535 : : }
536 : :
537 : : /* Hm, are these 'z' and 'Z' codes useful at all?
538 : : Shouldn't they be replaced by the functionality of create_string_buffer()
539 : : and c_wstring() ?
540 : : */
541 : 4 : case 'z':
542 : : case 'Z':
543 : : case 'P':
544 : 4 : return PyUnicode_FromFormat("<cparam '%c' (%p)>",
545 : 4 : self->tag, self->value.p);
546 : : break;
547 : :
548 : 3 : default:
549 [ + - ]: 3 : if (is_literal_char((unsigned char)self->tag)) {
550 : 3 : return PyUnicode_FromFormat("<cparam '%c' at %p>",
551 : 3 : (unsigned char)self->tag, (void *)self);
552 : : }
553 : : else {
554 : 0 : return PyUnicode_FromFormat("<cparam 0x%02x at %p>",
555 : 0 : (unsigned char)self->tag, (void *)self);
556 : : }
557 : : }
558 : : }
559 : :
560 : : static PyMemberDef PyCArgType_members[] = {
561 : : { "_obj", T_OBJECT,
562 : : offsetof(PyCArgObject, obj), READONLY,
563 : : "the wrapped object" },
564 : : { NULL },
565 : : };
566 : :
567 : : PyTypeObject PyCArg_Type = {
568 : : PyVarObject_HEAD_INIT(NULL, 0)
569 : : "CArgObject",
570 : : sizeof(PyCArgObject),
571 : : 0,
572 : : (destructor)PyCArg_dealloc, /* tp_dealloc */
573 : : 0, /* tp_vectorcall_offset */
574 : : 0, /* tp_getattr */
575 : : 0, /* tp_setattr */
576 : : 0, /* tp_as_async */
577 : : (reprfunc)PyCArg_repr, /* tp_repr */
578 : : 0, /* tp_as_number */
579 : : 0, /* tp_as_sequence */
580 : : 0, /* tp_as_mapping */
581 : : 0, /* tp_hash */
582 : : 0, /* tp_call */
583 : : 0, /* tp_str */
584 : : 0, /* tp_getattro */
585 : : 0, /* tp_setattro */
586 : : 0, /* tp_as_buffer */
587 : : Py_TPFLAGS_DEFAULT, /* tp_flags */
588 : : 0, /* tp_doc */
589 : : 0, /* tp_traverse */
590 : : 0, /* tp_clear */
591 : : 0, /* tp_richcompare */
592 : : 0, /* tp_weaklistoffset */
593 : : 0, /* tp_iter */
594 : : 0, /* tp_iternext */
595 : : 0, /* tp_methods */
596 : : PyCArgType_members, /* tp_members */
597 : : };
598 : :
599 : : /****************************************************************/
600 : : /*
601 : : * Convert a PyObject * into a parameter suitable to pass to an
602 : : * C function call.
603 : : *
604 : : * 1. Python integers are converted to C int and passed by value.
605 : : * Py_None is converted to a C NULL pointer.
606 : : *
607 : : * 2. 3-tuples are expected to have a format character in the first
608 : : * item, which must be 'i', 'f', 'd', 'q', or 'P'.
609 : : * The second item will have to be an integer, float, double, long long
610 : : * or integer (denoting an address void *), will be converted to the
611 : : * corresponding C data type and passed by value.
612 : : *
613 : : * 3. Other Python objects are tested for an '_as_parameter_' attribute.
614 : : * The value of this attribute must be an integer which will be passed
615 : : * by value, or a 2-tuple or 3-tuple which will be used according
616 : : * to point 2 above. The third item (if any), is ignored. It is normally
617 : : * used to keep the object alive where this parameter refers to.
618 : : * XXX This convention is dangerous - you can construct arbitrary tuples
619 : : * in Python and pass them. Would it be safer to use a custom container
620 : : * datatype instead of a tuple?
621 : : *
622 : : * 4. Other Python objects cannot be passed as parameters - an exception is raised.
623 : : *
624 : : * 5. ConvParam will store the converted result in a struct containing format
625 : : * and value.
626 : : */
627 : :
628 : : union result {
629 : : char c;
630 : : char b;
631 : : short h;
632 : : int i;
633 : : long l;
634 : : long long q;
635 : : long double D;
636 : : double d;
637 : : float f;
638 : : void *p;
639 : : };
640 : :
641 : : struct argument {
642 : : ffi_type *ffi_type;
643 : : PyObject *keep;
644 : : union result value;
645 : : };
646 : :
647 : : /*
648 : : * Convert a single Python object into a PyCArgObject and return it.
649 : : */
650 : 15123 : static int ConvParam(PyObject *obj, Py_ssize_t index, struct argument *pa)
651 : : {
652 : : StgDictObject *dict;
653 : 15123 : pa->keep = NULL; /* so we cannot forget it later */
654 : :
655 : 15123 : dict = PyObject_stgdict(obj);
656 [ + + ]: 15123 : if (dict) {
657 : : PyCArgObject *carg;
658 : : assert(dict->paramfunc);
659 : : /* If it has an stgdict, it is a CDataObject */
660 : 270 : carg = dict->paramfunc((CDataObject *)obj);
661 [ - + ]: 270 : if (carg == NULL)
662 : 0 : return -1;
663 : 270 : pa->ffi_type = carg->pffi_type;
664 : 270 : memcpy(&pa->value, &carg->value, sizeof(pa->value));
665 : 270 : pa->keep = (PyObject *)carg;
666 : 270 : return 0;
667 : : }
668 : :
669 [ + + ]: 14853 : if (PyCArg_CheckExact(obj)) {
670 : 14773 : PyCArgObject *carg = (PyCArgObject *)obj;
671 : 14773 : pa->ffi_type = carg->pffi_type;
672 : 14773 : Py_INCREF(obj);
673 : 14773 : pa->keep = obj;
674 : 14773 : memcpy(&pa->value, &carg->value, sizeof(pa->value));
675 : 14773 : return 0;
676 : : }
677 : :
678 : : /* check for None, integer, string or unicode and use directly if successful */
679 [ + + ]: 80 : if (obj == Py_None) {
680 : 22 : pa->ffi_type = &ffi_type_pointer;
681 : 22 : pa->value.p = NULL;
682 : 22 : return 0;
683 : : }
684 : :
685 [ + + ]: 58 : if (PyLong_Check(obj)) {
686 : 19 : pa->ffi_type = &ffi_type_sint;
687 : 19 : pa->value.i = (long)PyLong_AsUnsignedLong(obj);
688 [ + + + - ]: 19 : if (pa->value.i == -1 && PyErr_Occurred()) {
689 : 4 : PyErr_Clear();
690 : 4 : pa->value.i = PyLong_AsLong(obj);
691 [ - + - - ]: 4 : if (pa->value.i == -1 && PyErr_Occurred()) {
692 : 0 : PyErr_SetString(PyExc_OverflowError,
693 : : "int too long to convert");
694 : 0 : return -1;
695 : : }
696 : : }
697 : 19 : return 0;
698 : : }
699 : :
700 [ + + ]: 39 : if (PyBytes_Check(obj)) {
701 : 33 : pa->ffi_type = &ffi_type_pointer;
702 : 33 : pa->value.p = PyBytes_AsString(obj);
703 : 33 : Py_INCREF(obj);
704 : 33 : pa->keep = obj;
705 : 33 : return 0;
706 : : }
707 : :
708 [ - + ]: 6 : if (PyUnicode_Check(obj)) {
709 : 0 : pa->ffi_type = &ffi_type_pointer;
710 : 0 : pa->value.p = PyUnicode_AsWideCharString(obj, NULL);
711 [ # # ]: 0 : if (pa->value.p == NULL)
712 : 0 : return -1;
713 : 0 : pa->keep = PyCapsule_New(pa->value.p, CTYPES_CAPSULE_NAME_PYMEM, pymem_destructor);
714 [ # # ]: 0 : if (!pa->keep) {
715 : 0 : PyMem_Free(pa->value.p);
716 : 0 : return -1;
717 : : }
718 : 0 : return 0;
719 : : }
720 : :
721 : : {
722 : : _Py_IDENTIFIER(_as_parameter_);
723 : : PyObject *arg;
724 [ - + ]: 6 : if (_PyObject_LookupAttrId(obj, &PyId__as_parameter_, &arg) < 0) {
725 : 0 : return -1;
726 : : }
727 : : /* Which types should we exactly allow here?
728 : : integers are required for using Python classes
729 : : as parameters (they have to expose the '_as_parameter_'
730 : : attribute)
731 : : */
732 [ + + ]: 6 : if (arg) {
733 : : int result;
734 : 5 : result = ConvParam(arg, index, pa);
735 : 5 : Py_DECREF(arg);
736 : 5 : return result;
737 : : }
738 : 1 : PyErr_Format(PyExc_TypeError,
739 : : "Don't know how to convert parameter %d",
740 : : Py_SAFE_DOWNCAST(index, Py_ssize_t, int));
741 : 1 : return -1;
742 : : }
743 : : }
744 : :
745 : : #if defined(MS_WIN32) && !defined(_WIN32_WCE)
746 : : /*
747 : : Per: https://msdn.microsoft.com/en-us/library/7572ztz4.aspx
748 : : To be returned by value in RAX, user-defined types must have a length
749 : : of 1, 2, 4, 8, 16, 32, or 64 bits
750 : : */
751 : : int can_return_struct_as_int(size_t s)
752 : : {
753 : : return s == 1 || s == 2 || s == 4;
754 : : }
755 : :
756 : : int can_return_struct_as_sint64(size_t s)
757 : : {
758 : : #ifdef _M_ARM
759 : : // 8 byte structs cannot be returned in a register on ARM32
760 : : return 0;
761 : : #else
762 : : return s == 8;
763 : : #endif
764 : : }
765 : : #endif
766 : :
767 : :
768 : 8176 : ffi_type *_ctypes_get_ffi_type(PyObject *obj)
769 : : {
770 : : StgDictObject *dict;
771 [ - + ]: 8176 : if (obj == NULL)
772 : 0 : return &ffi_type_sint;
773 : 8176 : dict = PyType_stgdict(obj);
774 [ + + ]: 8176 : if (dict == NULL)
775 : 2 : return &ffi_type_sint;
776 : : #if defined(MS_WIN32) && !defined(_WIN32_WCE)
777 : : /* This little trick works correctly with MSVC.
778 : : It returns small structures in registers
779 : : */
780 : : if (dict->ffi_type_pointer.type == FFI_TYPE_STRUCT) {
781 : : if (can_return_struct_as_int(dict->ffi_type_pointer.size))
782 : : return &ffi_type_sint32;
783 : : else if (can_return_struct_as_sint64 (dict->ffi_type_pointer.size))
784 : : return &ffi_type_sint64;
785 : : }
786 : : #endif
787 : 8174 : return &dict->ffi_type_pointer;
788 : : }
789 : :
790 : :
791 : : /*
792 : : * libffi uses:
793 : : *
794 : : * ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi,
795 : : * unsigned int nargs,
796 : : * ffi_type *rtype,
797 : : * ffi_type **atypes);
798 : : *
799 : : * and then
800 : : *
801 : : * void ffi_call(ffi_cif *cif, void *fn, void *rvalue, void **avalues);
802 : : */
803 : 6999 : static int _call_function_pointer(int flags,
804 : : PPROC pProc,
805 : : void **avalues,
806 : : ffi_type **atypes,
807 : : ffi_type *restype,
808 : : void *resmem,
809 : : int argcount,
810 : : int argtypecount)
811 : : {
812 : 6999 : PyThreadState *_save = NULL; /* For Py_BLOCK_THREADS and Py_UNBLOCK_THREADS */
813 : 6999 : PyObject *error_object = NULL;
814 : : int *space;
815 : : ffi_cif cif;
816 : : int cc;
817 : : #if defined(MS_WIN32) && !defined(DONT_USE_SEH)
818 : : DWORD dwExceptionCode = 0;
819 : : EXCEPTION_RECORD record;
820 : : #endif
821 : : /* XXX check before here */
822 [ - + ]: 6999 : if (restype == NULL) {
823 : 0 : PyErr_SetString(PyExc_RuntimeError,
824 : : "No ffi_type for result");
825 : 0 : return -1;
826 : : }
827 : :
828 : 6999 : cc = FFI_DEFAULT_ABI;
829 : : #if defined(MS_WIN32) && !defined(MS_WIN64) && !defined(_WIN32_WCE) && !defined(_M_ARM)
830 : : if ((flags & FUNCFLAG_CDECL) == 0)
831 : : cc = FFI_STDCALL;
832 : : #endif
833 : :
834 : : # ifdef USING_APPLE_OS_LIBFFI
835 : : # define HAVE_FFI_PREP_CIF_VAR_RUNTIME __builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *)
836 : : # elif HAVE_FFI_PREP_CIF_VAR
837 : : # define HAVE_FFI_PREP_CIF_VAR_RUNTIME true
838 : : # else
839 : : # define HAVE_FFI_PREP_CIF_VAR_RUNTIME false
840 : : # endif
841 : :
842 : : /* Even on Apple-arm64 the calling convention for variadic functions coincides
843 : : * with the standard calling convention in the case that the function called
844 : : * only with its fixed arguments. Thus, we do not need a special flag to be
845 : : * set on variadic functions. We treat a function as variadic if it is called
846 : : * with a nonzero number of variadic arguments */
847 [ + + + + ]: 6999 : bool is_variadic = (argtypecount != 0 && argcount > argtypecount);
848 : : (void) is_variadic;
849 : :
850 : : #if defined(__APPLE__) && defined(__arm64__)
851 : : if (is_variadic) {
852 : : if (HAVE_FFI_PREP_CIF_VAR_RUNTIME) {
853 : : } else {
854 : : PyErr_SetString(PyExc_NotImplementedError, "ffi_prep_cif_var() is missing");
855 : : return -1;
856 : : }
857 : : }
858 : : #endif
859 : :
860 : : #if HAVE_FFI_PREP_CIF_VAR
861 [ + + ]: 6999 : if (is_variadic) {
862 : : if (HAVE_FFI_PREP_CIF_VAR_RUNTIME) {
863 [ - + ]: 107 : if (FFI_OK != ffi_prep_cif_var(&cif,
864 : : cc,
865 : : argtypecount,
866 : : argcount,
867 : : restype,
868 : : atypes)) {
869 : 0 : PyErr_SetString(PyExc_RuntimeError,
870 : : "ffi_prep_cif_var failed");
871 : 0 : return -1;
872 : : }
873 : : } else {
874 : : if (FFI_OK != ffi_prep_cif(&cif,
875 : : cc,
876 : : argcount,
877 : : restype,
878 : : atypes)) {
879 : : PyErr_SetString(PyExc_RuntimeError,
880 : : "ffi_prep_cif failed");
881 : : return -1;
882 : : }
883 : : }
884 : : } else
885 : : #endif
886 : :
887 : : {
888 [ - + ]: 6892 : if (FFI_OK != ffi_prep_cif(&cif,
889 : : cc,
890 : : argcount,
891 : : restype,
892 : : atypes)) {
893 : 0 : PyErr_SetString(PyExc_RuntimeError,
894 : : "ffi_prep_cif failed");
895 : 0 : return -1;
896 : : }
897 : : }
898 : :
899 [ + + ]: 6999 : if (flags & (FUNCFLAG_USE_ERRNO | FUNCFLAG_USE_LASTERROR)) {
900 : 1 : error_object = _ctypes_get_errobj(&space);
901 [ - + ]: 1 : if (error_object == NULL)
902 : 0 : return -1;
903 : : }
904 [ + + ]: 6999 : if ((flags & FUNCFLAG_PYTHONAPI) == 0)
905 : 6799 : Py_UNBLOCK_THREADS
906 [ + + ]: 6999 : if (flags & FUNCFLAG_USE_ERRNO) {
907 : 1 : int temp = space[0];
908 : 1 : space[0] = errno;
909 : 1 : errno = temp;
910 : : }
911 : : #ifdef MS_WIN32
912 : : if (flags & FUNCFLAG_USE_LASTERROR) {
913 : : int temp = space[1];
914 : : space[1] = GetLastError();
915 : : SetLastError(temp);
916 : : }
917 : : #ifndef DONT_USE_SEH
918 : : __try {
919 : : #endif
920 : : #endif
921 : 6999 : ffi_call(&cif, (void *)pProc, resmem, avalues);
922 : : #ifdef MS_WIN32
923 : : #ifndef DONT_USE_SEH
924 : : }
925 : : __except (HandleException(GetExceptionInformation(),
926 : : &dwExceptionCode, &record)) {
927 : : ;
928 : : }
929 : : #endif
930 : : if (flags & FUNCFLAG_USE_LASTERROR) {
931 : : int temp = space[1];
932 : : space[1] = GetLastError();
933 : : SetLastError(temp);
934 : : }
935 : : #endif
936 [ + + ]: 6999 : if (flags & FUNCFLAG_USE_ERRNO) {
937 : 1 : int temp = space[0];
938 : 1 : space[0] = errno;
939 : 1 : errno = temp;
940 : : }
941 [ + + ]: 6999 : if ((flags & FUNCFLAG_PYTHONAPI) == 0)
942 : 6799 : Py_BLOCK_THREADS
943 : 6999 : Py_XDECREF(error_object);
944 : : #ifdef MS_WIN32
945 : : #ifndef DONT_USE_SEH
946 : : if (dwExceptionCode) {
947 : : SetException(dwExceptionCode, &record);
948 : : return -1;
949 : : }
950 : : #endif
951 : : #endif
952 [ + + + + ]: 6999 : if ((flags & FUNCFLAG_PYTHONAPI) && PyErr_Occurred())
953 : 11 : return -1;
954 : 6988 : return 0;
955 : : }
956 : :
957 : : /*
958 : : * Convert the C value in result into a Python object, depending on restype.
959 : : *
960 : : * - If restype is NULL, return a Python integer.
961 : : * - If restype is None, return None.
962 : : * - If restype is a simple ctypes type (c_int, c_void_p), call the type's getfunc,
963 : : * pass the result to checker and return the result.
964 : : * - If restype is another ctypes type, return an instance of that.
965 : : * - Otherwise, call restype and return the result.
966 : : */
967 : 6988 : static PyObject *GetResult(PyObject *restype, void *result, PyObject *checker)
968 : : {
969 : : StgDictObject *dict;
970 : : PyObject *retval, *v;
971 : :
972 [ - + ]: 6988 : if (restype == NULL)
973 : 0 : return PyLong_FromLong(*(int *)result);
974 : :
975 [ + + ]: 6988 : if (restype == Py_None) {
976 : 16 : Py_RETURN_NONE;
977 : : }
978 : :
979 : 6972 : dict = PyType_stgdict(restype);
980 [ + + ]: 6972 : if (dict == NULL)
981 : 2 : return PyObject_CallFunction(restype, "i", *(int *)result);
982 : :
983 [ + + + + ]: 6970 : if (dict->getfunc && !_ctypes_simple_instance(restype)) {
984 : 6933 : retval = dict->getfunc(result, dict->size);
985 : : /* If restype is py_object (detected by comparing getfunc with
986 : : O_get), we have to call Py_DECREF because O_get has already
987 : : called Py_INCREF.
988 : : */
989 [ + + ]: 6933 : if (dict->getfunc == _ctypes_get_fielddesc("O")->getfunc) {
990 : 182 : Py_DECREF(retval);
991 : : }
992 : : } else
993 : 37 : retval = PyCData_FromBaseObj(restype, NULL, 0, result);
994 : :
995 [ + + - + ]: 6970 : if (!checker || !retval)
996 : 6969 : return retval;
997 : :
998 : 1 : v = PyObject_CallOneArg(checker, retval);
999 [ - + ]: 1 : if (v == NULL)
1000 : 0 : _PyTraceback_Add("GetResult", "_ctypes/callproc.c", __LINE__-2);
1001 : 1 : Py_DECREF(retval);
1002 : 1 : return v;
1003 : : }
1004 : :
1005 : : /*
1006 : : * Raise a new exception 'exc_class', adding additional text to the original
1007 : : * exception string.
1008 : : */
1009 : 20 : void _ctypes_extend_error(PyObject *exc_class, const char *fmt, ...)
1010 : : {
1011 : : va_list vargs;
1012 : : PyObject *tp, *v, *tb, *s, *cls_str, *msg_str;
1013 : :
1014 : 20 : va_start(vargs, fmt);
1015 : 20 : s = PyUnicode_FromFormatV(fmt, vargs);
1016 : 20 : va_end(vargs);
1017 [ - + ]: 20 : if (!s)
1018 : 0 : return;
1019 : :
1020 : 20 : PyErr_Fetch(&tp, &v, &tb);
1021 : 20 : PyErr_NormalizeException(&tp, &v, &tb);
1022 : 20 : cls_str = PyObject_Str(tp);
1023 [ + - ]: 20 : if (cls_str) {
1024 : 20 : PyUnicode_AppendAndDel(&s, cls_str);
1025 : 20 : PyUnicode_AppendAndDel(&s, PyUnicode_FromString(": "));
1026 [ - + ]: 20 : if (s == NULL)
1027 : 0 : goto error;
1028 : : } else
1029 : 0 : PyErr_Clear();
1030 : 20 : msg_str = PyObject_Str(v);
1031 [ + - ]: 20 : if (msg_str)
1032 : 20 : PyUnicode_AppendAndDel(&s, msg_str);
1033 : : else {
1034 : 0 : PyErr_Clear();
1035 : 0 : PyUnicode_AppendAndDel(&s, PyUnicode_FromString("???"));
1036 : : }
1037 [ - + ]: 20 : if (s == NULL)
1038 : 0 : goto error;
1039 : 20 : PyErr_SetObject(exc_class, s);
1040 : 20 : error:
1041 : 20 : Py_XDECREF(tp);
1042 : 20 : Py_XDECREF(v);
1043 : 20 : Py_XDECREF(tb);
1044 : 20 : Py_XDECREF(s);
1045 : : }
1046 : :
1047 : :
1048 : : #ifdef MS_WIN32
1049 : :
1050 : : static PyObject *
1051 : : GetComError(HRESULT errcode, GUID *riid, IUnknown *pIunk)
1052 : : {
1053 : : HRESULT hr;
1054 : : ISupportErrorInfo *psei = NULL;
1055 : : IErrorInfo *pei = NULL;
1056 : : BSTR descr=NULL, helpfile=NULL, source=NULL;
1057 : : GUID guid;
1058 : : DWORD helpcontext=0;
1059 : : LPOLESTR progid;
1060 : : PyObject *obj;
1061 : : LPOLESTR text;
1062 : :
1063 : : /* We absolutely have to release the GIL during COM method calls,
1064 : : otherwise we may get a deadlock!
1065 : : */
1066 : : Py_BEGIN_ALLOW_THREADS
1067 : :
1068 : : hr = pIunk->lpVtbl->QueryInterface(pIunk, &IID_ISupportErrorInfo, (void **)&psei);
1069 : : if (FAILED(hr))
1070 : : goto failed;
1071 : :
1072 : : hr = psei->lpVtbl->InterfaceSupportsErrorInfo(psei, riid);
1073 : : psei->lpVtbl->Release(psei);
1074 : : if (FAILED(hr))
1075 : : goto failed;
1076 : :
1077 : : hr = GetErrorInfo(0, &pei);
1078 : : if (hr != S_OK)
1079 : : goto failed;
1080 : :
1081 : : pei->lpVtbl->GetDescription(pei, &descr);
1082 : : pei->lpVtbl->GetGUID(pei, &guid);
1083 : : pei->lpVtbl->GetHelpContext(pei, &helpcontext);
1084 : : pei->lpVtbl->GetHelpFile(pei, &helpfile);
1085 : : pei->lpVtbl->GetSource(pei, &source);
1086 : :
1087 : : pei->lpVtbl->Release(pei);
1088 : :
1089 : : failed:
1090 : : Py_END_ALLOW_THREADS
1091 : :
1092 : : progid = NULL;
1093 : : ProgIDFromCLSID(&guid, &progid);
1094 : :
1095 : : text = FormatError(errcode);
1096 : : obj = Py_BuildValue(
1097 : : "iu(uuuiu)",
1098 : : errcode,
1099 : : text,
1100 : : descr, source, helpfile, helpcontext,
1101 : : progid);
1102 : : if (obj) {
1103 : : PyErr_SetObject(ComError, obj);
1104 : : Py_DECREF(obj);
1105 : : }
1106 : : LocalFree(text);
1107 : :
1108 : : if (descr)
1109 : : SysFreeString(descr);
1110 : : if (helpfile)
1111 : : SysFreeString(helpfile);
1112 : : if (source)
1113 : : SysFreeString(source);
1114 : :
1115 : : return NULL;
1116 : : }
1117 : : #endif
1118 : :
1119 : : #if (defined(__x86_64__) && (defined(__MINGW64__) || defined(__CYGWIN__))) || \
1120 : : defined(__aarch64__) || defined(__riscv)
1121 : : #define CTYPES_PASS_BY_REF_HACK
1122 : : #define POW2(x) (((x & ~(x - 1)) == x) ? x : 0)
1123 : : #define IS_PASS_BY_REF(x) (x > 8 || !POW2(x))
1124 : : #endif
1125 : :
1126 : : /*
1127 : : * Requirements, must be ensured by the caller:
1128 : : * - argtuple is tuple of arguments
1129 : : * - argtypes is either NULL, or a tuple of the same size as argtuple
1130 : : *
1131 : : * - XXX various requirements for restype, not yet collected
1132 : : */
1133 : 7017 : PyObject *_ctypes_callproc(PPROC pProc,
1134 : : PyObject *argtuple,
1135 : : #ifdef MS_WIN32
1136 : : IUnknown *pIunk,
1137 : : GUID *iid,
1138 : : #endif
1139 : : int flags,
1140 : : PyObject *argtypes, /* misleading name: This is a tuple of
1141 : : methods, not types: the .from_param
1142 : : class methods of the types */
1143 : : PyObject *restype,
1144 : : PyObject *checker)
1145 : : {
1146 : : Py_ssize_t i, n, argcount, argtype_count;
1147 : : void *resbuf;
1148 : : struct argument *args, *pa;
1149 : : ffi_type **atypes;
1150 : : ffi_type *rtype;
1151 : : void **avalues;
1152 : 7017 : PyObject *retval = NULL;
1153 : :
1154 : 7017 : n = argcount = PyTuple_GET_SIZE(argtuple);
1155 : : #ifdef MS_WIN32
1156 : : /* an optional COM object this pointer */
1157 : : if (pIunk)
1158 : : ++argcount;
1159 : : #endif
1160 : :
1161 [ + + ]: 7017 : if (argcount > CTYPES_MAX_ARGCOUNT)
1162 : : {
1163 : 1 : PyErr_Format(PyExc_ArgError, "too many arguments (%zi), maximum is %i",
1164 : : argcount, CTYPES_MAX_ARGCOUNT);
1165 : 1 : return NULL;
1166 : : }
1167 : :
1168 : 7016 : args = alloca(sizeof(struct argument) * argcount);
1169 : 7016 : memset(args, 0, sizeof(struct argument) * argcount);
1170 [ + + ]: 7016 : argtype_count = argtypes ? PyTuple_GET_SIZE(argtypes) : 0;
1171 : : #ifdef MS_WIN32
1172 : : if (pIunk) {
1173 : : args[0].ffi_type = &ffi_type_pointer;
1174 : : args[0].value.p = pIunk;
1175 : : pa = &args[1];
1176 : : } else
1177 : : #endif
1178 : 7016 : pa = &args[0];
1179 : :
1180 : : /* Convert the arguments */
1181 [ + + ]: 22133 : for (i = 0; i < n; ++i, ++pa) {
1182 : : PyObject *converter;
1183 : : PyObject *arg;
1184 : : int err;
1185 : :
1186 : 15134 : arg = PyTuple_GET_ITEM(argtuple, i); /* borrowed ref */
1187 : : /* For cdecl functions, we allow more actual arguments
1188 : : than the length of the argtypes tuple.
1189 : : This is checked in _ctypes::PyCFuncPtr_Call
1190 : : */
1191 [ + + + + ]: 30072 : if (argtypes && argtype_count > i) {
1192 : : PyObject *v;
1193 : 14955 : converter = PyTuple_GET_ITEM(argtypes, i);
1194 : 14955 : v = PyObject_CallOneArg(converter, arg);
1195 [ + + ]: 14955 : if (v == NULL) {
1196 : 16 : _ctypes_extend_error(PyExc_ArgError, "argument %zd: ", i+1);
1197 : 16 : goto cleanup;
1198 : : }
1199 : :
1200 : 14939 : err = ConvParam(v, i+1, pa);
1201 : 14939 : Py_DECREF(v);
1202 [ + + ]: 14939 : if (-1 == err) {
1203 : 1 : _ctypes_extend_error(PyExc_ArgError, "argument %zd: ", i+1);
1204 : 1 : goto cleanup;
1205 : : }
1206 : : } else {
1207 : 179 : err = ConvParam(arg, i+1, pa);
1208 [ - + ]: 179 : if (-1 == err) {
1209 : 0 : _ctypes_extend_error(PyExc_ArgError, "argument %zd: ", i+1);
1210 : 0 : goto cleanup; /* leaking ? */
1211 : : }
1212 : : }
1213 : : }
1214 : :
1215 [ + + ]: 6999 : if (restype == Py_None) {
1216 : 16 : rtype = &ffi_type_void;
1217 : : } else {
1218 : 6983 : rtype = _ctypes_get_ffi_type(restype);
1219 : : }
1220 : :
1221 : 6999 : resbuf = alloca(max(rtype->size, sizeof(ffi_arg)));
1222 : :
1223 : : #ifdef _Py_MEMORY_SANITIZER
1224 : : /* ffi_call actually initializes resbuf, but from asm, which
1225 : : * MemorySanitizer can't detect. Avoid false positives from MSan. */
1226 : : if (resbuf != NULL) {
1227 : : __msan_unpoison(resbuf, max(rtype->size, sizeof(ffi_arg)));
1228 : : }
1229 : : #endif
1230 : 6999 : avalues = (void **)alloca(sizeof(void *) * argcount);
1231 : 6999 : atypes = (ffi_type **)alloca(sizeof(ffi_type *) * argcount);
1232 [ + - + - : 6999 : if (!resbuf || !avalues || !atypes) {
- + ]
1233 : : PyErr_NoMemory();
1234 : 0 : goto cleanup;
1235 : : }
1236 [ + + ]: 22108 : for (i = 0; i < argcount; ++i) {
1237 : 15109 : atypes[i] = args[i].ffi_type;
1238 : : #ifdef CTYPES_PASS_BY_REF_HACK
1239 : : size_t size = atypes[i]->size;
1240 : : if (IS_PASS_BY_REF(size)) {
1241 : : void *tmp = alloca(size);
1242 : : if (atypes[i]->type == FFI_TYPE_STRUCT)
1243 : : memcpy(tmp, args[i].value.p, size);
1244 : : else
1245 : : memcpy(tmp, (void*)&args[i].value, size);
1246 : :
1247 : : avalues[i] = tmp;
1248 : : }
1249 : : else
1250 : : #endif
1251 [ + + ]: 15109 : if (atypes[i]->type == FFI_TYPE_STRUCT)
1252 : 44 : avalues[i] = (void *)args[i].value.p;
1253 : : else
1254 : 15065 : avalues[i] = (void *)&args[i].value;
1255 : : }
1256 : :
1257 [ + + ]: 6999 : if (-1 == _call_function_pointer(flags, pProc, avalues, atypes,
1258 : : rtype, resbuf,
1259 : : Py_SAFE_DOWNCAST(argcount, Py_ssize_t, int),
1260 : : Py_SAFE_DOWNCAST(argtype_count, Py_ssize_t, int)))
1261 : 11 : goto cleanup;
1262 : :
1263 : : #ifdef WORDS_BIGENDIAN
1264 : : /* libffi returns the result in a buffer with sizeof(ffi_arg). This
1265 : : causes problems on big endian machines, since the result buffer
1266 : : address cannot simply be used as result pointer, instead we must
1267 : : adjust the pointer value:
1268 : : */
1269 : : /*
1270 : : XXX I should find out and clarify why this is needed at all,
1271 : : especially why adjusting for ffi_type_float must be avoided on
1272 : : 64-bit platforms.
1273 : : */
1274 : : if (rtype->type != FFI_TYPE_FLOAT
1275 : : && rtype->type != FFI_TYPE_STRUCT
1276 : : && rtype->size < sizeof(ffi_arg))
1277 : : {
1278 : : resbuf = (char *)resbuf + sizeof(ffi_arg) - rtype->size;
1279 : : }
1280 : : #endif
1281 : :
1282 : : #ifdef MS_WIN32
1283 : : if (iid && pIunk) {
1284 : : if (*(int *)resbuf & 0x80000000)
1285 : : retval = GetComError(*(HRESULT *)resbuf, iid, pIunk);
1286 : : else
1287 : : retval = PyLong_FromLong(*(int *)resbuf);
1288 : : } else if (flags & FUNCFLAG_HRESULT) {
1289 : : if (*(int *)resbuf & 0x80000000)
1290 : : retval = PyErr_SetFromWindowsErr(*(int *)resbuf);
1291 : : else
1292 : : retval = PyLong_FromLong(*(int *)resbuf);
1293 : : } else
1294 : : #endif
1295 : 6988 : retval = GetResult(restype, resbuf, checker);
1296 : 7016 : cleanup:
1297 [ + + ]: 22151 : for (i = 0; i < argcount; ++i)
1298 : 15135 : Py_XDECREF(args[i].keep);
1299 : 7016 : return retval;
1300 : : }
1301 : :
1302 : : static int
1303 : 0 : _parse_voidp(PyObject *obj, void **address)
1304 : : {
1305 : 0 : *address = PyLong_AsVoidPtr(obj);
1306 [ # # ]: 0 : if (*address == NULL)
1307 : 0 : return 0;
1308 : 0 : return 1;
1309 : : }
1310 : :
1311 : : #ifdef MS_WIN32
1312 : :
1313 : : PyDoc_STRVAR(format_error_doc,
1314 : : "FormatError([integer]) -> string\n\
1315 : : \n\
1316 : : Convert a win32 error code into a string. If the error code is not\n\
1317 : : given, the return value of a call to GetLastError() is used.\n");
1318 : : static PyObject *format_error(PyObject *self, PyObject *args)
1319 : : {
1320 : : PyObject *result;
1321 : : wchar_t *lpMsgBuf;
1322 : : DWORD code = 0;
1323 : : if (!PyArg_ParseTuple(args, "|i:FormatError", &code))
1324 : : return NULL;
1325 : : if (code == 0)
1326 : : code = GetLastError();
1327 : : lpMsgBuf = FormatError(code);
1328 : : if (lpMsgBuf) {
1329 : : result = PyUnicode_FromWideChar(lpMsgBuf, wcslen(lpMsgBuf));
1330 : : LocalFree(lpMsgBuf);
1331 : : } else {
1332 : : result = PyUnicode_FromString("<no description>");
1333 : : }
1334 : : return result;
1335 : : }
1336 : :
1337 : : PyDoc_STRVAR(load_library_doc,
1338 : : "LoadLibrary(name, load_flags) -> handle\n\
1339 : : \n\
1340 : : Load an executable (usually a DLL), and return a handle to it.\n\
1341 : : The handle may be used to locate exported functions in this\n\
1342 : : module. load_flags are as defined for LoadLibraryEx in the\n\
1343 : : Windows API.\n");
1344 : : static PyObject *load_library(PyObject *self, PyObject *args)
1345 : : {
1346 : : PyObject *nameobj;
1347 : : int load_flags = 0;
1348 : : HMODULE hMod;
1349 : : DWORD err;
1350 : :
1351 : : if (!PyArg_ParseTuple(args, "U|i:LoadLibrary", &nameobj, &load_flags))
1352 : : return NULL;
1353 : :
1354 : : if (PySys_Audit("ctypes.dlopen", "O", nameobj) < 0) {
1355 : : return NULL;
1356 : : }
1357 : :
1358 : : WCHAR *name = PyUnicode_AsWideCharString(nameobj, NULL);
1359 : : if (!name)
1360 : : return NULL;
1361 : :
1362 : : Py_BEGIN_ALLOW_THREADS
1363 : : /* bpo-36085: Limit DLL search directories to avoid pre-loading
1364 : : * attacks and enable use of the AddDllDirectory function.
1365 : : */
1366 : : hMod = LoadLibraryExW(name, NULL, (DWORD)load_flags);
1367 : : err = hMod ? 0 : GetLastError();
1368 : : Py_END_ALLOW_THREADS
1369 : :
1370 : : PyMem_Free(name);
1371 : : if (err == ERROR_MOD_NOT_FOUND) {
1372 : : PyErr_Format(PyExc_FileNotFoundError,
1373 : : ("Could not find module '%.500S' (or one of its "
1374 : : "dependencies). Try using the full path with "
1375 : : "constructor syntax."),
1376 : : nameobj);
1377 : : return NULL;
1378 : : } else if (err) {
1379 : : return PyErr_SetFromWindowsErr(err);
1380 : : }
1381 : : #ifdef _WIN64
1382 : : return PyLong_FromVoidPtr(hMod);
1383 : : #else
1384 : : return Py_BuildValue("i", hMod);
1385 : : #endif
1386 : : }
1387 : :
1388 : : PyDoc_STRVAR(free_library_doc,
1389 : : "FreeLibrary(handle) -> void\n\
1390 : : \n\
1391 : : Free the handle of an executable previously loaded by LoadLibrary.\n");
1392 : : static PyObject *free_library(PyObject *self, PyObject *args)
1393 : : {
1394 : : void *hMod;
1395 : : BOOL result;
1396 : : DWORD err;
1397 : : if (!PyArg_ParseTuple(args, "O&:FreeLibrary", &_parse_voidp, &hMod))
1398 : : return NULL;
1399 : :
1400 : : Py_BEGIN_ALLOW_THREADS
1401 : : result = FreeLibrary((HMODULE)hMod);
1402 : : err = result ? 0 : GetLastError();
1403 : : Py_END_ALLOW_THREADS
1404 : :
1405 : : if (!result) {
1406 : : return PyErr_SetFromWindowsErr(err);
1407 : : }
1408 : : Py_RETURN_NONE;
1409 : : }
1410 : :
1411 : : PyDoc_STRVAR(copy_com_pointer_doc,
1412 : : "CopyComPointer(src, dst) -> HRESULT value\n");
1413 : :
1414 : : static PyObject *
1415 : : copy_com_pointer(PyObject *self, PyObject *args)
1416 : : {
1417 : : PyObject *p1, *p2, *r = NULL;
1418 : : struct argument a, b;
1419 : : IUnknown *src, **pdst;
1420 : : if (!PyArg_ParseTuple(args, "OO:CopyComPointer", &p1, &p2))
1421 : : return NULL;
1422 : : a.keep = b.keep = NULL;
1423 : :
1424 : : if (-1 == ConvParam(p1, 0, &a) || -1 == ConvParam(p2, 1, &b))
1425 : : goto done;
1426 : : src = (IUnknown *)a.value.p;
1427 : : pdst = (IUnknown **)b.value.p;
1428 : :
1429 : : if (pdst == NULL)
1430 : : r = PyLong_FromLong(E_POINTER);
1431 : : else {
1432 : : if (src)
1433 : : src->lpVtbl->AddRef(src);
1434 : : *pdst = src;
1435 : : r = PyLong_FromLong(S_OK);
1436 : : }
1437 : : done:
1438 : : Py_XDECREF(a.keep);
1439 : : Py_XDECREF(b.keep);
1440 : : return r;
1441 : : }
1442 : : #else
1443 : : #ifdef __APPLE__
1444 : : #ifdef HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH
1445 : : #define HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH_RUNTIME \
1446 : : __builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *)
1447 : : #else
1448 : : // Support the deprecated case of compiling on an older macOS version
1449 : : static void *libsystem_b_handle;
1450 : : static bool (*_dyld_shared_cache_contains_path)(const char *path);
1451 : :
1452 : : __attribute__((constructor)) void load_dyld_shared_cache_contains_path(void) {
1453 : : libsystem_b_handle = dlopen("/usr/lib/libSystem.B.dylib", RTLD_LAZY);
1454 : : if (libsystem_b_handle != NULL) {
1455 : : _dyld_shared_cache_contains_path = dlsym(libsystem_b_handle, "_dyld_shared_cache_contains_path");
1456 : : }
1457 : : }
1458 : :
1459 : : __attribute__((destructor)) void unload_dyld_shared_cache_contains_path(void) {
1460 : : if (libsystem_b_handle != NULL) {
1461 : : dlclose(libsystem_b_handle);
1462 : : }
1463 : : }
1464 : : #define HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH_RUNTIME \
1465 : : _dyld_shared_cache_contains_path != NULL
1466 : : #endif
1467 : :
1468 : : static PyObject *py_dyld_shared_cache_contains_path(PyObject *self, PyObject *args)
1469 : : {
1470 : : PyObject *name, *name2;
1471 : : char *name_str;
1472 : :
1473 : : if (HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH_RUNTIME) {
1474 : : int r;
1475 : :
1476 : : if (!PyArg_ParseTuple(args, "O", &name))
1477 : : return NULL;
1478 : :
1479 : : if (name == Py_None)
1480 : : Py_RETURN_FALSE;
1481 : :
1482 : : if (PyUnicode_FSConverter(name, &name2) == 0)
1483 : : return NULL;
1484 : : name_str = PyBytes_AS_STRING(name2);
1485 : :
1486 : : r = _dyld_shared_cache_contains_path(name_str);
1487 : : Py_DECREF(name2);
1488 : :
1489 : : if (r) {
1490 : : Py_RETURN_TRUE;
1491 : : } else {
1492 : : Py_RETURN_FALSE;
1493 : : }
1494 : :
1495 : : } else {
1496 : : PyErr_SetString(PyExc_NotImplementedError, "_dyld_shared_cache_contains_path symbol is missing");
1497 : : return NULL;
1498 : : }
1499 : :
1500 : : }
1501 : : #endif
1502 : :
1503 : 378 : static PyObject *py_dl_open(PyObject *self, PyObject *args)
1504 : : {
1505 : : PyObject *name, *name2;
1506 : : const char *name_str;
1507 : : void * handle;
1508 : : #if HAVE_DECL_RTLD_LOCAL
1509 : 378 : int mode = RTLD_NOW | RTLD_LOCAL;
1510 : : #else
1511 : : /* cygwin doesn't define RTLD_LOCAL */
1512 : : int mode = RTLD_NOW;
1513 : : #endif
1514 [ - + ]: 378 : if (!PyArg_ParseTuple(args, "O|i:dlopen", &name, &mode))
1515 : 0 : return NULL;
1516 : 378 : mode |= RTLD_NOW;
1517 [ + + ]: 378 : if (name != Py_None) {
1518 [ - + ]: 52 : if (PyUnicode_FSConverter(name, &name2) == 0)
1519 : 0 : return NULL;
1520 : 52 : name_str = PyBytes_AS_STRING(name2);
1521 : : } else {
1522 : 326 : name_str = NULL;
1523 : 326 : name2 = NULL;
1524 : : }
1525 [ - + ]: 378 : if (PySys_Audit("ctypes.dlopen", "O", name) < 0) {
1526 : 0 : return NULL;
1527 : : }
1528 : 378 : handle = ctypes_dlopen(name_str, mode);
1529 : 378 : Py_XDECREF(name2);
1530 [ + + ]: 378 : if (!handle) {
1531 : 3 : const char *errmsg = ctypes_dlerror();
1532 [ - + ]: 3 : if (!errmsg)
1533 : 0 : errmsg = "dlopen() error";
1534 : 3 : PyErr_SetString(PyExc_OSError,
1535 : : errmsg);
1536 : 3 : return NULL;
1537 : : }
1538 : 375 : return PyLong_FromVoidPtr(handle);
1539 : : }
1540 : :
1541 : 0 : static PyObject *py_dl_close(PyObject *self, PyObject *args)
1542 : : {
1543 : : void *handle;
1544 : :
1545 [ # # ]: 0 : if (!PyArg_ParseTuple(args, "O&:dlclose", &_parse_voidp, &handle))
1546 : 0 : return NULL;
1547 [ # # ]: 0 : if (dlclose(handle)) {
1548 : 0 : PyErr_SetString(PyExc_OSError,
1549 : 0 : ctypes_dlerror());
1550 : 0 : return NULL;
1551 : : }
1552 : 0 : Py_RETURN_NONE;
1553 : : }
1554 : :
1555 : 0 : static PyObject *py_dl_sym(PyObject *self, PyObject *args)
1556 : : {
1557 : : char *name;
1558 : : void *handle;
1559 : : void *ptr;
1560 : :
1561 [ # # ]: 0 : if (!PyArg_ParseTuple(args, "O&s:dlsym",
1562 : : &_parse_voidp, &handle, &name))
1563 : 0 : return NULL;
1564 [ # # ]: 0 : if (PySys_Audit("ctypes.dlsym/handle", "O", args) < 0) {
1565 : 0 : return NULL;
1566 : : }
1567 : 0 : ptr = ctypes_dlsym((void*)handle, name);
1568 [ # # ]: 0 : if (!ptr) {
1569 : 0 : PyErr_SetString(PyExc_OSError,
1570 : 0 : ctypes_dlerror());
1571 : 0 : return NULL;
1572 : : }
1573 : 0 : return PyLong_FromVoidPtr(ptr);
1574 : : }
1575 : : #endif
1576 : :
1577 : : /*
1578 : : * Only for debugging so far: So that we can call CFunction instances
1579 : : *
1580 : : * XXX Needs to accept more arguments: flags, argtypes, restype
1581 : : */
1582 : : static PyObject *
1583 : 0 : call_function(PyObject *self, PyObject *args)
1584 : : {
1585 : : void *func;
1586 : : PyObject *arguments;
1587 : : PyObject *result;
1588 : :
1589 [ # # ]: 0 : if (!PyArg_ParseTuple(args,
1590 : : "O&O!",
1591 : : &_parse_voidp, &func,
1592 : : &PyTuple_Type, &arguments))
1593 : 0 : return NULL;
1594 [ # # ]: 0 : if (PySys_Audit("ctypes.call_function", "nO",
1595 : : (Py_ssize_t)func, arguments) < 0) {
1596 : 0 : return NULL;
1597 : : }
1598 : :
1599 : 0 : result = _ctypes_callproc((PPROC)func,
1600 : : arguments,
1601 : : #ifdef MS_WIN32
1602 : : NULL,
1603 : : NULL,
1604 : : #endif
1605 : : 0, /* flags */
1606 : : NULL, /* self->argtypes */
1607 : : NULL, /* self->restype */
1608 : : NULL); /* checker */
1609 : 0 : return result;
1610 : : }
1611 : :
1612 : : /*
1613 : : * Only for debugging so far: So that we can call CFunction instances
1614 : : *
1615 : : * XXX Needs to accept more arguments: flags, argtypes, restype
1616 : : */
1617 : : static PyObject *
1618 : 0 : call_cdeclfunction(PyObject *self, PyObject *args)
1619 : : {
1620 : : void *func;
1621 : : PyObject *arguments;
1622 : : PyObject *result;
1623 : :
1624 [ # # ]: 0 : if (!PyArg_ParseTuple(args,
1625 : : "O&O!",
1626 : : &_parse_voidp, &func,
1627 : : &PyTuple_Type, &arguments))
1628 : 0 : return NULL;
1629 [ # # ]: 0 : if (PySys_Audit("ctypes.call_function", "nO",
1630 : : (Py_ssize_t)func, arguments) < 0) {
1631 : 0 : return NULL;
1632 : : }
1633 : :
1634 : 0 : result = _ctypes_callproc((PPROC)func,
1635 : : arguments,
1636 : : #ifdef MS_WIN32
1637 : : NULL,
1638 : : NULL,
1639 : : #endif
1640 : : FUNCFLAG_CDECL, /* flags */
1641 : : NULL, /* self->argtypes */
1642 : : NULL, /* self->restype */
1643 : : NULL); /* checker */
1644 : 0 : return result;
1645 : : }
1646 : :
1647 : : /*****************************************************************
1648 : : * functions
1649 : : */
1650 : : PyDoc_STRVAR(sizeof_doc,
1651 : : "sizeof(C type) -> integer\n"
1652 : : "sizeof(C instance) -> integer\n"
1653 : : "Return the size in bytes of a C instance");
1654 : :
1655 : : static PyObject *
1656 : 13024 : sizeof_func(PyObject *self, PyObject *obj)
1657 : : {
1658 : : StgDictObject *dict;
1659 : :
1660 : 13024 : dict = PyType_stgdict(obj);
1661 [ + + ]: 13024 : if (dict)
1662 : 12864 : return PyLong_FromSsize_t(dict->size);
1663 : :
1664 [ + - ]: 160 : if (CDataObject_Check(obj))
1665 : 160 : return PyLong_FromSsize_t(((CDataObject *)obj)->b_size);
1666 : 0 : PyErr_SetString(PyExc_TypeError,
1667 : : "this type has no size");
1668 : 0 : return NULL;
1669 : : }
1670 : :
1671 : : PyDoc_STRVAR(alignment_doc,
1672 : : "alignment(C type) -> integer\n"
1673 : : "alignment(C instance) -> integer\n"
1674 : : "Return the alignment requirements of a C instance");
1675 : :
1676 : : static PyObject *
1677 : 41 : align_func(PyObject *self, PyObject *obj)
1678 : : {
1679 : : StgDictObject *dict;
1680 : :
1681 : 41 : dict = PyType_stgdict(obj);
1682 [ + + ]: 41 : if (dict)
1683 : 28 : return PyLong_FromSsize_t(dict->align);
1684 : :
1685 : 13 : dict = PyObject_stgdict(obj);
1686 [ + - ]: 13 : if (dict)
1687 : 13 : return PyLong_FromSsize_t(dict->align);
1688 : :
1689 : 0 : PyErr_SetString(PyExc_TypeError,
1690 : : "no alignment info");
1691 : 0 : return NULL;
1692 : : }
1693 : :
1694 : : PyDoc_STRVAR(byref_doc,
1695 : : "byref(C instance[, offset=0]) -> byref-object\n"
1696 : : "Return a pointer lookalike to a C instance, only usable\n"
1697 : : "as function argument");
1698 : :
1699 : : /*
1700 : : * We must return something which can be converted to a parameter,
1701 : : * but still has a reference to self.
1702 : : */
1703 : : static PyObject *
1704 : 6454 : byref(PyObject *self, PyObject *args)
1705 : : {
1706 : : PyCArgObject *parg;
1707 : : PyObject *obj;
1708 : 6454 : PyObject *pyoffset = NULL;
1709 : 6454 : Py_ssize_t offset = 0;
1710 : :
1711 [ - + ]: 6454 : if (!PyArg_UnpackTuple(args, "byref", 1, 2,
1712 : : &obj, &pyoffset))
1713 : 0 : return NULL;
1714 [ - + ]: 6454 : if (pyoffset) {
1715 : 0 : offset = PyNumber_AsSsize_t(pyoffset, NULL);
1716 [ # # # # ]: 0 : if (offset == -1 && PyErr_Occurred())
1717 : 0 : return NULL;
1718 : : }
1719 [ - + ]: 6454 : if (!CDataObject_Check(obj)) {
1720 : 0 : PyErr_Format(PyExc_TypeError,
1721 : : "byref() argument must be a ctypes instance, not '%s'",
1722 : 0 : Py_TYPE(obj)->tp_name);
1723 : 0 : return NULL;
1724 : : }
1725 : :
1726 : 6454 : parg = PyCArgObject_new();
1727 [ - + ]: 6454 : if (parg == NULL)
1728 : 0 : return NULL;
1729 : :
1730 : 6454 : parg->tag = 'P';
1731 : 6454 : parg->pffi_type = &ffi_type_pointer;
1732 : 6454 : Py_INCREF(obj);
1733 : 6454 : parg->obj = obj;
1734 : 6454 : parg->value.p = (char *)((CDataObject *)obj)->b_ptr + offset;
1735 : 6454 : return (PyObject *)parg;
1736 : : }
1737 : :
1738 : : PyDoc_STRVAR(addressof_doc,
1739 : : "addressof(C instance) -> integer\n"
1740 : : "Return the address of the C instance internal buffer");
1741 : :
1742 : : static PyObject *
1743 : 100 : addressof(PyObject *self, PyObject *obj)
1744 : : {
1745 [ - + ]: 100 : if (!CDataObject_Check(obj)) {
1746 : 0 : PyErr_SetString(PyExc_TypeError,
1747 : : "invalid type");
1748 : 0 : return NULL;
1749 : : }
1750 [ - + ]: 100 : if (PySys_Audit("ctypes.addressof", "(O)", obj) < 0) {
1751 : 0 : return NULL;
1752 : : }
1753 : 100 : return PyLong_FromVoidPtr(((CDataObject *)obj)->b_ptr);
1754 : : }
1755 : :
1756 : : static int
1757 : 1 : converter(PyObject *obj, void **address)
1758 : : {
1759 : 1 : *address = PyLong_AsVoidPtr(obj);
1760 : 1 : return *address != NULL;
1761 : : }
1762 : :
1763 : : static PyObject *
1764 : 1 : My_PyObj_FromPtr(PyObject *self, PyObject *args)
1765 : : {
1766 : : PyObject *ob;
1767 [ - + ]: 1 : if (!PyArg_ParseTuple(args, "O&:PyObj_FromPtr", converter, &ob)) {
1768 : 0 : return NULL;
1769 : : }
1770 [ - + ]: 1 : if (PySys_Audit("ctypes.PyObj_FromPtr", "(O)", ob) < 0) {
1771 : 0 : return NULL;
1772 : : }
1773 : 1 : Py_INCREF(ob);
1774 : 1 : return ob;
1775 : : }
1776 : :
1777 : : static PyObject *
1778 : 0 : My_Py_INCREF(PyObject *self, PyObject *arg)
1779 : : {
1780 : 0 : Py_INCREF(arg); /* that's what this function is for */
1781 : 0 : Py_INCREF(arg); /* that for returning it */
1782 : 0 : return arg;
1783 : : }
1784 : :
1785 : : static PyObject *
1786 : 0 : My_Py_DECREF(PyObject *self, PyObject *arg)
1787 : : {
1788 : 0 : Py_DECREF(arg); /* that's what this function is for */
1789 : 0 : Py_INCREF(arg); /* that's for returning it */
1790 : 0 : return arg;
1791 : : }
1792 : :
1793 : : static PyObject *
1794 : 33 : resize(PyObject *self, PyObject *args)
1795 : : {
1796 : : CDataObject *obj;
1797 : : StgDictObject *dict;
1798 : : Py_ssize_t size;
1799 : :
1800 [ - + ]: 33 : if (!PyArg_ParseTuple(args,
1801 : : "On:resize",
1802 : : &obj, &size))
1803 : 0 : return NULL;
1804 : :
1805 : 33 : dict = PyObject_stgdict((PyObject *)obj);
1806 [ - + ]: 33 : if (dict == NULL) {
1807 : 0 : PyErr_SetString(PyExc_TypeError,
1808 : : "excepted ctypes instance");
1809 : 0 : return NULL;
1810 : : }
1811 [ - + ]: 33 : if (size < dict->size) {
1812 : 0 : PyErr_Format(PyExc_ValueError,
1813 : : "minimum size is %zd",
1814 : : dict->size);
1815 : 0 : return NULL;
1816 : : }
1817 [ - + ]: 33 : if (obj->b_needsfree == 0) {
1818 : 0 : PyErr_Format(PyExc_ValueError,
1819 : : "Memory cannot be resized because this object doesn't own it");
1820 : 0 : return NULL;
1821 : : }
1822 [ + + ]: 33 : if ((size_t)size <= sizeof(obj->b_value)) {
1823 : : /* internal default buffer is large enough */
1824 : 32 : obj->b_size = size;
1825 : 32 : goto done;
1826 : : }
1827 [ + - ]: 1 : if (!_CDataObject_HasExternalBuffer(obj)) {
1828 : : /* We are currently using the objects default buffer, but it
1829 : : isn't large enough any more. */
1830 : 1 : void *ptr = PyMem_Calloc(1, size);
1831 [ - + ]: 1 : if (ptr == NULL)
1832 : : return PyErr_NoMemory();
1833 : 1 : memmove(ptr, obj->b_ptr, obj->b_size);
1834 : 1 : obj->b_ptr = ptr;
1835 : 1 : obj->b_size = size;
1836 : : } else {
1837 : 0 : void * ptr = PyMem_Realloc(obj->b_ptr, size);
1838 [ # # ]: 0 : if (ptr == NULL)
1839 : : return PyErr_NoMemory();
1840 : 0 : obj->b_ptr = ptr;
1841 : 0 : obj->b_size = size;
1842 : : }
1843 : 33 : done:
1844 : 33 : Py_RETURN_NONE;
1845 : : }
1846 : :
1847 : : static PyObject *
1848 : 18 : unpickle(PyObject *self, PyObject *args)
1849 : : {
1850 : : PyObject *typ, *state, *meth, *obj, *result;
1851 : : _Py_IDENTIFIER(__new__);
1852 : : _Py_IDENTIFIER(__setstate__);
1853 : :
1854 [ - + ]: 18 : if (!PyArg_ParseTuple(args, "OO!", &typ, &PyTuple_Type, &state))
1855 : 0 : return NULL;
1856 : 18 : obj = _PyObject_CallMethodIdOneArg(typ, &PyId___new__, typ);
1857 [ - + ]: 18 : if (obj == NULL)
1858 : 0 : return NULL;
1859 : :
1860 : 18 : meth = _PyObject_GetAttrId(obj, &PyId___setstate__);
1861 [ - + ]: 18 : if (meth == NULL) {
1862 : 0 : goto error;
1863 : : }
1864 : :
1865 : 18 : result = PyObject_Call(meth, state, NULL);
1866 : 18 : Py_DECREF(meth);
1867 [ - + ]: 18 : if (result == NULL) {
1868 : 0 : goto error;
1869 : : }
1870 : 18 : Py_DECREF(result);
1871 : :
1872 : 18 : return obj;
1873 : :
1874 : 0 : error:
1875 : 0 : Py_DECREF(obj);
1876 : 0 : return NULL;
1877 : : }
1878 : :
1879 : : static PyObject *
1880 : 824 : POINTER(PyObject *self, PyObject *cls)
1881 : : {
1882 : : PyObject *result;
1883 : : PyTypeObject *typ;
1884 : : PyObject *key;
1885 : : char *buf;
1886 : :
1887 : 824 : result = PyDict_GetItemWithError(_ctypes_ptrtype_cache, cls);
1888 [ + + ]: 824 : if (result) {
1889 : 117 : Py_INCREF(result);
1890 : 117 : return result;
1891 : : }
1892 [ - + ]: 707 : else if (PyErr_Occurred()) {
1893 : 0 : return NULL;
1894 : : }
1895 [ + + ]: 707 : if (PyUnicode_CheckExact(cls)) {
1896 : 2 : const char *name = PyUnicode_AsUTF8(cls);
1897 [ - + ]: 2 : if (name == NULL)
1898 : 0 : return NULL;
1899 : 2 : buf = PyMem_Malloc(strlen(name) + 3 + 1);
1900 [ - + ]: 2 : if (buf == NULL)
1901 : : return PyErr_NoMemory();
1902 : 2 : sprintf(buf, "LP_%s", name);
1903 : 2 : result = PyObject_CallFunction((PyObject *)Py_TYPE(&PyCPointer_Type),
1904 : : "s(O){}",
1905 : : buf,
1906 : : &PyCPointer_Type);
1907 : 2 : PyMem_Free(buf);
1908 [ - + ]: 2 : if (result == NULL)
1909 : 0 : return result;
1910 : 2 : key = PyLong_FromVoidPtr(result);
1911 [ - + ]: 2 : if (key == NULL) {
1912 : 0 : Py_DECREF(result);
1913 : 0 : return NULL;
1914 : : }
1915 [ + - ]: 705 : } else if (PyType_Check(cls)) {
1916 : 705 : typ = (PyTypeObject *)cls;
1917 : 705 : buf = PyMem_Malloc(strlen(typ->tp_name) + 3 + 1);
1918 [ - + ]: 705 : if (buf == NULL)
1919 : : return PyErr_NoMemory();
1920 : 705 : sprintf(buf, "LP_%s", typ->tp_name);
1921 : 705 : result = PyObject_CallFunction((PyObject *)Py_TYPE(&PyCPointer_Type),
1922 : : "s(O){sO}",
1923 : : buf,
1924 : : &PyCPointer_Type,
1925 : : "_type_", cls);
1926 : 705 : PyMem_Free(buf);
1927 [ - + ]: 705 : if (result == NULL)
1928 : 0 : return result;
1929 : 705 : Py_INCREF(cls);
1930 : 705 : key = cls;
1931 : : } else {
1932 : 0 : PyErr_SetString(PyExc_TypeError, "must be a ctypes type");
1933 : 0 : return NULL;
1934 : : }
1935 [ - + ]: 707 : if (-1 == PyDict_SetItem(_ctypes_ptrtype_cache, key, result)) {
1936 : 0 : Py_DECREF(result);
1937 : 0 : Py_DECREF(key);
1938 : 0 : return NULL;
1939 : : }
1940 : 707 : Py_DECREF(key);
1941 : 707 : return result;
1942 : : }
1943 : :
1944 : : static PyObject *
1945 : 68 : pointer(PyObject *self, PyObject *arg)
1946 : : {
1947 : : PyObject *result;
1948 : : PyObject *typ;
1949 : :
1950 : 68 : typ = PyDict_GetItemWithError(_ctypes_ptrtype_cache, (PyObject *)Py_TYPE(arg));
1951 [ + + ]: 68 : if (typ) {
1952 : 63 : return PyObject_CallOneArg(typ, arg);
1953 : : }
1954 [ - + ]: 5 : else if (PyErr_Occurred()) {
1955 : 0 : return NULL;
1956 : : }
1957 : 5 : typ = POINTER(NULL, (PyObject *)Py_TYPE(arg));
1958 [ - + ]: 5 : if (typ == NULL)
1959 : 0 : return NULL;
1960 : 5 : result = PyObject_CallOneArg(typ, arg);
1961 : 5 : Py_DECREF(typ);
1962 : 5 : return result;
1963 : : }
1964 : :
1965 : : static PyObject *
1966 : 0 : buffer_info(PyObject *self, PyObject *arg)
1967 : : {
1968 : 0 : StgDictObject *dict = PyType_stgdict(arg);
1969 : : PyObject *shape;
1970 : : Py_ssize_t i;
1971 : :
1972 [ # # ]: 0 : if (dict == NULL)
1973 : 0 : dict = PyObject_stgdict(arg);
1974 [ # # ]: 0 : if (dict == NULL) {
1975 : 0 : PyErr_SetString(PyExc_TypeError,
1976 : : "not a ctypes type or object");
1977 : 0 : return NULL;
1978 : : }
1979 : 0 : shape = PyTuple_New(dict->ndim);
1980 [ # # ]: 0 : if (shape == NULL)
1981 : 0 : return NULL;
1982 [ # # ]: 0 : for (i = 0; i < (int)dict->ndim; ++i)
1983 : 0 : PyTuple_SET_ITEM(shape, i, PyLong_FromSsize_t(dict->shape[i]));
1984 : :
1985 [ # # ]: 0 : if (PyErr_Occurred()) {
1986 : 0 : Py_DECREF(shape);
1987 : 0 : return NULL;
1988 : : }
1989 : 0 : return Py_BuildValue("siN", dict->format, dict->ndim, shape);
1990 : : }
1991 : :
1992 : :
1993 : :
1994 : : PyMethodDef _ctypes_module_methods[] = {
1995 : : {"get_errno", get_errno, METH_NOARGS},
1996 : : {"set_errno", set_errno, METH_VARARGS},
1997 : : {"POINTER", POINTER, METH_O },
1998 : : {"pointer", pointer, METH_O },
1999 : : {"_unpickle", unpickle, METH_VARARGS },
2000 : : {"buffer_info", buffer_info, METH_O, "Return buffer interface information"},
2001 : : {"resize", resize, METH_VARARGS, "Resize the memory buffer of a ctypes instance"},
2002 : : #ifdef MS_WIN32
2003 : : {"get_last_error", get_last_error, METH_NOARGS},
2004 : : {"set_last_error", set_last_error, METH_VARARGS},
2005 : : {"CopyComPointer", copy_com_pointer, METH_VARARGS, copy_com_pointer_doc},
2006 : : {"FormatError", format_error, METH_VARARGS, format_error_doc},
2007 : : {"LoadLibrary", load_library, METH_VARARGS, load_library_doc},
2008 : : {"FreeLibrary", free_library, METH_VARARGS, free_library_doc},
2009 : : {"_check_HRESULT", check_hresult, METH_VARARGS},
2010 : : #else
2011 : : {"dlopen", py_dl_open, METH_VARARGS,
2012 : : "dlopen(name, flag={RTLD_GLOBAL|RTLD_LOCAL}) open a shared library"},
2013 : : {"dlclose", py_dl_close, METH_VARARGS, "dlclose a library"},
2014 : : {"dlsym", py_dl_sym, METH_VARARGS, "find symbol in shared library"},
2015 : : #endif
2016 : : #ifdef __APPLE__
2017 : : {"_dyld_shared_cache_contains_path", py_dyld_shared_cache_contains_path, METH_VARARGS, "check if path is in the shared cache"},
2018 : : #endif
2019 : : {"alignment", align_func, METH_O, alignment_doc},
2020 : : {"sizeof", sizeof_func, METH_O, sizeof_doc},
2021 : : {"byref", byref, METH_VARARGS, byref_doc},
2022 : : {"addressof", addressof, METH_O, addressof_doc},
2023 : : {"call_function", call_function, METH_VARARGS },
2024 : : {"call_cdeclfunction", call_cdeclfunction, METH_VARARGS },
2025 : : {"PyObj_FromPtr", My_PyObj_FromPtr, METH_VARARGS },
2026 : : {"Py_INCREF", My_Py_INCREF, METH_O },
2027 : : {"Py_DECREF", My_Py_DECREF, METH_O },
2028 : : {NULL, NULL} /* Sentinel */
2029 : : };
2030 : :
2031 : : /*
2032 : : Local Variables:
2033 : : compile-command: "cd .. && python setup.py -q build -g && python setup.py -q build install --home ~"
2034 : : End:
2035 : : */
|