From 5fd6751c2b1074bfa8de7f7e874f28193cdef63a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20A=C3=9Fhauer?= Date: Fri, 26 Nov 2021 19:04:09 +0100 Subject: [PATCH] lazyload: use correct calling conventions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Christoph Reiter reported on the Git for Windows issue tracker[1], that mingw_strftime() imports strftime() from ucrtbase.dll with the wrong calling convention. It should be __cdecl instead of WINAPI, which we always use in DECLARE_PROC_ADDR(). The MSYS2 project encountered cmake sefaults on x86 Windows caused by the same issue in the cmake source. [2] There are no known git crashes that where caused by this, yet, but we should try to prevent them. We import two other non-WINAPI functions via DECLARE_PROC_ADDR(), too. * NtSetSystemInformation() (NTAPI) * GetUserNameExW() (SEC_ENTRY) NTAPI, SEC_ENTRY and WINAPI are all ususally defined as __stdcall, but there are circumstances where they're defined differently. Teach DECLARE_PROC_ADDR() about calling conventions and be explicit about when we want to use which calling convention. Import winnt.h for the definition of NTAPI and security.h for SEC_ENTRY near their respective only users. [1] https://github.com/git-for-windows/git/issues/3560 [2] https://github.com/msys2/MINGW-packages/issues/10152 Reported-By: Christoph Reiter Signed-off-by: Matthias Aßhauer --- compat/mingw.c | 5 +++-- compat/win32/lazyload.h | 6 +++--- compat/win32/trace2_win32_process_info.c | 4 ++-- compat/winansi.c | 5 +++-- t/helper/test-drop-caches.c | 4 +++- 5 files changed, 14 insertions(+), 10 deletions(-) diff --git a/compat/mingw.c b/compat/mingw.c index 9e0cd1e097f25f..6f3f56037aac8f 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -8,6 +8,7 @@ #include "win32/lazyload.h" #include "../config.h" #include "dir.h" +#include #define HCAST(type, handle) ((type)(intptr_t)handle) @@ -1008,7 +1009,7 @@ size_t mingw_strftime(char *s, size_t max, /* a pointer to the original strftime in case we can't find the UCRT version */ static size_t (*fallback)(char *, size_t, const char *, const struct tm *) = strftime; size_t ret; - DECLARE_PROC_ADDR(ucrtbase.dll, size_t, strftime, char *, size_t, + DECLARE_PROC_ADDR(ucrtbase.dll, size_t, __cdecl, strftime, char *, size_t, const char *, const struct tm *); if (INIT_PROC_ADDR(strftime)) @@ -2183,7 +2184,7 @@ enum EXTENDED_NAME_FORMAT { static char *get_extended_user_info(enum EXTENDED_NAME_FORMAT type) { - DECLARE_PROC_ADDR(secur32.dll, BOOL, GetUserNameExW, + DECLARE_PROC_ADDR(secur32.dll, BOOL, SEC_ENTRY, GetUserNameExW, enum EXTENDED_NAME_FORMAT, LPCWSTR, PULONG); static wchar_t wbuffer[1024]; DWORD len; diff --git a/compat/win32/lazyload.h b/compat/win32/lazyload.h index 2b3637135f68a3..f2bb96c89c735c 100644 --- a/compat/win32/lazyload.h +++ b/compat/win32/lazyload.h @@ -4,7 +4,7 @@ /* * A pair of macros to simplify loading of DLL functions. Example: * - * DECLARE_PROC_ADDR(kernel32.dll, BOOL, CreateHardLinkW, + * DECLARE_PROC_ADDR(kernel32.dll, BOOL, WINAPI, CreateHardLinkW, * LPCWSTR, LPCWSTR, LPSECURITY_ATTRIBUTES); * * if (!INIT_PROC_ADDR(CreateHardLinkW)) @@ -25,10 +25,10 @@ struct proc_addr { }; /* Declares a function to be loaded dynamically from a DLL. */ -#define DECLARE_PROC_ADDR(dll, rettype, function, ...) \ +#define DECLARE_PROC_ADDR(dll, rettype, convention, function, ...) \ static struct proc_addr proc_addr_##function = \ { #dll, #function, NULL, 0 }; \ - typedef rettype (WINAPI *proc_type_##function)(__VA_ARGS__); \ + typedef rettype (convention *proc_type_##function)(__VA_ARGS__); \ static proc_type_##function function /* diff --git a/compat/win32/trace2_win32_process_info.c b/compat/win32/trace2_win32_process_info.c index 8ccbd1c2c6f82d..a53fd924340f7d 100644 --- a/compat/win32/trace2_win32_process_info.c +++ b/compat/win32/trace2_win32_process_info.c @@ -143,8 +143,8 @@ static void get_is_being_debugged(void) */ static void get_peak_memory_info(void) { - DECLARE_PROC_ADDR(psapi.dll, BOOL, GetProcessMemoryInfo, HANDLE, - PPROCESS_MEMORY_COUNTERS, DWORD); + DECLARE_PROC_ADDR(psapi.dll, BOOL, WINAPI, GetProcessMemoryInfo, + HANDLE, PPROCESS_MEMORY_COUNTERS, DWORD); if (INIT_PROC_ADDR(GetProcessMemoryInfo)) { PROCESS_MEMORY_COUNTERS pmc; diff --git a/compat/winansi.c b/compat/winansi.c index c27b20a79d91cf..7af28b8a212b0f 100644 --- a/compat/winansi.c +++ b/compat/winansi.c @@ -45,8 +45,9 @@ typedef struct _CONSOLE_FONT_INFOEX { static void warn_if_raster_font(void) { DWORD fontFamily = 0; - DECLARE_PROC_ADDR(kernel32.dll, BOOL, GetCurrentConsoleFontEx, - HANDLE, BOOL, PCONSOLE_FONT_INFOEX); + DECLARE_PROC_ADDR(kernel32.dll, BOOL, WINAPI, + GetCurrentConsoleFontEx, HANDLE, BOOL, + PCONSOLE_FONT_INFOEX); /* don't bother if output was ascii only */ if (!non_ascii_used) diff --git a/t/helper/test-drop-caches.c b/t/helper/test-drop-caches.c index 7b4278462bb716..0ddf2cc0ecc720 100644 --- a/t/helper/test-drop-caches.c +++ b/t/helper/test-drop-caches.c @@ -3,6 +3,7 @@ #if defined(GIT_WINDOWS_NATIVE) #include "lazyload.h" +#include static int cmd_sync(void) { @@ -86,7 +87,8 @@ static int cmd_dropcaches(void) { HANDLE hProcess = GetCurrentProcess(); HANDLE hToken; - DECLARE_PROC_ADDR(ntdll.dll, DWORD, NtSetSystemInformation, INT, PVOID, ULONG); + DECLARE_PROC_ADDR(ntdll.dll, DWORD, NTAPI, NtSetSystemInformation, INT, PVOID, + ULONG); SYSTEM_MEMORY_LIST_COMMAND command; int status;