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