Skip to content

Commit 2fcd13e

Browse files
committed
[asan][win] Fix ExitThread leak
Use tls to store the memory created by `VirtualAlloc`, Then intercept `ExitThread` and release the memory
1 parent dd59198 commit 2fcd13e

File tree

1 file changed

+35
-1
lines changed

1 file changed

+35
-1
lines changed

compiler-rt/lib/asan/asan_win.cpp

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,32 @@ struct ThreadStartParams {
136136
void *arg;
137137
};
138138

139+
static atomic_uint32_t g_native_tls_key{TLS_OUT_OF_INDEXES};
140+
141+
bool AllocTLS(DWORD *key) {
142+
DWORD value = TlsAlloc();
143+
if (value != TLS_OUT_OF_INDEXES) {
144+
*key = value;
145+
return true;
146+
}
147+
return false;
148+
}
149+
139150
static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
151+
DWORD key = atomic_load(&g_native_tls_key, memory_order_relaxed);
152+
if (key == TLS_OUT_OF_INDEXES) {
153+
// Leak global key
154+
CHECK(AllocTLS(&key));
155+
DWORD old_key = TLS_OUT_OF_INDEXES;
156+
// Prevent another thread already store
157+
if (!atomic_compare_exchange_strong(&g_native_tls_key, (u32 *)&old_key,
158+
(u32)key, memory_order_relaxed)) {
159+
TlsFree(key);
160+
key = atomic_load(&g_native_tls_key, memory_order_relaxed);
161+
}
162+
}
163+
CHECK(key != TLS_OUT_OF_INDEXES);
164+
TlsSetValue(key, arg);
140165
AsanThread *t = (AsanThread *)arg;
141166
SetCurrentThread(t);
142167
t->ThreadStart(GetTid());
@@ -145,7 +170,6 @@ static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
145170
t->GetStartData(params);
146171

147172
auto res = (*params.start_routine)(params.arg);
148-
t->Destroy(); // POSIX calls this from TSD destructor.
149173
return res;
150174
}
151175

@@ -166,6 +190,15 @@ INTERCEPTOR_WINAPI(HANDLE, CreateThread, LPSECURITY_ATTRIBUTES security,
166190
thr_flags, tid);
167191
}
168192

193+
INTERCEPTOR_WINAPI(void, ExitThread, DWORD dwExitCode) {
194+
DWORD key = atomic_load(&g_native_tls_key, memory_order_relaxed);
195+
AsanThread *t = (AsanThread *)TlsGetValue(key);
196+
if (t) {
197+
t->Destroy();
198+
}
199+
REAL(ExitThread)(dwExitCode);
200+
}
201+
169202
// }}}
170203

171204
namespace __asan {
@@ -181,6 +214,7 @@ void InitializePlatformInterceptors() {
181214
(LPCWSTR)&InitializePlatformInterceptors, &pinned));
182215

183216
ASAN_INTERCEPT_FUNC(CreateThread);
217+
ASAN_INTERCEPT_FUNC(ExitThread);
184218
ASAN_INTERCEPT_FUNC(SetUnhandledExceptionFilter);
185219

186220
#ifdef _WIN64

0 commit comments

Comments
 (0)