1 //===-- asan_interceptors.cc ----------------------------------------------===//
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
6 //===----------------------------------------------------------------------===//
8 // This file is a part of AddressSanitizer, an address sanity checker.
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
31 #include "sanitizer_common/sanitizer_posix.h"
34 #if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION || \
35 ASAN_INTERCEPT__SJLJ_UNWIND_RAISEEXCEPTION
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"
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
57 return REAL(strnlen
)(s
, maxlen
);
60 return internal_strnlen(s
, maxlen
);
63 void SetThreadName(const char *name
) {
64 AsanThread
*t
= GetCurrentThread();
66 asanThreadRegistry().SetThreadName(t
->tid(), name
);
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.
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; \
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); \
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(); \
107 #define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \
110 #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
113 #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
116 #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
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
124 #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
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) \
132 if (flags()->strict_init_order) \
133 StopInitOrderChecking(); \
134 CheckNoDeepBind(filename, flag); \
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(); \
148 #define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size) \
150 ASAN_INTERCEPTOR_ENTER(ctx, memmove); \
151 ASAN_MEMMOVE_IMPL(ctx, to, from, size); \
154 #define COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size) \
156 ASAN_INTERCEPTOR_ENTER(ctx, memcpy); \
157 ASAN_MEMCPY_IMPL(ctx, to, from, size); \
160 #define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size) \
162 ASAN_INTERCEPTOR_ENTER(ctx, memset); \
163 ASAN_MEMSET_IMPL(ctx, block, c, size); \
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
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) \
178 #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \
183 #include "sanitizer_common/sanitizer_common_syscalls.inc"
184 #include "sanitizer_common/sanitizer_syscalls_netbsd.inc"
186 struct ThreadStartParam
{
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(¶m
->t
, memory_order_acquire
))) == nullptr)
197 internal_sched_yield();
199 return t
->ThreadStart(GetTid(), ¶m
->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
;
211 REAL(pthread_attr_getdetachstate
)(attr
, &detached
);
212 ThreadStartParam param
;
213 atomic_store(¶m
.t
, 0, memory_order_relaxed
);
214 atomic_store(¶m
.is_registered
, 0, memory_order_relaxed
);
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
;
224 result
= REAL(pthread_create
)(thread
, attr
, asan_thread_start
, ¶m
);
227 u32 current_tid
= GetCurrentTidOrInvalid();
229 AsanThread::Create(start_routine
, arg
, current_tid
, &stack
, detached
);
230 atomic_store(¶m
.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(¶m
.is_registered
, memory_order_acquire
) == 0)
238 internal_sched_yield();
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).
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__
))
281 int res
= real_swapcontext(oucp
, ucp
);
283 int res
= REAL(swapcontext
)(oucp
, ucp
);
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
289 ClearShadowMemoryForContextStack(stack
, ssize
);
292 #endif // ASAN_INTERCEPT_SWAPCONTEXT
295 #define longjmp __longjmp14
296 #define siglongjmp __siglongjmp14
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
);
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
);
318 #if ASAN_INTERCEPT_SIGLONGJMP
319 INTERCEPTOR(void, siglongjmp
, void *env
, int val
) {
320 __asan_handle_no_return();
321 REAL(siglongjmp
)(env
, val
);
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
);
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
);
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
);
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
);
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
));
365 DECLARE_REAL(char*, index
, const char *string
, int c
)
366 OVERRIDE_FUNCTION(index
, strchr
);
368 DEFINE_REAL(char*, index
, const char *string
, int c
)
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
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
) {
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,
412 return REAL(strncat
)(to
, from
, size
);
415 INTERCEPTOR(char*, strcpy
, char *to
, const char *from
) { // NOLINT
417 ASAN_INTERCEPTOR_ENTER(ctx
, strcpy
); // NOLINT
419 if (UNLIKELY(!asan_inited
)) return REAL(strcpy
)(to
, from
); // NOLINT
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
) {
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
) {
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
) {
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
) {
484 ASAN_INTERCEPTOR_ENTER(ctx
, strtol
);
485 ENSURE_ASAN_INITED();
486 if (!flags()->replace_str
) {
487 return REAL(strtol
)(nptr
, endptr
, base
);
490 long result
= REAL(strtol
)(nptr
, &real_endptr
, base
); // NOLINT
491 StrtolFixAndCheck(ctx
, nptr
, endptr
, real_endptr
, base
);
495 INTERCEPTOR(int, atoi
, const char *nptr
) {
497 ASAN_INTERCEPTOR_ENTER(ctx
, atoi
);
499 if (UNLIKELY(!asan_inited
)) return REAL(atoi
)(nptr
);
501 ENSURE_ASAN_INITED();
502 if (!flags()->replace_str
) {
503 return REAL(atoi
)(nptr
);
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);
516 INTERCEPTOR(long, atol
, const char *nptr
) { // NOLINT
518 ASAN_INTERCEPTOR_ENTER(ctx
, atol
);
520 if (UNLIKELY(!asan_inited
)) return REAL(atol
)(nptr
);
522 ENSURE_ASAN_INITED();
523 if (!flags()->replace_str
) {
524 return REAL(atol
)(nptr
);
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);
533 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
534 INTERCEPTOR(long long, strtoll
, const char *nptr
, // NOLINT
535 char **endptr
, int base
) {
537 ASAN_INTERCEPTOR_ENTER(ctx
, strtoll
);
538 ENSURE_ASAN_INITED();
539 if (!flags()->replace_str
) {
540 return REAL(strtoll
)(nptr
, endptr
, base
);
543 long long result
= REAL(strtoll
)(nptr
, &real_endptr
, base
); // NOLINT
544 StrtolFixAndCheck(ctx
, nptr
, endptr
, real_endptr
, base
);
548 INTERCEPTOR(long long, atoll
, const char *nptr
) { // NOLINT
550 ASAN_INTERCEPTOR_ENTER(ctx
, atoll
);
551 ENSURE_ASAN_INITED();
552 if (!flags()->replace_str
) {
553 return REAL(atoll
)(nptr
);
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);
561 #endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
563 #if ASAN_INTERCEPT___CXA_ATEXIT
564 static void AtCxaAtexit(void *unused
) {
566 StopInitOrderChecking();
569 INTERCEPTOR(int, __cxa_atexit
, void (*func
)(void *), void *arg
,
572 if (UNLIKELY(!asan_inited
)) return REAL(__cxa_atexit
)(func
, arg
, dso_handle
);
574 ENSURE_ASAN_INITED();
575 int res
= REAL(__cxa_atexit
)(func
, arg
, dso_handle
);
576 REAL(__cxa_atexit
)(AtCxaAtexit
, nullptr, nullptr);
579 #endif // ASAN_INTERCEPT___CXA_ATEXIT
581 // ---------------------- InitializeAsanInterceptors ---------------- {{{1
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
);
599 #if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
600 ASAN_INTERCEPT_FUNC(index
);
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
);
611 // Intecept jump-related functions.
612 ASAN_INTERCEPT_FUNC(longjmp
);
614 #if ASAN_INTERCEPT_SWAPCONTEXT
615 ASAN_INTERCEPT_FUNC(swapcontext
);
617 #if ASAN_INTERCEPT__LONGJMP
618 ASAN_INTERCEPT_FUNC(_longjmp
);
620 #if ASAN_INTERCEPT___LONGJMP_CHK
621 ASAN_INTERCEPT_FUNC(__longjmp_chk
);
623 #if ASAN_INTERCEPT_SIGLONGJMP
624 ASAN_INTERCEPT_FUNC(siglongjmp
);
627 // Intercept exception handling functions.
628 #if ASAN_INTERCEPT___CXA_THROW
629 ASAN_INTERCEPT_FUNC(__cxa_throw
);
631 #if ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION
632 ASAN_INTERCEPT_FUNC(__cxa_rethrow_primary_exception
);
634 // Indirectly intercept std::rethrow_exception.
635 #if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION
636 INTERCEPT_FUNCTION(_Unwind_RaiseException
);
638 // Indirectly intercept std::rethrow_exception.
639 #if ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION
640 INTERCEPT_FUNCTION(_Unwind_SjLj_RaiseException
);
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
);
648 ASAN_INTERCEPT_FUNC(pthread_create
);
650 ASAN_INTERCEPT_FUNC(pthread_join
);
653 // Intercept atexit function.
654 #if ASAN_INTERCEPT___CXA_ATEXIT
655 ASAN_INTERCEPT_FUNC(__cxa_atexit
);
658 InitializePlatformInterceptors();
660 VReport(1, "AddressSanitizer: libc interceptors initialized\n");
663 } // namespace __asan
665 #endif // !SANITIZER_FUCHSIA