2018-11-16 Richard Biener <rguenther@suse.de>
[official-gcc.git] / libsanitizer / asan / asan_interceptors.cc
blobfc9818bee8a22718a9844a4a07cfe0e9ccb5fcc8
1 //===-- asan_interceptors.cc ----------------------------------------------===//
2 //
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // This file is a part of AddressSanitizer, an address sanity checker.
9 //
10 // Intercept various libc functions.
11 //===----------------------------------------------------------------------===//
13 #include "asan_interceptors.h"
14 #include "asan_allocator.h"
15 #include "asan_internal.h"
16 #include "asan_mapping.h"
17 #include "asan_poisoning.h"
18 #include "asan_report.h"
19 #include "asan_stack.h"
20 #include "asan_stats.h"
21 #include "asan_suppressions.h"
22 #include "lsan/lsan_common.h"
23 #include "sanitizer_common/sanitizer_libc.h"
25 // There is no general interception at all on Fuchsia and RTEMS.
26 // Only the functions in asan_interceptors_memintrinsics.cc are
27 // really defined to replace libc functions.
28 #if !SANITIZER_FUCHSIA && !SANITIZER_RTEMS
30 #if SANITIZER_POSIX
31 #include "sanitizer_common/sanitizer_posix.h"
32 #endif
34 #if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION || \
35 ASAN_INTERCEPT__SJLJ_UNWIND_RAISEEXCEPTION
36 #include <unwind.h>
37 #endif
39 #if defined(__i386) && SANITIZER_LINUX
40 #define ASAN_PTHREAD_CREATE_VERSION "GLIBC_2.1"
41 #elif defined(__mips__) && SANITIZER_LINUX
42 #define ASAN_PTHREAD_CREATE_VERSION "GLIBC_2.2"
43 #endif
45 namespace __asan {
47 #define ASAN_READ_STRING_OF_LEN(ctx, s, len, n) \
48 ASAN_READ_RANGE((ctx), (s), \
49 common_flags()->strict_string_checks ? (len) + 1 : (n))
51 #define ASAN_READ_STRING(ctx, s, n) \
52 ASAN_READ_STRING_OF_LEN((ctx), (s), REAL(strlen)(s), (n))
54 static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) {
55 #if SANITIZER_INTERCEPT_STRNLEN
56 if (REAL(strnlen)) {
57 return REAL(strnlen)(s, maxlen);
59 #endif
60 return internal_strnlen(s, maxlen);
63 void SetThreadName(const char *name) {
64 AsanThread *t = GetCurrentThread();
65 if (t)
66 asanThreadRegistry().SetThreadName(t->tid(), name);
69 int OnExit() {
70 if (CAN_SANITIZE_LEAKS && common_flags()->detect_leaks &&
71 __lsan::HasReportedLeaks()) {
72 return common_flags()->exitcode;
74 // FIXME: ask frontend whether we need to return failure.
75 return 0;
78 } // namespace __asan
80 // ---------------------- Wrappers ---------------- {{{1
81 using namespace __asan; // NOLINT
83 DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr)
84 DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
86 #define ASAN_INTERCEPTOR_ENTER(ctx, func) \
87 AsanInterceptorContext _ctx = {#func}; \
88 ctx = (void *)&_ctx; \
89 (void) ctx; \
91 #define COMMON_INTERCEPT_FUNCTION(name) ASAN_INTERCEPT_FUNC(name)
92 #define COMMON_INTERCEPT_FUNCTION_VER(name, ver) \
93 ASAN_INTERCEPT_FUNC_VER(name, ver)
94 #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
95 ASAN_WRITE_RANGE(ctx, ptr, size)
96 #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
97 ASAN_READ_RANGE(ctx, ptr, size)
98 #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
99 ASAN_INTERCEPTOR_ENTER(ctx, func); \
100 do { \
101 if (asan_init_is_running) \
102 return REAL(func)(__VA_ARGS__); \
103 if (SANITIZER_MAC && UNLIKELY(!asan_inited)) \
104 return REAL(func)(__VA_ARGS__); \
105 ENSURE_ASAN_INITED(); \
106 } while (false)
107 #define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \
108 do { \
109 } while (false)
110 #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
111 do { \
112 } while (false)
113 #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
114 do { \
115 } while (false)
116 #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
117 do { \
118 } while (false)
119 #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name)
120 // Should be asanThreadRegistry().SetThreadNameByUserId(thread, name)
121 // But asan does not remember UserId's for threads (pthread_t);
122 // and remembers all ever existed threads, so the linear search by UserId
123 // can be slow.
124 #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
125 do { \
126 } while (false)
127 #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
128 // Strict init-order checking is dlopen-hostile:
129 // https://github.com/google/sanitizers/issues/178
130 #define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag) \
131 do { \
132 if (flags()->strict_init_order) \
133 StopInitOrderChecking(); \
134 CheckNoDeepBind(filename, flag); \
135 } while (false)
136 #define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
137 #define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle)
138 #define COMMON_INTERCEPTOR_LIBRARY_UNLOADED()
139 #define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!asan_inited)
140 #define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \
141 if (AsanThread *t = GetCurrentThread()) { \
142 *begin = t->tls_begin(); \
143 *end = t->tls_end(); \
144 } else { \
145 *begin = *end = 0; \
148 #define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size) \
149 do { \
150 ASAN_INTERCEPTOR_ENTER(ctx, memmove); \
151 ASAN_MEMMOVE_IMPL(ctx, to, from, size); \
152 } while (false)
154 #define COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size) \
155 do { \
156 ASAN_INTERCEPTOR_ENTER(ctx, memcpy); \
157 ASAN_MEMCPY_IMPL(ctx, to, from, size); \
158 } while (false)
160 #define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size) \
161 do { \
162 ASAN_INTERCEPTOR_ENTER(ctx, memset); \
163 ASAN_MEMSET_IMPL(ctx, block, c, size); \
164 } while (false)
166 #include "sanitizer_common/sanitizer_common_interceptors.inc"
167 #include "sanitizer_common/sanitizer_signal_interceptors.inc"
169 // Syscall interceptors don't have contexts, we don't support suppressions
170 // for them.
171 #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) ASAN_READ_RANGE(nullptr, p, s)
172 #define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) ASAN_WRITE_RANGE(nullptr, p, s)
173 #define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
174 do { \
175 (void)(p); \
176 (void)(s); \
177 } while (false)
178 #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \
179 do { \
180 (void)(p); \
181 (void)(s); \
182 } while (false)
183 #include "sanitizer_common/sanitizer_common_syscalls.inc"
184 #include "sanitizer_common/sanitizer_syscalls_netbsd.inc"
186 struct ThreadStartParam {
187 atomic_uintptr_t t;
188 atomic_uintptr_t is_registered;
191 #if ASAN_INTERCEPT_PTHREAD_CREATE
192 static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
193 ThreadStartParam *param = reinterpret_cast<ThreadStartParam *>(arg);
194 AsanThread *t = nullptr;
195 while ((t = reinterpret_cast<AsanThread *>(
196 atomic_load(&param->t, memory_order_acquire))) == nullptr)
197 internal_sched_yield();
198 SetCurrentThread(t);
199 return t->ThreadStart(GetTid(), &param->is_registered);
202 INTERCEPTOR(int, pthread_create, void *thread,
203 void *attr, void *(*start_routine)(void*), void *arg) {
204 EnsureMainThreadIDIsCorrect();
205 // Strict init-order checking is thread-hostile.
206 if (flags()->strict_init_order)
207 StopInitOrderChecking();
208 GET_STACK_TRACE_THREAD;
209 int detached = 0;
210 if (attr)
211 REAL(pthread_attr_getdetachstate)(attr, &detached);
212 ThreadStartParam param;
213 atomic_store(&param.t, 0, memory_order_relaxed);
214 atomic_store(&param.is_registered, 0, memory_order_relaxed);
215 int result;
217 // Ignore all allocations made by pthread_create: thread stack/TLS may be
218 // stored by pthread for future reuse even after thread destruction, and
219 // the linked list it's stored in doesn't even hold valid pointers to the
220 // objects, the latter are calculated by obscure pointer arithmetic.
221 #if CAN_SANITIZE_LEAKS
222 __lsan::ScopedInterceptorDisabler disabler;
223 #endif
224 result = REAL(pthread_create)(thread, attr, asan_thread_start, &param);
226 if (result == 0) {
227 u32 current_tid = GetCurrentTidOrInvalid();
228 AsanThread *t =
229 AsanThread::Create(start_routine, arg, current_tid, &stack, detached);
230 atomic_store(&param.t, reinterpret_cast<uptr>(t), memory_order_release);
231 // Wait until the AsanThread object is initialized and the ThreadRegistry
232 // entry is in "started" state. One reason for this is that after this
233 // interceptor exits, the child thread's stack may be the only thing holding
234 // the |arg| pointer. This may cause LSan to report a leak if leak checking
235 // happens at a point when the interceptor has already exited, but the stack
236 // range for the child thread is not yet known.
237 while (atomic_load(&param.is_registered, memory_order_acquire) == 0)
238 internal_sched_yield();
240 return result;
243 INTERCEPTOR(int, pthread_join, void *t, void **arg) {
244 return real_pthread_join(t, arg);
247 DEFINE_REAL_PTHREAD_FUNCTIONS
248 #endif // ASAN_INTERCEPT_PTHREAD_CREATE
250 #if ASAN_INTERCEPT_SWAPCONTEXT
251 static void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) {
252 // Align to page size.
253 uptr PageSize = GetPageSizeCached();
254 uptr bottom = stack & ~(PageSize - 1);
255 ssize += stack - bottom;
256 ssize = RoundUpTo(ssize, PageSize);
257 static const uptr kMaxSaneContextStackSize = 1 << 22; // 4 Mb
258 if (AddrIsInMem(bottom) && ssize && ssize <= kMaxSaneContextStackSize) {
259 PoisonShadow(bottom, ssize, 0);
263 INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp,
264 struct ucontext_t *ucp) {
265 static bool reported_warning = false;
266 if (!reported_warning) {
267 Report("WARNING: ASan doesn't fully support makecontext/swapcontext "
268 "functions and may produce false positives in some cases!\n");
269 reported_warning = true;
271 // Clear shadow memory for new context (it may share stack
272 // with current context).
273 uptr stack, ssize;
274 ReadContextStack(ucp, &stack, &ssize);
275 ClearShadowMemoryForContextStack(stack, ssize);
276 #if __has_attribute(__indirect_return__) && \
277 (defined(__x86_64__) || defined(__i386__))
278 int (*real_swapcontext)(struct ucontext_t *, struct ucontext_t *)
279 __attribute__((__indirect_return__))
280 = REAL(swapcontext);
281 int res = real_swapcontext(oucp, ucp);
282 #else
283 int res = REAL(swapcontext)(oucp, ucp);
284 #endif
285 // swapcontext technically does not return, but program may swap context to
286 // "oucp" later, that would look as if swapcontext() returned 0.
287 // We need to clear shadow for ucp once again, as it may be in arbitrary
288 // state.
289 ClearShadowMemoryForContextStack(stack, ssize);
290 return res;
292 #endif // ASAN_INTERCEPT_SWAPCONTEXT
294 #if SANITIZER_NETBSD
295 #define longjmp __longjmp14
296 #define siglongjmp __siglongjmp14
297 #endif
299 INTERCEPTOR(void, longjmp, void *env, int val) {
300 __asan_handle_no_return();
301 REAL(longjmp)(env, val);
304 #if ASAN_INTERCEPT__LONGJMP
305 INTERCEPTOR(void, _longjmp, void *env, int val) {
306 __asan_handle_no_return();
307 REAL(_longjmp)(env, val);
309 #endif
311 #if ASAN_INTERCEPT___LONGJMP_CHK
312 INTERCEPTOR(void, __longjmp_chk, void *env, int val) {
313 __asan_handle_no_return();
314 REAL(__longjmp_chk)(env, val);
316 #endif
318 #if ASAN_INTERCEPT_SIGLONGJMP
319 INTERCEPTOR(void, siglongjmp, void *env, int val) {
320 __asan_handle_no_return();
321 REAL(siglongjmp)(env, val);
323 #endif
325 #if ASAN_INTERCEPT___CXA_THROW
326 INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
327 CHECK(REAL(__cxa_throw));
328 __asan_handle_no_return();
329 REAL(__cxa_throw)(a, b, c);
331 #endif
333 #if ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION
334 INTERCEPTOR(void, __cxa_rethrow_primary_exception, void *a) {
335 CHECK(REAL(__cxa_rethrow_primary_exception));
336 __asan_handle_no_return();
337 REAL(__cxa_rethrow_primary_exception)(a);
339 #endif
341 #if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION
342 INTERCEPTOR(_Unwind_Reason_Code, _Unwind_RaiseException,
343 _Unwind_Exception *object) {
344 CHECK(REAL(_Unwind_RaiseException));
345 __asan_handle_no_return();
346 return REAL(_Unwind_RaiseException)(object);
348 #endif
350 #if ASAN_INTERCEPT__SJLJ_UNWIND_RAISEEXCEPTION
351 INTERCEPTOR(_Unwind_Reason_Code, _Unwind_SjLj_RaiseException,
352 _Unwind_Exception *object) {
353 CHECK(REAL(_Unwind_SjLj_RaiseException));
354 __asan_handle_no_return();
355 return REAL(_Unwind_SjLj_RaiseException)(object);
357 #endif
359 #if ASAN_INTERCEPT_INDEX
360 # if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
361 INTERCEPTOR(char*, index, const char *string, int c)
362 ALIAS(WRAPPER_NAME(strchr));
363 # else
364 # if SANITIZER_MAC
365 DECLARE_REAL(char*, index, const char *string, int c)
366 OVERRIDE_FUNCTION(index, strchr);
367 # else
368 DEFINE_REAL(char*, index, const char *string, int c)
369 # endif
370 # endif
371 #endif // ASAN_INTERCEPT_INDEX
373 // For both strcat() and strncat() we need to check the validity of |to|
374 // argument irrespective of the |from| length.
375 INTERCEPTOR(char*, strcat, char *to, const char *from) { // NOLINT
376 void *ctx;
377 ASAN_INTERCEPTOR_ENTER(ctx, strcat); // NOLINT
378 ENSURE_ASAN_INITED();
379 if (flags()->replace_str) {
380 uptr from_length = REAL(strlen)(from);
381 ASAN_READ_RANGE(ctx, from, from_length + 1);
382 uptr to_length = REAL(strlen)(to);
383 ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
384 ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
385 // If the copying actually happens, the |from| string should not overlap
386 // with the resulting string starting at |to|, which has a length of
387 // to_length + from_length + 1.
388 if (from_length > 0) {
389 CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1,
390 from, from_length + 1);
393 return REAL(strcat)(to, from); // NOLINT
396 INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
397 void *ctx;
398 ASAN_INTERCEPTOR_ENTER(ctx, strncat);
399 ENSURE_ASAN_INITED();
400 if (flags()->replace_str) {
401 uptr from_length = MaybeRealStrnlen(from, size);
402 uptr copy_length = Min(size, from_length + 1);
403 ASAN_READ_RANGE(ctx, from, copy_length);
404 uptr to_length = REAL(strlen)(to);
405 ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
406 ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
407 if (from_length > 0) {
408 CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1,
409 from, copy_length);
412 return REAL(strncat)(to, from, size);
415 INTERCEPTOR(char*, strcpy, char *to, const char *from) { // NOLINT
416 void *ctx;
417 ASAN_INTERCEPTOR_ENTER(ctx, strcpy); // NOLINT
418 #if SANITIZER_MAC
419 if (UNLIKELY(!asan_inited)) return REAL(strcpy)(to, from); // NOLINT
420 #endif
421 // strcpy is called from malloc_default_purgeable_zone()
422 // in __asan::ReplaceSystemAlloc() on Mac.
423 if (asan_init_is_running) {
424 return REAL(strcpy)(to, from); // NOLINT
426 ENSURE_ASAN_INITED();
427 if (flags()->replace_str) {
428 uptr from_size = REAL(strlen)(from) + 1;
429 CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size);
430 ASAN_READ_RANGE(ctx, from, from_size);
431 ASAN_WRITE_RANGE(ctx, to, from_size);
433 return REAL(strcpy)(to, from); // NOLINT
436 INTERCEPTOR(char*, strdup, const char *s) {
437 void *ctx;
438 ASAN_INTERCEPTOR_ENTER(ctx, strdup);
439 if (UNLIKELY(!asan_inited)) return internal_strdup(s);
440 ENSURE_ASAN_INITED();
441 uptr length = REAL(strlen)(s);
442 if (flags()->replace_str) {
443 ASAN_READ_RANGE(ctx, s, length + 1);
445 GET_STACK_TRACE_MALLOC;
446 void *new_mem = asan_malloc(length + 1, &stack);
447 REAL(memcpy)(new_mem, s, length + 1);
448 return reinterpret_cast<char*>(new_mem);
451 #if ASAN_INTERCEPT___STRDUP
452 INTERCEPTOR(char*, __strdup, const char *s) {
453 void *ctx;
454 ASAN_INTERCEPTOR_ENTER(ctx, strdup);
455 if (UNLIKELY(!asan_inited)) return internal_strdup(s);
456 ENSURE_ASAN_INITED();
457 uptr length = REAL(strlen)(s);
458 if (flags()->replace_str) {
459 ASAN_READ_RANGE(ctx, s, length + 1);
461 GET_STACK_TRACE_MALLOC;
462 void *new_mem = asan_malloc(length + 1, &stack);
463 REAL(memcpy)(new_mem, s, length + 1);
464 return reinterpret_cast<char*>(new_mem);
466 #endif // ASAN_INTERCEPT___STRDUP
468 INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) {
469 void *ctx;
470 ASAN_INTERCEPTOR_ENTER(ctx, strncpy);
471 ENSURE_ASAN_INITED();
472 if (flags()->replace_str) {
473 uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1);
474 CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size);
475 ASAN_READ_RANGE(ctx, from, from_size);
476 ASAN_WRITE_RANGE(ctx, to, size);
478 return REAL(strncpy)(to, from, size);
481 INTERCEPTOR(long, strtol, const char *nptr, // NOLINT
482 char **endptr, int base) {
483 void *ctx;
484 ASAN_INTERCEPTOR_ENTER(ctx, strtol);
485 ENSURE_ASAN_INITED();
486 if (!flags()->replace_str) {
487 return REAL(strtol)(nptr, endptr, base);
489 char *real_endptr;
490 long result = REAL(strtol)(nptr, &real_endptr, base); // NOLINT
491 StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
492 return result;
495 INTERCEPTOR(int, atoi, const char *nptr) {
496 void *ctx;
497 ASAN_INTERCEPTOR_ENTER(ctx, atoi);
498 #if SANITIZER_MAC
499 if (UNLIKELY(!asan_inited)) return REAL(atoi)(nptr);
500 #endif
501 ENSURE_ASAN_INITED();
502 if (!flags()->replace_str) {
503 return REAL(atoi)(nptr);
505 char *real_endptr;
506 // "man atoi" tells that behavior of atoi(nptr) is the same as
507 // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
508 // parsed integer can't be stored in *long* type (even if it's
509 // different from int). So, we just imitate this behavior.
510 int result = REAL(strtol)(nptr, &real_endptr, 10);
511 FixRealStrtolEndptr(nptr, &real_endptr);
512 ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
513 return result;
516 INTERCEPTOR(long, atol, const char *nptr) { // NOLINT
517 void *ctx;
518 ASAN_INTERCEPTOR_ENTER(ctx, atol);
519 #if SANITIZER_MAC
520 if (UNLIKELY(!asan_inited)) return REAL(atol)(nptr);
521 #endif
522 ENSURE_ASAN_INITED();
523 if (!flags()->replace_str) {
524 return REAL(atol)(nptr);
526 char *real_endptr;
527 long result = REAL(strtol)(nptr, &real_endptr, 10); // NOLINT
528 FixRealStrtolEndptr(nptr, &real_endptr);
529 ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
530 return result;
533 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
534 INTERCEPTOR(long long, strtoll, const char *nptr, // NOLINT
535 char **endptr, int base) {
536 void *ctx;
537 ASAN_INTERCEPTOR_ENTER(ctx, strtoll);
538 ENSURE_ASAN_INITED();
539 if (!flags()->replace_str) {
540 return REAL(strtoll)(nptr, endptr, base);
542 char *real_endptr;
543 long long result = REAL(strtoll)(nptr, &real_endptr, base); // NOLINT
544 StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
545 return result;
548 INTERCEPTOR(long long, atoll, const char *nptr) { // NOLINT
549 void *ctx;
550 ASAN_INTERCEPTOR_ENTER(ctx, atoll);
551 ENSURE_ASAN_INITED();
552 if (!flags()->replace_str) {
553 return REAL(atoll)(nptr);
555 char *real_endptr;
556 long long result = REAL(strtoll)(nptr, &real_endptr, 10); // NOLINT
557 FixRealStrtolEndptr(nptr, &real_endptr);
558 ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
559 return result;
561 #endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
563 #if ASAN_INTERCEPT___CXA_ATEXIT
564 static void AtCxaAtexit(void *unused) {
565 (void)unused;
566 StopInitOrderChecking();
569 INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
570 void *dso_handle) {
571 #if SANITIZER_MAC
572 if (UNLIKELY(!asan_inited)) return REAL(__cxa_atexit)(func, arg, dso_handle);
573 #endif
574 ENSURE_ASAN_INITED();
575 int res = REAL(__cxa_atexit)(func, arg, dso_handle);
576 REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr);
577 return res;
579 #endif // ASAN_INTERCEPT___CXA_ATEXIT
581 // ---------------------- InitializeAsanInterceptors ---------------- {{{1
582 namespace __asan {
583 void InitializeAsanInterceptors() {
584 static bool was_called_once;
585 CHECK(!was_called_once);
586 was_called_once = true;
587 InitializeCommonInterceptors();
588 InitializeSignalInterceptors();
590 // Intercept str* functions.
591 ASAN_INTERCEPT_FUNC(strcat); // NOLINT
592 ASAN_INTERCEPT_FUNC(strcpy); // NOLINT
593 ASAN_INTERCEPT_FUNC(strncat);
594 ASAN_INTERCEPT_FUNC(strncpy);
595 ASAN_INTERCEPT_FUNC(strdup);
596 #if ASAN_INTERCEPT___STRDUP
597 ASAN_INTERCEPT_FUNC(__strdup);
598 #endif
599 #if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
600 ASAN_INTERCEPT_FUNC(index);
601 #endif
603 ASAN_INTERCEPT_FUNC(atoi);
604 ASAN_INTERCEPT_FUNC(atol);
605 ASAN_INTERCEPT_FUNC(strtol);
606 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
607 ASAN_INTERCEPT_FUNC(atoll);
608 ASAN_INTERCEPT_FUNC(strtoll);
609 #endif
611 // Intecept jump-related functions.
612 ASAN_INTERCEPT_FUNC(longjmp);
614 #if ASAN_INTERCEPT_SWAPCONTEXT
615 ASAN_INTERCEPT_FUNC(swapcontext);
616 #endif
617 #if ASAN_INTERCEPT__LONGJMP
618 ASAN_INTERCEPT_FUNC(_longjmp);
619 #endif
620 #if ASAN_INTERCEPT___LONGJMP_CHK
621 ASAN_INTERCEPT_FUNC(__longjmp_chk);
622 #endif
623 #if ASAN_INTERCEPT_SIGLONGJMP
624 ASAN_INTERCEPT_FUNC(siglongjmp);
625 #endif
627 // Intercept exception handling functions.
628 #if ASAN_INTERCEPT___CXA_THROW
629 ASAN_INTERCEPT_FUNC(__cxa_throw);
630 #endif
631 #if ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION
632 ASAN_INTERCEPT_FUNC(__cxa_rethrow_primary_exception);
633 #endif
634 // Indirectly intercept std::rethrow_exception.
635 #if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION
636 INTERCEPT_FUNCTION(_Unwind_RaiseException);
637 #endif
638 // Indirectly intercept std::rethrow_exception.
639 #if ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION
640 INTERCEPT_FUNCTION(_Unwind_SjLj_RaiseException);
641 #endif
643 // Intercept threading-related functions
644 #if ASAN_INTERCEPT_PTHREAD_CREATE
645 #if defined(ASAN_PTHREAD_CREATE_VERSION)
646 ASAN_INTERCEPT_FUNC_VER(pthread_create, ASAN_PTHREAD_CREATE_VERSION);
647 #else
648 ASAN_INTERCEPT_FUNC(pthread_create);
649 #endif
650 ASAN_INTERCEPT_FUNC(pthread_join);
651 #endif
653 // Intercept atexit function.
654 #if ASAN_INTERCEPT___CXA_ATEXIT
655 ASAN_INTERCEPT_FUNC(__cxa_atexit);
656 #endif
658 InitializePlatformInterceptors();
660 VReport(1, "AddressSanitizer: libc interceptors initialized\n");
663 } // namespace __asan
665 #endif // !SANITIZER_FUCHSIA