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