1 #ifndef Py_BUILD_CORE_BUILTIN
2 # define Py_BUILD_CORE_MODULE 1
3 #endif
4
5 #include "Python.h"
6 // windows.h must be included before pycore internal headers
7 #ifdef MS_WIN32
8 # include <windows.h>
9 #endif
10
11 #include "pycore_call.h" // _PyObject_CallNoArgs()
12 #include "pycore_runtime.h" // _Py_ID()
13
14 #include <stdbool.h>
15
16 #ifdef MS_WIN32
17 # include <malloc.h>
18 #endif
19
20 #include <ffi.h>
21 #include "ctypes.h"
22
23 #ifdef HAVE_ALLOCA_H
24 /* AIX needs alloca.h for alloca() */
25 #include <alloca.h>
26 #endif
27
28 /**************************************************************/
29
30 static int
CThunkObject_traverse(PyObject * myself,visitproc visit,void * arg)31 CThunkObject_traverse(PyObject *myself, visitproc visit, void *arg)
32 {
33 CThunkObject *self = (CThunkObject *)myself;
34 Py_VISIT(Py_TYPE(self));
35 Py_VISIT(self->converters);
36 Py_VISIT(self->callable);
37 Py_VISIT(self->restype);
38 return 0;
39 }
40
41 static int
CThunkObject_clear(PyObject * myself)42 CThunkObject_clear(PyObject *myself)
43 {
44 CThunkObject *self = (CThunkObject *)myself;
45 Py_CLEAR(self->converters);
46 Py_CLEAR(self->callable);
47 Py_CLEAR(self->restype);
48 return 0;
49 }
50
51 static void
CThunkObject_dealloc(PyObject * myself)52 CThunkObject_dealloc(PyObject *myself)
53 {
54 CThunkObject *self = (CThunkObject *)myself;
55 PyTypeObject *tp = Py_TYPE(myself);
56 PyObject_GC_UnTrack(self);
57 (void)CThunkObject_clear(myself);
58 if (self->pcl_write) {
59 Py_ffi_closure_free(self->pcl_write);
60 }
61 PyObject_GC_Del(self);
62 Py_DECREF(tp);
63 }
64
65 static PyType_Slot cthunk_slots[] = {
66 {Py_tp_doc, (void *)PyDoc_STR("CThunkObject")},
67 {Py_tp_dealloc, CThunkObject_dealloc},
68 {Py_tp_traverse, CThunkObject_traverse},
69 {Py_tp_clear, CThunkObject_clear},
70 {0, NULL},
71 };
72
73 PyType_Spec cthunk_spec = {
74 .name = "_ctypes.CThunkObject",
75 .basicsize = sizeof(CThunkObject),
76 .itemsize = sizeof(ffi_type),
77 .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
78 Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_DISALLOW_INSTANTIATION),
79 .slots = cthunk_slots,
80 };
81
82 /**************************************************************/
83
84 static void
PrintError(const char * msg,...)85 PrintError(const char *msg, ...)
86 {
87 char buf[512];
88 PyObject *f = PySys_GetObject("stderr");
89 va_list marker;
90
91 va_start(marker, msg);
92 PyOS_vsnprintf(buf, sizeof(buf), msg, marker);
93 va_end(marker);
94 if (f != NULL && f != Py_None)
95 PyFile_WriteString(buf, f);
96 PyErr_Print();
97 }
98
99
100 #ifdef MS_WIN32
101 /*
102 * We must call AddRef() on non-NULL COM pointers we receive as arguments
103 * to callback functions - these functions are COM method implementations.
104 * The Python instances we create have a __del__ method which calls Release().
105 *
106 * The presence of a class attribute named '_needs_com_addref_' triggers this
107 * behaviour. It would also be possible to call the AddRef() Python method,
108 * after checking for PyObject_IsTrue(), but this would probably be somewhat
109 * slower.
110 */
111 static void
TryAddRef(PyObject * cnv,CDataObject * obj)112 TryAddRef(PyObject *cnv, CDataObject *obj)
113 {
114 IUnknown *punk;
115 PyObject *attrdict = _PyType_GetDict((PyTypeObject *)cnv);
116 if (!attrdict) {
117 return;
118 }
119 int r = PyDict_Contains(attrdict, &_Py_ID(_needs_com_addref_));
120 if (r <= 0) {
121 if (r < 0) {
122 PrintError("getting _needs_com_addref_");
123 }
124 return;
125 }
126
127 punk = *(IUnknown **)obj->b_ptr;
128 if (punk)
129 punk->lpVtbl->AddRef(punk);
130 return;
131 }
132 #endif
133
134 /******************************************************************************
135 *
136 * Call the python object with all arguments
137 *
138 */
139
140 // BEWARE: The GIL needs to be held throughout the function
_CallPythonObject(ctypes_state * st,void * mem,ffi_type * restype,SETFUNC setfunc,PyObject * callable,PyObject * converters,int flags,void ** pArgs)141 static void _CallPythonObject(ctypes_state *st,
142 void *mem,
143 ffi_type *restype,
144 SETFUNC setfunc,
145 PyObject *callable,
146 PyObject *converters,
147 int flags,
148 void **pArgs)
149 {
150 PyObject *result = NULL;
151 Py_ssize_t i = 0, j = 0, nargs = 0;
152 PyObject *error_object = NULL;
153 int *space;
154
155 assert(PyTuple_Check(converters));
156 nargs = PyTuple_GET_SIZE(converters);
157 assert(nargs <= CTYPES_MAX_ARGCOUNT);
158 PyObject **args = alloca(nargs * sizeof(PyObject *));
159 PyObject **cnvs = PySequence_Fast_ITEMS(converters);
160 for (i = 0; i < nargs; i++) {
161 PyObject *cnv = cnvs[i]; // borrowed ref
162
163 StgInfo *info;
164 if (PyStgInfo_FromType(st, cnv, &info) < 0) {
165 goto Done;
166 }
167
168 if (info && info->getfunc && !_ctypes_simple_instance(st, cnv)) {
169 PyObject *v = info->getfunc(*pArgs, info->size);
170 if (!v) {
171 PrintError("create argument %zd:\n", i);
172 goto Done;
173 }
174 args[i] = v;
175 /* XXX XXX XX
176 We have the problem that c_byte or c_short have info->size of
177 1 resp. 4, but these parameters are pushed as sizeof(int) bytes.
178 BTW, the same problem occurs when they are pushed as parameters
179 */
180 }
181 else if (info) {
182 /* Hm, shouldn't we use PyCData_AtAddress() or something like that instead? */
183 CDataObject *obj = (CDataObject *)_PyObject_CallNoArgs(cnv);
184 if (!obj) {
185 PrintError("create argument %zd:\n", i);
186 goto Done;
187 }
188 if (!CDataObject_Check(st, obj)) {
189 Py_DECREF(obj);
190 PrintError("unexpected result of create argument %zd:\n", i);
191 goto Done;
192 }
193 memcpy(obj->b_ptr, *pArgs, info->size);
194 args[i] = (PyObject *)obj;
195 #ifdef MS_WIN32
196 TryAddRef(cnv, obj);
197 #endif
198 } else {
199 PyErr_SetString(PyExc_TypeError,
200 "cannot build parameter");
201 PrintError("Parsing argument %zd\n", i);
202 goto Done;
203 }
204 /* XXX error handling! */
205 pArgs++;
206 }
207
208 if (flags & (FUNCFLAG_USE_ERRNO | FUNCFLAG_USE_LASTERROR)) {
209 error_object = _ctypes_get_errobj(st, &space);
210 if (error_object == NULL)
211 goto Done;
212 if (flags & FUNCFLAG_USE_ERRNO) {
213 int temp = space[0];
214 space[0] = errno;
215 errno = temp;
216 }
217 #ifdef MS_WIN32
218 if (flags & FUNCFLAG_USE_LASTERROR) {
219 int temp = space[1];
220 space[1] = GetLastError();
221 SetLastError(temp);
222 }
223 #endif
224 }
225
226 result = PyObject_Vectorcall(callable, args, nargs, NULL);
227 if (result == NULL) {
228 PyErr_FormatUnraisable(
229 "Exception ignored on calling ctypes callback function %R",
230 callable);
231 }
232
233 #ifdef MS_WIN32
234 if (flags & FUNCFLAG_USE_LASTERROR) {
235 int temp = space[1];
236 space[1] = GetLastError();
237 SetLastError(temp);
238 }
239 #endif
240 if (flags & FUNCFLAG_USE_ERRNO) {
241 int temp = space[0];
242 space[0] = errno;
243 errno = temp;
244 }
245 Py_XDECREF(error_object);
246
247 if (restype != &ffi_type_void && result) {
248 assert(setfunc);
249
250 #ifdef WORDS_BIGENDIAN
251 /* See the corresponding code in _ctypes_callproc():
252 in callproc.c, around line 1219. */
253 if (restype->type != FFI_TYPE_FLOAT && restype->size < sizeof(ffi_arg)) {
254 mem = (char *)mem + sizeof(ffi_arg) - restype->size;
255 }
256 #endif
257
258 /* keep is an object we have to keep alive so that the result
259 stays valid. If there is no such object, the setfunc will
260 have returned Py_None.
261
262 If there is such an object, we have no choice than to keep
263 it alive forever - but a refcount and/or memory leak will
264 be the result. EXCEPT when restype is py_object - Python
265 itself knows how to manage the refcount of these objects.
266 */
267 PyObject *keep = setfunc(mem, result, 0);
268
269 if (keep == NULL) {
270 /* Could not convert callback result. */
271 PyErr_FormatUnraisable(
272 "Exception ignored on converting result "
273 "of ctypes callback function %R",
274 callable);
275 }
276 else if (setfunc != _ctypes_get_fielddesc("O")->setfunc) {
277 if (keep == Py_None) {
278 /* Nothing to keep */
279 Py_DECREF(keep);
280 }
281 else if (PyErr_WarnEx(PyExc_RuntimeWarning,
282 "memory leak in callback function.",
283 1) == -1) {
284 PyErr_FormatUnraisable(
285 "Exception ignored on converting result "
286 "of ctypes callback function %R",
287 callable);
288 }
289 }
290 }
291
292 Py_XDECREF(result);
293
294 Done:
295 for (j = 0; j < i; j++) {
296 Py_DECREF(args[j]);
297 }
298 }
299
closure_fcn(ffi_cif * cif,void * resp,void ** args,void * userdata)300 static void closure_fcn(ffi_cif *cif,
301 void *resp,
302 void **args,
303 void *userdata)
304 {
305 PyGILState_STATE state = PyGILState_Ensure();
306
307 CThunkObject *p = (CThunkObject *)userdata;
308 ctypes_state *st = get_module_state_by_class(Py_TYPE(p));
309
310 _CallPythonObject(st,
311 resp,
312 p->ffi_restype,
313 p->setfunc,
314 p->callable,
315 p->converters,
316 p->flags,
317 args);
318
319 PyGILState_Release(state);
320 }
321
CThunkObject_new(ctypes_state * st,Py_ssize_t nargs)322 static CThunkObject* CThunkObject_new(ctypes_state *st, Py_ssize_t nargs)
323 {
324 CThunkObject *p;
325 Py_ssize_t i;
326
327 p = PyObject_GC_NewVar(CThunkObject, st->PyCThunk_Type, nargs);
328 if (p == NULL) {
329 return NULL;
330 }
331
332 p->pcl_write = NULL;
333 p->pcl_exec = NULL;
334 memset(&p->cif, 0, sizeof(p->cif));
335 p->flags = 0;
336 p->converters = NULL;
337 p->callable = NULL;
338 p->restype = NULL;
339 p->setfunc = NULL;
340 p->ffi_restype = NULL;
341
342 for (i = 0; i < nargs + 1; ++i)
343 p->atypes[i] = NULL;
344 PyObject_GC_Track((PyObject *)p);
345 return p;
346 }
347
_ctypes_alloc_callback(ctypes_state * st,PyObject * callable,PyObject * converters,PyObject * restype,int flags)348 CThunkObject *_ctypes_alloc_callback(ctypes_state *st,
349 PyObject *callable,
350 PyObject *converters,
351 PyObject *restype,
352 int flags)
353 {
354 int result;
355 CThunkObject *p;
356 Py_ssize_t nargs, i;
357 ffi_abi cc;
358
359 assert(PyTuple_Check(converters));
360 nargs = PyTuple_GET_SIZE(converters);
361 p = CThunkObject_new(st, nargs);
362 if (p == NULL)
363 return NULL;
364
365 assert(CThunk_CheckExact(st, (PyObject *)p));
366
367 p->pcl_write = Py_ffi_closure_alloc(sizeof(ffi_closure), &p->pcl_exec);
368 if (p->pcl_write == NULL) {
369 PyErr_NoMemory();
370 goto error;
371 }
372
373 p->flags = flags;
374 PyObject **cnvs = PySequence_Fast_ITEMS(converters);
375 for (i = 0; i < nargs; ++i) {
376 PyObject *cnv = cnvs[i]; // borrowed ref
377 p->atypes[i] = _ctypes_get_ffi_type(st, cnv);
378 }
379 p->atypes[i] = NULL;
380
381 p->restype = Py_NewRef(restype);
382 if (restype == Py_None) {
383 p->setfunc = NULL;
384 p->ffi_restype = &ffi_type_void;
385 } else {
386 StgInfo *info;
387 if (PyStgInfo_FromType(st, restype, &info) < 0) {
388 goto error;
389 }
390
391 if (info == NULL || info->setfunc == NULL) {
392 PyErr_SetString(PyExc_TypeError,
393 "invalid result type for callback function");
394 goto error;
395 }
396 p->setfunc = info->setfunc;
397 p->ffi_restype = &info->ffi_type_pointer;
398 }
399
400 cc = FFI_DEFAULT_ABI;
401 #if defined(MS_WIN32) && !defined(_WIN32_WCE) && !defined(MS_WIN64) && !defined(_M_ARM)
402 if ((flags & FUNCFLAG_CDECL) == 0)
403 cc = FFI_STDCALL;
404 #endif
405 result = ffi_prep_cif(&p->cif, cc,
406 Py_SAFE_DOWNCAST(nargs, Py_ssize_t, int),
407 p->ffi_restype,
408 &p->atypes[0]);
409 if (result != FFI_OK) {
410 PyErr_Format(PyExc_RuntimeError,
411 "ffi_prep_cif failed with %d", result);
412 goto error;
413 }
414
415
416 #if HAVE_FFI_PREP_CLOSURE_LOC
417 # ifdef USING_APPLE_OS_LIBFFI
418 # ifdef HAVE_BUILTIN_AVAILABLE
419 # define HAVE_FFI_PREP_CLOSURE_LOC_RUNTIME __builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *)
420 # else
421 # define HAVE_FFI_PREP_CLOSURE_LOC_RUNTIME (ffi_prep_closure_loc != NULL)
422 # endif
423 # else
424 # define HAVE_FFI_PREP_CLOSURE_LOC_RUNTIME 1
425 # endif
426 if (HAVE_FFI_PREP_CLOSURE_LOC_RUNTIME) {
427 result = ffi_prep_closure_loc(p->pcl_write, &p->cif, closure_fcn,
428 p,
429 p->pcl_exec);
430 } else
431 #endif
432 {
433 #if defined(USING_APPLE_OS_LIBFFI) && defined(__arm64__)
434 PyErr_Format(PyExc_NotImplementedError, "ffi_prep_closure_loc() is missing");
435 goto error;
436 #else
437 // GH-85272, GH-23327, GH-100540: On macOS,
438 // HAVE_FFI_PREP_CLOSURE_LOC_RUNTIME is checked at runtime because the
439 // symbol might not be available at runtime when targeting macOS 10.14
440 // or earlier. Even if ffi_prep_closure_loc() is called in practice,
441 // the deprecated ffi_prep_closure() code path is needed if
442 // HAVE_FFI_PREP_CLOSURE_LOC_RUNTIME is false.
443 //
444 // On non-macOS platforms, even if HAVE_FFI_PREP_CLOSURE_LOC_RUNTIME is
445 // defined as 1 and ffi_prep_closure_loc() is used in practice, this
446 // code path is still compiled and emits a compiler warning. The
447 // deprecated code path is likely to be removed by a simple
448 // optimization pass.
449 //
450 // Ignore the compiler warning on the ffi_prep_closure() deprecation,
451 // rather than using complex #if/#else code paths for the different
452 // platforms.
453 _Py_COMP_DIAG_PUSH
454 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
455 result = ffi_prep_closure(p->pcl_write, &p->cif, closure_fcn, p);
456 _Py_COMP_DIAG_POP
457 #endif
458 }
459
460 if (result != FFI_OK) {
461 PyErr_Format(PyExc_RuntimeError,
462 "ffi_prep_closure failed with %d", result);
463 goto error;
464 }
465
466 p->converters = Py_NewRef(converters);
467 p->callable = Py_NewRef(callable);
468 return p;
469
470 error:
471 Py_XDECREF(p);
472 return NULL;
473 }
474
475 #ifdef MS_WIN32
476
LoadPython(void)477 static void LoadPython(void)
478 {
479 if (!Py_IsInitialized()) {
480 Py_Initialize();
481 }
482 }
483
484 /******************************************************************/
485
Call_GetClassObject(REFCLSID rclsid,REFIID riid,LPVOID * ppv)486 long Call_GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
487 {
488 PyObject *func, *result;
489 long retval;
490 static PyObject *context;
491
492 if (context == NULL)
493 context = PyUnicode_InternFromString("_ctypes.DllGetClassObject");
494
495 func = _PyImport_GetModuleAttrString("ctypes", "DllGetClassObject");
496 if (!func) {
497 PyErr_WriteUnraisable(context ? context : Py_None);
498 /* There has been a warning before about this already */
499 return E_FAIL;
500 }
501
502 {
503 PyObject *py_rclsid = PyLong_FromVoidPtr((void *)rclsid);
504 if (py_rclsid == NULL) {
505 Py_DECREF(func);
506 PyErr_WriteUnraisable(context ? context : Py_None);
507 return E_FAIL;
508 }
509 PyObject *py_riid = PyLong_FromVoidPtr((void *)riid);
510 if (py_riid == NULL) {
511 Py_DECREF(func);
512 Py_DECREF(py_rclsid);
513 PyErr_WriteUnraisable(context ? context : Py_None);
514 return E_FAIL;
515 }
516 PyObject *py_ppv = PyLong_FromVoidPtr(ppv);
517 if (py_ppv == NULL) {
518 Py_DECREF(py_rclsid);
519 Py_DECREF(py_riid);
520 Py_DECREF(func);
521 PyErr_WriteUnraisable(context ? context : Py_None);
522 return E_FAIL;
523 }
524 result = PyObject_CallFunctionObjArgs(func,
525 py_rclsid,
526 py_riid,
527 py_ppv,
528 NULL);
529 Py_DECREF(py_rclsid);
530 Py_DECREF(py_riid);
531 Py_DECREF(py_ppv);
532 }
533 Py_DECREF(func);
534 if (!result) {
535 PyErr_WriteUnraisable(context ? context : Py_None);
536 return E_FAIL;
537 }
538
539 retval = PyLong_AsLong(result);
540 if (PyErr_Occurred()) {
541 PyErr_WriteUnraisable(context ? context : Py_None);
542 retval = E_FAIL;
543 }
544 Py_DECREF(result);
545 return retval;
546 }
547
DllGetClassObject(REFCLSID rclsid,REFIID riid,LPVOID * ppv)548 STDAPI DllGetClassObject(REFCLSID rclsid,
549 REFIID riid,
550 LPVOID *ppv)
551 {
552 long result;
553 PyGILState_STATE state;
554
555 LoadPython();
556 state = PyGILState_Ensure();
557 result = Call_GetClassObject(rclsid, riid, ppv);
558 PyGILState_Release(state);
559 return result;
560 }
561
Call_CanUnloadNow(void)562 long Call_CanUnloadNow(void)
563 {
564 PyObject *mod, *func, *result;
565 long retval;
566 static PyObject *context;
567
568 if (context == NULL)
569 context = PyUnicode_InternFromString("_ctypes.DllCanUnloadNow");
570
571 mod = PyImport_ImportModule("ctypes");
572 if (!mod) {
573 /* OutputDebugString("Could not import ctypes"); */
574 /* We assume that this error can only occur when shutting
575 down, so we silently ignore it */
576 PyErr_Clear();
577 return E_FAIL;
578 }
579 /* Other errors cannot be raised, but are printed to stderr */
580 func = PyObject_GetAttrString(mod, "DllCanUnloadNow");
581 Py_DECREF(mod);
582 if (!func) {
583 PyErr_WriteUnraisable(context ? context : Py_None);
584 return E_FAIL;
585 }
586
587 result = _PyObject_CallNoArgs(func);
588 Py_DECREF(func);
589 if (!result) {
590 PyErr_WriteUnraisable(context ? context : Py_None);
591 return E_FAIL;
592 }
593
594 retval = PyLong_AsLong(result);
595 if (PyErr_Occurred()) {
596 PyErr_WriteUnraisable(context ? context : Py_None);
597 retval = E_FAIL;
598 }
599 Py_DECREF(result);
600 return retval;
601 }
602
603 /*
604 DllRegisterServer and DllUnregisterServer still missing
605 */
606
DllCanUnloadNow(void)607 STDAPI DllCanUnloadNow(void)
608 {
609 long result;
610 PyGILState_STATE state = PyGILState_Ensure();
611 result = Call_CanUnloadNow();
612 PyGILState_Release(state);
613 return result;
614 }
615
616 #ifndef Py_NO_ENABLE_SHARED
DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvRes)617 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvRes)
618 {
619 switch(fdwReason) {
620 case DLL_PROCESS_ATTACH:
621 DisableThreadLibraryCalls(hinstDLL);
622 break;
623 }
624 return TRUE;
625 }
626 #endif
627
628 #endif
629
630 /*
631 Local Variables:
632 compile-command: "cd .. && python setup.py -q build_ext"
633 End:
634 */
635