* GH-115322: fix ctypes call_function audit hook on 32-bit platforms.
It was using a signed conversion to communicate the function id (pointer) value.
with TestHook() as hook:
_ctypes.call_function(ctypes._memmove_addr, (0, 0, 0))
- assert ("ctypes.call_function", (ctypes._memmove_addr, (0, 0, 0))) in hook.seen
+ assert ("ctypes.call_function", (ctypes._memmove_addr, (0, 0, 0))) in hook.seen, f"{ctypes._memmove_addr=} {hook.seen=}"
ctypes.CFUNCTYPE(ctypes.c_voidp)(ctypes._memset_addr)(1, 0, 0)
- assert ("ctypes.call_function", (ctypes._memset_addr, (1, 0, 0))) in hook.seen
+ assert ("ctypes.call_function", (ctypes._memset_addr, (1, 0, 0))) in hook.seen, f"{ctypes._memset_addr=} {hook.seen=}"
with TestHook() as hook:
ctypes.cast(ctypes.c_voidp(0), ctypes.POINTER(ctypes.c_char))
The underlying extension modules behind :mod:`readline`:, :mod:`subprocess`,
and :mod:`ctypes` now raise audit events on previously uncovered code paths
that could lead to file system access related to C function calling and
-external binary execution.
+external binary execution. The ``ctypes.call_function`` audit hook has also
+been fixed to use an unsigned value for its ``function pointer``.
PyObject *retval = NULL;
// Both call_function and call_cdeclfunction call us:
+#if SIZEOF_VOID_P == SIZEOF_LONG
+ if (PySys_Audit("ctypes.call_function", "kO",
+ (unsigned long)pProc, argtuple) < 0) {
+#elif SIZEOF_VOID_P == SIZEOF_LONG_LONG
+ if (PySys_Audit("ctypes.call_function", "KO",
+ (unsigned long long)pProc, argtuple) < 0) {
+#else
+# warning "unexpected pointer size, you may see odd values in audit hooks"
if (PySys_Audit("ctypes.call_function", "nO",
(Py_ssize_t)pProc, argtuple) < 0) {
+#endif
return NULL;
}