diff --git a/patches/node/.patches b/patches/node/.patches index f9f78a077fc..419e5545a40 100644 --- a/patches/node/.patches +++ b/patches/node/.patches @@ -26,3 +26,4 @@ chore_fix_-wimplicit-fallthrough.patch fix_event_with_invalid_timestamp_in_trace_log.patch test_fix_test-datetime-change-notify_after_daylight_change.patch test_add_fixture_trim_option.patch +fix_crash_caused_by_gethostnamew_on_windows_7.patch diff --git a/patches/node/fix_crash_caused_by_gethostnamew_on_windows_7.patch b/patches/node/fix_crash_caused_by_gethostnamew_on_windows_7.patch new file mode 100644 index 00000000000..eb24c26a805 --- /dev/null +++ b/patches/node/fix_crash_caused_by_gethostnamew_on_windows_7.patch @@ -0,0 +1,234 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cheng Zhao +Date: Fri, 12 Nov 2021 17:25:37 +0900 +Subject: fix: crash caused by GetHostNameW on Windows 7 + +Backported from https://github.com/libuv/libuv/pull/3285. + +diff --git a/deps/uv/src/win/util.c b/deps/uv/src/win/util.c +index 88602c7ee8623f16f87398cf3ffd1f71555fc1a0..5ffde08e1aed041c4da679156ed10f7e54bfc386 100644 +--- a/deps/uv/src/win/util.c ++++ b/deps/uv/src/win/util.c +@@ -37,6 +37,7 @@ + #include + #include + #include ++#include + /* clang-format on */ + #include + #include +@@ -56,6 +57,10 @@ + /* The number of nanoseconds in one second. */ + #define UV__NANOSEC 1000000000 + ++/* Local buffer size for WSAQUERYSETW data inside uv__gethostnamew_nt60 ++ sizeof(WSAQUERYSETW) + 512 = 632 bytes to match GetHostNameW behavior */ ++#define WSAQ_LOCAL_BUF_LEN (sizeof(WSAQUERYSETW) + 512) ++ + /* Max user name length, from iphlpapi.h */ + #ifndef UNLEN + # define UNLEN 256 +@@ -72,6 +77,11 @@ static CRITICAL_SECTION process_title_lock; + /* Frequency of the high-resolution clock. */ + static uint64_t hrtime_frequency_ = 0; + ++/* Parameters for WSAQUERYSETW inside uv__gethostnamew_nt60 */ ++static GUID guid_host_name = SVCID_HOSTNAME; ++static AFPROTOCOLS af_protocols[2] = { {AF_INET, IPPROTO_UDP}, ++ {AF_INET, IPPROTO_TCP} }; ++ + + /* + * One-time initialization code for functionality defined in util.c. +@@ -1663,6 +1673,125 @@ int uv_os_unsetenv(const char* name) { + } + + ++static int WSAAPI uv__gethostnamew_nt60(PWSTR name, int name_len) { ++ int result_len; ++ int error_code = NO_ERROR; ++ ++ /* WSALookupService stuff ++ * Avoid dynamic memory allocation if possible */ ++ CHAR local_buf[WSAQ_LOCAL_BUF_LEN]; ++ DWORD dwlen = WSAQ_LOCAL_BUF_LEN; ++ WSAQUERYSETW* pwsaq; ++ /* hostname returned from WSALookupService stage */ ++ WCHAR* result_name = NULL; ++ /* WSALookupService handle */ ++ HANDLE hlookup; ++ /* Fallback to heap allocation if stack buffer is too small */ ++ WSAQUERYSETW* heap_data = NULL; ++ ++ /* check input */ ++ if (name == NULL) { ++ error_code = WSAEFAULT; ++ goto cleanup; ++ } ++ ++ /* ++ * Stage 1: Check environment variable ++ * _CLUSTER_NETWORK_NAME_ len == ComputeName(NETBIOS) len. ++ * i.e 15 characters + null. ++ * It overrides the actual hostname, so application can ++ * work when network name and computer name are different ++ */ ++ result_len = GetEnvironmentVariableW(L"_CLUSTER_NETWORK_NAME_", ++ name, ++ name_len); ++ if (result_len != 0) { ++ if (result_len > name_len) { ++ error_code = WSAEFAULT; ++ } ++ goto cleanup; ++ } ++ ++ /* Stage 2: Do normal lookup through WSALookupServiceLookup */ ++ pwsaq = (WSAQUERYSETW*) local_buf; ++ memset(pwsaq, 0, sizeof(*pwsaq)); ++ pwsaq->dwSize = sizeof(*pwsaq); ++ pwsaq->lpszServiceInstanceName = NULL; ++ pwsaq->lpServiceClassId = &guid_host_name; ++ pwsaq->dwNameSpace = NS_ALL; ++ pwsaq->lpafpProtocols = &af_protocols[0]; ++ pwsaq->dwNumberOfProtocols = 2; ++ ++ error_code = WSALookupServiceBeginW(pwsaq, LUP_RETURN_NAME, &hlookup); ++ if (error_code == NO_ERROR) { ++ /* Try stack allocation first */ ++ error_code = WSALookupServiceNextW(hlookup, 0, &dwlen, pwsaq); ++ if (error_code == NO_ERROR) { ++ result_name = pwsaq->lpszServiceInstanceName; ++ } else { ++ error_code = WSAGetLastError(); ++ ++ if (error_code == WSAEFAULT) { ++ /* Should never happen */ ++ assert(sizeof(CHAR) * dwlen >= sizeof(WSAQUERYSETW)); ++ ++ /* Fallback to the heap allocation */ ++ heap_data = uv__malloc(sizeof(CHAR) * (size_t) dwlen); ++ if (heap_data != NULL) { ++ error_code = WSALookupServiceNextW(hlookup, 0, &dwlen, heap_data); ++ if (error_code == NO_ERROR) { ++ result_name = heap_data->lpszServiceInstanceName; ++ } else { ++ error_code = WSAGetLastError(); ++ } ++ } else { ++ error_code = WSA_NOT_ENOUGH_MEMORY; ++ } ++ } ++ } ++ ++ WSALookupServiceEnd(hlookup); ++ ++ if (error_code != NO_ERROR) { ++ WSASetLastError(error_code); ++ } ++ } ++ ++ if (result_name != NULL) { ++ size_t wlen = wcslen(result_name) + 1; ++ ++ if (wlen <= (size_t) name_len) { ++ wmemcpy(name, result_name, wlen); ++ } else { ++ error_code = WSAEFAULT; ++ } ++ goto cleanup; ++ } ++ ++ /* Stage 3: If WSALookupServiceLookup fails, fallback to GetComputerName */ ++ result_len = name_len; ++ /* Reset error code */ ++ error_code = NO_ERROR; ++ ++ if (GetComputerNameW(name, (PDWORD)&result_len) == FALSE) { ++ error_code = WSAENETDOWN; ++ if (result_len >= name_len) { ++ error_code = WSAEFAULT; ++ } ++ } ++ ++cleanup: ++ uv__free(heap_data); ++ ++ if (error_code == NO_ERROR) { ++ return NO_ERROR; ++ } else { ++ WSASetLastError(error_code); ++ return SOCKET_ERROR; ++ } ++} ++ ++ + int uv_os_gethostname(char* buffer, size_t* size) { + WCHAR buf[UV_MAXHOSTNAMESIZE]; + size_t len; +@@ -1674,7 +1803,9 @@ int uv_os_gethostname(char* buffer, size_t* size) { + + uv__once_init(); /* Initialize winsock */ + +- if (GetHostNameW(buf, UV_MAXHOSTNAMESIZE) != 0) ++ sGetHostNameW gethostnamew = ++ pGetHostNameW == NULL ? uv__gethostnamew_nt60 : pGetHostNameW; ++ if (gethostnamew(buf, UV_MAXHOSTNAMESIZE) != 0) + return uv_translate_sys_error(WSAGetLastError()); + + convert_result = uv__convert_utf16_to_utf8(buf, -1, &utf8_str); +diff --git a/deps/uv/src/win/winapi.c b/deps/uv/src/win/winapi.c +index bb86ec8ceac8ba3fccd02b292aca7ddfab38e187..9d6effb10ddd1801f7411ee71a70575b7072ab7d 100644 +--- a/deps/uv/src/win/winapi.c ++++ b/deps/uv/src/win/winapi.c +@@ -45,12 +45,15 @@ sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification; + /* User32.dll function pointer */ + sSetWinEventHook pSetWinEventHook; + ++/* ws2_32.dll function pointer */ ++sGetHostNameW pGetHostNameW; + + void uv_winapi_init(void) { + HMODULE ntdll_module; + HMODULE powrprof_module; + HMODULE user32_module; + HMODULE kernel32_module; ++ HMODULE ws2_32_module;; + + ntdll_module = GetModuleHandleA("ntdll.dll"); + if (ntdll_module == NULL) { +@@ -134,4 +137,10 @@ void uv_winapi_init(void) { + pSetWinEventHook = (sSetWinEventHook) + GetProcAddress(user32_module, "SetWinEventHook"); + } ++ ++ ws2_32_module = LoadLibraryA("ws2_32.dll"); ++ if (ws2_32_module != NULL) { ++ pGetHostNameW = (sGetHostNameW) ++ GetProcAddress(ws2_32_module, "GetHostNameW"); ++ } + } +diff --git a/deps/uv/src/win/winapi.h b/deps/uv/src/win/winapi.h +index 0b66b5634bca88cec65b1bf0c0193986f5ddd542..5951717ab9e21db274f956c44410cc03c1617eaf 100644 +--- a/deps/uv/src/win/winapi.h ++++ b/deps/uv/src/win/winapi.h +@@ -4739,6 +4739,11 @@ typedef struct _TCP_INITIAL_RTO_PARAMETERS { + # define SIO_TCP_INITIAL_RTO _WSAIOW(IOC_VENDOR,17) + #endif + ++/* From winsock2.h */ ++typedef int (WSAAPI *sGetHostNameW) ++ (PWSTR name, ++ int namelen); ++ + /* Ntdll function pointers */ + extern sRtlGetVersion pRtlGetVersion; + extern sRtlNtStatusToDosError pRtlNtStatusToDosError; +@@ -4759,4 +4764,7 @@ extern sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotifi + /* User32.dll function pointer */ + extern sSetWinEventHook pSetWinEventHook; + ++/* ws2_32.dll function pointer */ ++extern sGetHostNameW pGetHostNameW; ++ + #endif /* UV_WIN_WINAPI_H_ */