-
Notifications
You must be signed in to change notification settings - Fork 15k
/
fix_crash_caused_by_gethostnamew_on_windows_7.patch
184 lines (172 loc) · 5.59 KB
/
fix_crash_caused_by_gethostnamew_on_windows_7.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Cheng Zhao <zcbenz@gmail.com>
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 33e874ac442f88b58d2b68c8ec9764f6f664552e..eb10d0395ed55504b29efa43779e9c10965d45e1 100644
--- a/deps/uv/src/win/util.c
+++ b/deps/uv/src/win/util.c
@@ -37,6 +37,7 @@
#include <psapi.h>
#include <tlhelp32.h>
#include <windows.h>
+#include <svcguid.h>
/* clang-format on */
#include <userenv.h>
#include <math.h>
@@ -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,11 +1803,11 @@ int uv_os_gethostname(char* buffer, size_t* size) {
uv__once_init(); /* Initialize winsock */
- if (pGetHostNameW == NULL)
- return UV_ENOSYS;
+ uv_sGetHostNameW gethostnamew =
+ pGetHostNameW == NULL ? uv__gethostnamew_nt60 : pGetHostNameW;
- if (pGetHostNameW(buf, UV_MAXHOSTNAMESIZE) != 0)
- return uv_translate_sys_error(WSAGetLastError());
+ if (gethostnamew(buf, UV_MAXHOSTNAMESIZE) != 0)
+ return uv_translate_sys_error(WSAGetLastError());
convert_result = uv__convert_utf16_to_utf8(buf, -1, &utf8_str);