• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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