20
20
21
21
#include " asan_interceptors.h"
22
22
#include " asan_internal.h"
23
+ #include " asan_mapping.h"
23
24
#include " asan_report.h"
24
25
#include " asan_stack.h"
25
26
#include " asan_thread.h"
26
- #include " asan_mapping.h"
27
27
#include " sanitizer_common/sanitizer_libc.h"
28
28
#include " sanitizer_common/sanitizer_mutex.h"
29
29
#include " sanitizer_common/sanitizer_win.h"
@@ -77,7 +77,7 @@ static long WINAPI SEHHandler(EXCEPTION_POINTERS *info) {
77
77
}
78
78
79
79
INTERCEPTOR_WINAPI (LPTOP_LEVEL_EXCEPTION_FILTER, SetUnhandledExceptionFilter,
80
- LPTOP_LEVEL_EXCEPTION_FILTER ExceptionFilter) {
80
+ LPTOP_LEVEL_EXCEPTION_FILTER ExceptionFilter) {
81
81
CHECK (REAL (SetUnhandledExceptionFilter));
82
82
if (ExceptionFilter == &SEHHandler)
83
83
return REAL (SetUnhandledExceptionFilter)(ExceptionFilter);
@@ -132,7 +132,7 @@ INTERCEPTOR(int, _except_handler4, void *a, void *b, void *c, void *d) {
132
132
#endif
133
133
134
134
static thread_return_t THREAD_CALLING_CONV asan_thread_start (void *arg) {
135
- AsanThread *t = (AsanThread*)arg;
135
+ AsanThread *t = (AsanThread *)arg;
136
136
SetCurrentThread (t);
137
137
return t->ThreadStart (GetTid (), /* signal_thread_is_registered */ nullptr );
138
138
}
@@ -162,10 +162,9 @@ void InitializePlatformInterceptors() {
162
162
// The interceptors were not designed to be removable, so we have to keep this
163
163
// module alive for the life of the process.
164
164
HMODULE pinned;
165
- CHECK (GetModuleHandleExW (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
166
- GET_MODULE_HANDLE_EX_FLAG_PIN,
167
- (LPCWSTR)&InitializePlatformInterceptors,
168
- &pinned));
165
+ CHECK (GetModuleHandleExW (
166
+ GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_PIN,
167
+ (LPCWSTR)&InitializePlatformInterceptors, &pinned));
169
168
170
169
ASAN_INTERCEPT_FUNC (CreateThread);
171
170
ASAN_INTERCEPT_FUNC (SetUnhandledExceptionFilter);
@@ -197,24 +196,46 @@ static bool tsd_key_inited = false;
197
196
198
197
static __declspec (thread) void *fake_tsd = 0;
199
198
199
+ // https://docs.microsoft.com/en-us/windows/desktop/api/winternl/ns-winternl-_teb
200
+ // "[This structure may be altered in future versions of Windows. Applications
201
+ // should use the alternate functions listed in this topic.]"
202
+ typedef struct _TEB {
203
+ PVOID Reserved1[12 ];
204
+ // PVOID ThreadLocalStoragePointer; is here, at the last field in Reserved1.
205
+ PVOID ProcessEnvironmentBlock;
206
+ PVOID Reserved2[399 ];
207
+ BYTE Reserved3[1952 ];
208
+ PVOID TlsSlots[64 ];
209
+ BYTE Reserved4[8 ];
210
+ PVOID Reserved5[26 ];
211
+ PVOID ReservedForOle;
212
+ PVOID Reserved6[4 ];
213
+ PVOID TlsExpansionSlots;
214
+ } TEB, *PTEB;
215
+
216
+ constexpr size_t TEB_RESERVED_FIELDS_THREAD_LOCAL_STORAGE_OFFSET = 11 ;
217
+ BOOL IsTlsInitialized () {
218
+ PTEB teb = (PTEB)NtCurrentTeb ();
219
+ return teb->Reserved1 [TEB_RESERVED_FIELDS_THREAD_LOCAL_STORAGE_OFFSET] !=
220
+ nullptr ;
221
+ }
222
+
200
223
void AsanTSDInit (void (*destructor)(void *tsd)) {
201
224
// FIXME: we're ignoring the destructor for now.
202
225
tsd_key_inited = true ;
203
226
}
204
227
205
228
void *AsanTSDGet () {
206
229
CHECK (tsd_key_inited);
207
- return fake_tsd;
230
+ return IsTlsInitialized () ? fake_tsd : nullptr ;
208
231
}
209
232
210
233
void AsanTSDSet (void *tsd) {
211
234
CHECK (tsd_key_inited);
212
235
fake_tsd = tsd;
213
236
}
214
237
215
- void PlatformTSDDtor (void *tsd) {
216
- AsanThread::TSDDtor (tsd);
217
- }
238
+ void PlatformTSDDtor (void *tsd) { AsanThread::TSDDtor (tsd); }
218
239
// }}}
219
240
220
241
// ---------------------- Various stuff ---------------- {{{
@@ -245,9 +266,7 @@ void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
245
266
UNIMPLEMENTED ();
246
267
}
247
268
248
- void AsanOnDeadlySignal (int , void *siginfo, void *context) {
249
- UNIMPLEMENTED ();
250
- }
269
+ void AsanOnDeadlySignal (int , void *siginfo, void *context) { UNIMPLEMENTED (); }
251
270
252
271
#if SANITIZER_WINDOWS64
253
272
// Exception handler for dealing with shadow memory.
@@ -256,7 +275,9 @@ ShadowExceptionHandler(PEXCEPTION_POINTERS exception_pointers) {
256
275
uptr page_size = GetPageSizeCached ();
257
276
// Only handle access violations.
258
277
if (exception_pointers->ExceptionRecord ->ExceptionCode !=
259
- EXCEPTION_ACCESS_VIOLATION) {
278
+ EXCEPTION_ACCESS_VIOLATION ||
279
+ exception_pointers->ExceptionRecord ->NumberParameters < 2 ) {
280
+ __asan_handle_no_return ();
260
281
return EXCEPTION_CONTINUE_SEARCH;
261
282
}
262
283
@@ -265,7 +286,10 @@ ShadowExceptionHandler(PEXCEPTION_POINTERS exception_pointers) {
265
286
(uptr)(exception_pointers->ExceptionRecord ->ExceptionInformation [1 ]);
266
287
267
288
// Check valid shadow range.
268
- if (!AddrIsInShadow (addr)) return EXCEPTION_CONTINUE_SEARCH;
289
+ if (!AddrIsInShadow (addr)) {
290
+ __asan_handle_no_return ();
291
+ return EXCEPTION_CONTINUE_SEARCH;
292
+ }
269
293
270
294
// This is an access violation while trying to read from the shadow. Commit
271
295
// the relevant page and let execution continue.
@@ -276,7 +300,8 @@ ShadowExceptionHandler(PEXCEPTION_POINTERS exception_pointers) {
276
300
// Commit the page.
277
301
uptr result =
278
302
(uptr)::VirtualAlloc ((LPVOID)page, page_size, MEM_COMMIT, PAGE_READWRITE);
279
- if (result != page) return EXCEPTION_CONTINUE_SEARCH;
303
+ if (result != page)
304
+ return EXCEPTION_CONTINUE_SEARCH;
280
305
281
306
// The page mapping succeeded, so continue execution as usual.
282
307
return EXCEPTION_CONTINUE_EXECUTION;
@@ -293,7 +318,7 @@ void InitializePlatformExceptionHandlers() {
293
318
}
294
319
295
320
bool IsSystemHeapAddress (uptr addr) {
296
- return ::HeapValidate (GetProcessHeap (), 0 , (void *)addr) != FALSE ;
321
+ return ::HeapValidate (GetProcessHeap (), 0 , (void *)addr) != FALSE ;
297
322
}
298
323
299
324
// We want to install our own exception handler (EH) to print helpful reports
@@ -312,8 +337,7 @@ bool IsSystemHeapAddress(uptr addr) {
312
337
// asan_dynamic_runtime_thunk.lib to all the modules, thus __asan_set_seh_filter
313
338
// will be called for each instrumented module. This ensures that at least one
314
339
// __asan_set_seh_filter call happens after the .exe module CRT is initialized.
315
- extern " C" SANITIZER_INTERFACE_ATTRIBUTE
316
- int __asan_set_seh_filter () {
340
+ extern " C" SANITIZER_INTERFACE_ATTRIBUTE int __asan_set_seh_filter () {
317
341
// We should only store the previous handler if it's not our own handler in
318
342
// order to avoid loops in the EH chain.
319
343
auto prev_seh_handler = SetUnhandledExceptionFilter (SEHHandler);
@@ -347,12 +371,13 @@ __declspec(allocate(".CRT$XCAB")) int (*__intercept_seh)() =
347
371
// which run before the CRT. Users also add code to .CRT$XLC, so it's important
348
372
// to run our initializers first.
349
373
static void NTAPI asan_thread_init (void *module, DWORD reason, void *reserved) {
350
- if (reason == DLL_PROCESS_ATTACH) __asan_init ();
374
+ if (reason == DLL_PROCESS_ATTACH)
375
+ __asan_init ();
351
376
}
352
377
353
378
#pragma section(".CRT$XLAB", long, read) // NOLINT
354
- __declspec (allocate(" .CRT$XLAB" )) void (NTAPI *__asan_tls_init)(void *,
355
- unsigned long , void *) = asan_thread_init;
379
+ __declspec (allocate(" .CRT$XLAB" )) void(NTAPI *__asan_tls_init)(
380
+ void *, unsigned long , void *) = asan_thread_init;
356
381
#endif
357
382
358
383
static void NTAPI asan_thread_exit (void *module, DWORD reason, void *reserved) {
@@ -365,8 +390,8 @@ static void NTAPI asan_thread_exit(void *module, DWORD reason, void *reserved) {
365
390
}
366
391
367
392
#pragma section(".CRT$XLY", long, read) // NOLINT
368
- __declspec (allocate(" .CRT$XLY" )) void (NTAPI *__asan_tls_exit)(void *,
369
- unsigned long , void *) = asan_thread_exit;
393
+ __declspec (allocate(" .CRT$XLY" )) void (NTAPI *__asan_tls_exit)(
394
+ void *, unsigned long , void *) = asan_thread_exit;
370
395
371
396
WIN_FORCE_LINK (__asan_dso_reg_hook)
372
397
0 commit comments