Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-11-19 09:50:45

0001 #ifndef Py_EMSCRIPTEN_TRAMPOLINE_H
0002 #define Py_EMSCRIPTEN_TRAMPOLINE_H
0003 
0004 #include "pycore_runtime.h"  // _PyRuntimeState
0005 
0006 /**
0007  * C function call trampolines to mitigate bad function pointer casts.
0008  *
0009  * Section 6.3.2.3, paragraph 8 reads:
0010  *
0011  *      A pointer to a function of one type may be converted to a pointer to a
0012  *      function of another type and back again; the result shall compare equal to
0013  *      the original pointer. If a converted pointer is used to call a function
0014  *      whose type is not compatible with the pointed-to type, the behavior is
0015  *      undefined.
0016  *
0017  * Typical native ABIs ignore additional arguments or fill in missing values
0018  * with 0/NULL in function pointer cast. Compilers do not show warnings when a
0019  * function pointer is explicitly casted to an incompatible type.
0020  *
0021  * Bad fpcasts are an issue in WebAssembly. WASM's indirect_call has strict
0022  * function signature checks. Argument count, types, and return type must match.
0023  *
0024  * Third party code unintentionally rely on problematic fpcasts. The call
0025  * trampoline mitigates common occurrences of bad fpcasts on Emscripten.
0026  */
0027 
0028 #if defined(__EMSCRIPTEN__) && defined(PY_CALL_TRAMPOLINE)
0029 
0030 void _Py_EmscriptenTrampoline_Init(_PyRuntimeState *runtime);
0031 
0032 PyObject*
0033 _PyEM_TrampolineCall_JavaScript(PyCFunctionWithKeywords func,
0034                                 PyObject* self,
0035                                 PyObject* args,
0036                                 PyObject* kw);
0037 
0038 PyObject*
0039 _PyEM_TrampolineCall_Reflection(PyCFunctionWithKeywords func,
0040                                 PyObject* self,
0041                                 PyObject* args,
0042                                 PyObject* kw);
0043 
0044 #define _PyEM_TrampolineCall(meth, self, args, kw) \
0045     ((_PyRuntime.wasm_type_reflection_available) ? \
0046         (_PyEM_TrampolineCall_Reflection((PyCFunctionWithKeywords)(meth), (self), (args), (kw))) : \
0047         (_PyEM_TrampolineCall_JavaScript((PyCFunctionWithKeywords)(meth), (self), (args), (kw))))
0048 
0049 #define _PyCFunction_TrampolineCall(meth, self, args) \
0050     _PyEM_TrampolineCall( \
0051         (*(PyCFunctionWithKeywords)(void(*)(void))(meth)), (self), (args), NULL)
0052 
0053 #define _PyCFunctionWithKeywords_TrampolineCall(meth, self, args, kw) \
0054     _PyEM_TrampolineCall((meth), (self), (args), (kw))
0055 
0056 #define descr_set_trampoline_call(set, obj, value, closure) \
0057     ((int)_PyEM_TrampolineCall((PyCFunctionWithKeywords)(set), (obj), (value), (PyObject*)(closure)))
0058 
0059 #define descr_get_trampoline_call(get, obj, closure) \
0060     _PyEM_TrampolineCall((PyCFunctionWithKeywords)(get), (obj), (PyObject*)(closure), NULL)
0061 
0062 
0063 #else // defined(__EMSCRIPTEN__) && defined(PY_CALL_TRAMPOLINE)
0064 
0065 #define _Py_EmscriptenTrampoline_Init(runtime)
0066 
0067 #define _PyCFunction_TrampolineCall(meth, self, args) \
0068     (meth)((self), (args))
0069 
0070 #define _PyCFunctionWithKeywords_TrampolineCall(meth, self, args, kw) \
0071     (meth)((self), (args), (kw))
0072 
0073 #define descr_set_trampoline_call(set, obj, value, closure) \
0074     (set)((obj), (value), (closure))
0075 
0076 #define descr_get_trampoline_call(get, obj, closure) \
0077     (get)((obj), (closure))
0078 
0079 #endif // defined(__EMSCRIPTEN__) && defined(PY_CALL_TRAMPOLINE)
0080 
0081 #endif // ndef Py_EMSCRIPTEN_SIGNAL_H