1 //===-- asan_interceptors.cpp ---------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file is a part of AddressSanitizer, an address sanity checker.
11 // Intercept various libc functions.
12 //===----------------------------------------------------------------------===//
14 #include "asan_interceptors.h"
16 #include "asan_allocator.h"
17 #include "asan_internal.h"
18 #include "asan_mapping.h"
19 #include "asan_poisoning.h"
20 #include "asan_report.h"
21 #include "asan_stack.h"
22 #include "asan_stats.h"
23 #include "asan_suppressions.h"
24 #include "asan_thread.h"
25 #include "lsan/lsan_common.h"
26 #include "sanitizer_common/sanitizer_errno.h"
27 #include "sanitizer_common/sanitizer_internal_defs.h"
28 #include "sanitizer_common/sanitizer_libc.h"
30 // There is no general interception at all on Fuchsia.
31 // Only the functions in asan_interceptors_memintrinsics.cpp are
32 // really defined to replace libc functions.
33 #if !SANITIZER_FUCHSIA
36 # include "sanitizer_common/sanitizer_posix.h"
39 # if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION || \
40 ASAN_INTERCEPT__SJLJ_UNWIND_RAISEEXCEPTION
44 # if defined(__i386) && SANITIZER_LINUX
45 # define ASAN_PTHREAD_CREATE_VERSION "GLIBC_2.1"
46 # elif defined(__mips__) && SANITIZER_LINUX
47 # define ASAN_PTHREAD_CREATE_VERSION "GLIBC_2.2"
52 #define ASAN_READ_STRING_OF_LEN(ctx, s, len, n) \
53 ASAN_READ_RANGE((ctx), (s), \
54 common_flags()->strict_string_checks ? (len) + 1 : (n))
56 # define ASAN_READ_STRING(ctx, s, n) \
57 ASAN_READ_STRING_OF_LEN((ctx), (s), internal_strlen(s), (n))
59 static inline uptr
MaybeRealStrnlen(const char *s
, uptr maxlen
) {
60 #if SANITIZER_INTERCEPT_STRNLEN
62 return REAL(strnlen
)(s
, maxlen
);
65 return internal_strnlen(s
, maxlen
);
68 void SetThreadName(const char *name
) {
69 AsanThread
*t
= GetCurrentThread();
71 asanThreadRegistry().SetThreadName(t
->tid(), name
);
75 if (CAN_SANITIZE_LEAKS
&& common_flags()->detect_leaks
&&
76 __lsan::HasReportedLeaks()) {
77 return common_flags()->exitcode
;
79 // FIXME: ask frontend whether we need to return failure.
85 // ---------------------- Wrappers ---------------- {{{1
86 using namespace __asan
;
88 DECLARE_REAL_AND_INTERCEPTOR(void *, malloc
, uptr
)
89 DECLARE_REAL_AND_INTERCEPTOR(void, free
, void *)
91 #define COMMON_INTERCEPT_FUNCTION_VER(name, ver) \
92 ASAN_INTERCEPT_FUNC_VER(name, ver)
93 #define COMMON_INTERCEPT_FUNCTION_VER_UNVERSIONED_FALLBACK(name, ver) \
94 ASAN_INTERCEPT_FUNC_VER_UNVERSIONED_FALLBACK(name, ver)
95 #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
96 ASAN_WRITE_RANGE(ctx, ptr, size)
97 #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
98 ASAN_READ_RANGE(ctx, ptr, size)
99 #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
100 ASAN_INTERCEPTOR_ENTER(ctx, func); \
102 if (asan_init_is_running) \
103 return REAL(func)(__VA_ARGS__); \
104 if (SANITIZER_APPLE && UNLIKELY(!asan_inited)) \
105 return REAL(func)(__VA_ARGS__); \
106 ENSURE_ASAN_INITED(); \
108 #define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \
111 #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
114 #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
117 #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
120 #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name)
121 // Should be asanThreadRegistry().SetThreadNameByUserId(thread, name)
122 // But asan does not remember UserId's for threads (pthread_t);
123 // and remembers all ever existed threads, so the linear search by UserId
125 #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
128 #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
129 // Strict init-order checking is dlopen-hostile:
130 // https://github.com/google/sanitizers/issues/178
131 # define COMMON_INTERCEPTOR_DLOPEN(filename, flag) \
133 if (flags()->strict_init_order) \
134 StopInitOrderChecking(); \
135 CheckNoDeepBind(filename, flag); \
136 REAL(dlopen)(filename, flag); \
138 # define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
139 # define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle)
140 # define COMMON_INTERCEPTOR_LIBRARY_UNLOADED()
141 # define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!asan_inited)
142 # define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \
143 if (AsanThread *t = GetCurrentThread()) { \
144 *begin = t->tls_begin(); \
145 *end = t->tls_end(); \
150 template <class Mmap
>
151 static void* mmap_interceptor(Mmap real_mmap
, void *addr
, SIZE_T length
,
152 int prot
, int flags
, int fd
, OFF64_T offset
) {
153 void *res
= real_mmap(addr
, length
, prot
, flags
, fd
, offset
);
154 if (length
&& res
!= (void *)-1) {
155 const uptr beg
= reinterpret_cast<uptr
>(res
);
156 DCHECK(IsAligned(beg
, GetPageSize()));
157 SIZE_T rounded_length
= RoundUpTo(length
, GetPageSize());
158 // Only unpoison shadow if it's an ASAN managed address.
159 if (AddrIsInMem(beg
) && AddrIsInMem(beg
+ rounded_length
- 1))
160 PoisonShadow(beg
, RoundUpTo(length
, GetPageSize()), 0);
165 template <class Munmap
>
166 static int munmap_interceptor(Munmap real_munmap
, void *addr
, SIZE_T length
) {
167 // We should not tag if munmap fail, but it's to late to tag after
168 // real_munmap, as the pages could be mmaped by another thread.
169 const uptr beg
= reinterpret_cast<uptr
>(addr
);
170 if (length
&& IsAligned(beg
, GetPageSize())) {
171 SIZE_T rounded_length
= RoundUpTo(length
, GetPageSize());
172 // Protect from unmapping the shadow.
173 if (AddrIsInMem(beg
) && AddrIsInMem(beg
+ rounded_length
- 1))
174 PoisonShadow(beg
, rounded_length
, 0);
176 return real_munmap(addr
, length
);
179 # define COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, length, prot, flags, \
183 return mmap_interceptor(REAL(mmap), addr, sz, prot, flags, fd, off); \
186 # define COMMON_INTERCEPTOR_MUNMAP_IMPL(ctx, addr, length) \
189 return munmap_interceptor(REAL(munmap), addr, sz); \
192 #if CAN_SANITIZE_LEAKS
193 #define COMMON_INTERCEPTOR_STRERROR() \
194 __lsan::ScopedInterceptorDisabler disabler
197 #define SIGNAL_INTERCEPTOR_ENTER() ENSURE_ASAN_INITED()
199 #include "sanitizer_common/sanitizer_common_interceptors.inc"
200 #include "sanitizer_common/sanitizer_signal_interceptors.inc"
202 // Syscall interceptors don't have contexts, we don't support suppressions
204 #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) ASAN_READ_RANGE(nullptr, p, s)
205 #define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) ASAN_WRITE_RANGE(nullptr, p, s)
206 #define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
211 #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \
216 #include "sanitizer_common/sanitizer_common_syscalls.inc"
217 #include "sanitizer_common/sanitizer_syscalls_netbsd.inc"
219 #if ASAN_INTERCEPT_PTHREAD_CREATE
220 static thread_return_t THREAD_CALLING_CONV
asan_thread_start(void *arg
) {
221 AsanThread
*t
= (AsanThread
*)arg
;
223 auto self
= GetThreadSelf();
224 auto args
= asanThreadArgRetval().GetArgs(self
);
225 t
->ThreadStart(GetTid());
227 # if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
229 __sanitizer_sigset_t sigset
;
230 t
->GetStartData(sigset
);
231 SetSigProcMask(&sigset
, nullptr);
234 thread_return_t retval
= (*args
.routine
)(args
.arg_retval
);
235 asanThreadArgRetval().Finish(self
, retval
);
239 INTERCEPTOR(int, pthread_create
, void *thread
, void *attr
,
240 void *(*start_routine
)(void *), void *arg
) {
241 EnsureMainThreadIDIsCorrect();
242 // Strict init-order checking is thread-hostile.
243 if (flags()->strict_init_order
)
244 StopInitOrderChecking();
245 GET_STACK_TRACE_THREAD
;
246 bool detached
= [attr
]() {
248 return attr
&& !REAL(pthread_attr_getdetachstate
)(attr
, &d
) &&
252 u32 current_tid
= GetCurrentTidOrInvalid();
254 __sanitizer_sigset_t sigset
= {};
255 # if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
257 ScopedBlockSignals
block(&sigset
);
260 AsanThread
*t
= AsanThread::Create(sigset
, current_tid
, &stack
, detached
);
264 // Ignore all allocations made by pthread_create: thread stack/TLS may be
265 // stored by pthread for future reuse even after thread destruction, and
266 // the linked list it's stored in doesn't even hold valid pointers to the
267 // objects, the latter are calculated by obscure pointer arithmetic.
268 # if CAN_SANITIZE_LEAKS
269 __lsan::ScopedInterceptorDisabler disabler
;
271 asanThreadArgRetval().Create(detached
, {start_routine
, arg
}, [&]() -> uptr
{
272 result
= REAL(pthread_create
)(thread
, attr
, asan_thread_start
, t
);
273 return result
? 0 : *(uptr
*)(thread
);
277 // If the thread didn't start delete the AsanThread to avoid leaking it.
278 // Note AsanThreadContexts never get destroyed so the AsanThreadContext
279 // that was just created for the AsanThread is wasted.
285 INTERCEPTOR(int, pthread_join
, void *thread
, void **retval
) {
287 asanThreadArgRetval().Join((uptr
)thread
, [&]() {
288 result
= REAL(pthread_join
)(thread
, retval
);
294 INTERCEPTOR(int, pthread_detach
, void *thread
) {
296 asanThreadArgRetval().Detach((uptr
)thread
, [&]() {
297 result
= REAL(pthread_detach
)(thread
);
303 INTERCEPTOR(int, pthread_exit
, void *retval
) {
304 asanThreadArgRetval().Finish(GetThreadSelf(), retval
);
305 return REAL(pthread_exit
)(retval
);
308 # if ASAN_INTERCEPT_TRYJOIN
309 INTERCEPTOR(int, pthread_tryjoin_np
, void *thread
, void **ret
) {
311 asanThreadArgRetval().Join((uptr
)thread
, [&]() {
312 result
= REAL(pthread_tryjoin_np
)(thread
, ret
);
319 # if ASAN_INTERCEPT_TIMEDJOIN
320 INTERCEPTOR(int, pthread_timedjoin_np
, void *thread
, void **ret
,
321 const struct timespec
*abstime
) {
323 asanThreadArgRetval().Join((uptr
)thread
, [&]() {
324 result
= REAL(pthread_timedjoin_np
)(thread
, ret
, abstime
);
331 DEFINE_REAL_PTHREAD_FUNCTIONS
332 #endif // ASAN_INTERCEPT_PTHREAD_CREATE
334 #if ASAN_INTERCEPT_SWAPCONTEXT
335 static void ClearShadowMemoryForContextStack(uptr stack
, uptr ssize
) {
336 // Only clear if we know the stack. This should be true only for contexts
337 // created with makecontext().
340 // Align to page size.
341 uptr PageSize
= GetPageSizeCached();
342 uptr bottom
= RoundDownTo(stack
, PageSize
);
343 if (!AddrIsInMem(bottom
))
345 ssize
+= stack
- bottom
;
346 ssize
= RoundUpTo(ssize
, PageSize
);
347 PoisonShadow(bottom
, ssize
, 0);
350 INTERCEPTOR(void, makecontext
, struct ucontext_t
*ucp
, void (*func
)(), int argc
,
354 // We don't know a better way to forward ... into REAL function. We can
355 // increase args size if neccecary.
356 CHECK_LE(argc
, ARRAY_SIZE(args
));
357 internal_memset(args
, 0, sizeof(args
));
359 for (int i
= 0; i
< argc
; ++i
) args
[i
] = va_arg(ap
, uptr
);
362 # define ENUMERATE_ARRAY_4(start) \
363 args[start], args[start + 1], args[start + 2], args[start + 3]
364 # define ENUMERATE_ARRAY_16(start) \
365 ENUMERATE_ARRAY_4(start), ENUMERATE_ARRAY_4(start + 4), \
366 ENUMERATE_ARRAY_4(start + 8), ENUMERATE_ARRAY_4(start + 12)
367 # define ENUMERATE_ARRAY_64() \
368 ENUMERATE_ARRAY_16(0), ENUMERATE_ARRAY_16(16), ENUMERATE_ARRAY_16(32), \
369 ENUMERATE_ARRAY_16(48)
372 ((struct ucontext_t
*)ucp
, func
, argc
, ENUMERATE_ARRAY_64());
374 # undef ENUMERATE_ARRAY_4
375 # undef ENUMERATE_ARRAY_16
376 # undef ENUMERATE_ARRAY_64
378 // Sign the stack so we can identify it for unpoisoning.
379 SignContextStack(ucp
);
382 INTERCEPTOR(int, swapcontext
, struct ucontext_t
*oucp
,
383 struct ucontext_t
*ucp
) {
384 static bool reported_warning
= false;
385 if (!reported_warning
) {
386 Report("WARNING: ASan doesn't fully support makecontext/swapcontext "
387 "functions and may produce false positives in some cases!\n");
388 reported_warning
= true;
390 // Clear shadow memory for new context (it may share stack
391 // with current context).
393 ReadContextStack(ucp
, &stack
, &ssize
);
394 ClearShadowMemoryForContextStack(stack
, ssize
);
396 # if __has_attribute(__indirect_return__) && \
397 (defined(__x86_64__) || defined(__i386__))
398 int (*real_swapcontext
)(struct ucontext_t
*, struct ucontext_t
*)
399 __attribute__((__indirect_return__
)) = REAL(swapcontext
);
400 int res
= real_swapcontext(oucp
, ucp
);
402 int res
= REAL(swapcontext
)(oucp
, ucp
);
404 // swapcontext technically does not return, but program may swap context to
405 // "oucp" later, that would look as if swapcontext() returned 0.
406 // We need to clear shadow for ucp once again, as it may be in arbitrary
408 ClearShadowMemoryForContextStack(stack
, ssize
);
411 #endif // ASAN_INTERCEPT_SWAPCONTEXT
414 #define longjmp __longjmp14
415 #define siglongjmp __siglongjmp14
418 INTERCEPTOR(void, longjmp
, void *env
, int val
) {
419 __asan_handle_no_return();
420 REAL(longjmp
)(env
, val
);
423 #if ASAN_INTERCEPT__LONGJMP
424 INTERCEPTOR(void, _longjmp
, void *env
, int val
) {
425 __asan_handle_no_return();
426 REAL(_longjmp
)(env
, val
);
430 #if ASAN_INTERCEPT___LONGJMP_CHK
431 INTERCEPTOR(void, __longjmp_chk
, void *env
, int val
) {
432 __asan_handle_no_return();
433 REAL(__longjmp_chk
)(env
, val
);
437 #if ASAN_INTERCEPT_SIGLONGJMP
438 INTERCEPTOR(void, siglongjmp
, void *env
, int val
) {
439 __asan_handle_no_return();
440 REAL(siglongjmp
)(env
, val
);
444 #if ASAN_INTERCEPT___CXA_THROW
445 INTERCEPTOR(void, __cxa_throw
, void *a
, void *b
, void *c
) {
446 CHECK(REAL(__cxa_throw
));
447 __asan_handle_no_return();
448 REAL(__cxa_throw
)(a
, b
, c
);
452 #if ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION
453 INTERCEPTOR(void, __cxa_rethrow_primary_exception
, void *a
) {
454 CHECK(REAL(__cxa_rethrow_primary_exception
));
455 __asan_handle_no_return();
456 REAL(__cxa_rethrow_primary_exception
)(a
);
460 #if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION
461 INTERCEPTOR(_Unwind_Reason_Code
, _Unwind_RaiseException
,
462 _Unwind_Exception
*object
) {
463 CHECK(REAL(_Unwind_RaiseException
));
464 __asan_handle_no_return();
465 return REAL(_Unwind_RaiseException
)(object
);
469 #if ASAN_INTERCEPT__SJLJ_UNWIND_RAISEEXCEPTION
470 INTERCEPTOR(_Unwind_Reason_Code
, _Unwind_SjLj_RaiseException
,
471 _Unwind_Exception
*object
) {
472 CHECK(REAL(_Unwind_SjLj_RaiseException
));
473 __asan_handle_no_return();
474 return REAL(_Unwind_SjLj_RaiseException
)(object
);
478 #if ASAN_INTERCEPT_INDEX
479 # if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
480 INTERCEPTOR(char*, index
, const char *string
, int c
)
484 DECLARE_REAL(char*, index
, const char *string
, int c
)
485 OVERRIDE_FUNCTION(index
, strchr
);
487 DEFINE_REAL(char*, index
, const char *string
, int c
)
490 #endif // ASAN_INTERCEPT_INDEX
492 // For both strcat() and strncat() we need to check the validity of |to|
493 // argument irrespective of the |from| length.
494 INTERCEPTOR(char *, strcat
, char *to
, const char *from
) {
496 ASAN_INTERCEPTOR_ENTER(ctx
, strcat
);
497 ENSURE_ASAN_INITED();
498 if (flags()->replace_str
) {
499 uptr from_length
= internal_strlen(from
);
500 ASAN_READ_RANGE(ctx
, from
, from_length
+ 1);
501 uptr to_length
= internal_strlen(to
);
502 ASAN_READ_STRING_OF_LEN(ctx
, to
, to_length
, to_length
);
503 ASAN_WRITE_RANGE(ctx
, to
+ to_length
, from_length
+ 1);
504 // If the copying actually happens, the |from| string should not overlap
505 // with the resulting string starting at |to|, which has a length of
506 // to_length + from_length + 1.
507 if (from_length
> 0) {
508 CHECK_RANGES_OVERLAP("strcat", to
, from_length
+ to_length
+ 1, from
,
512 return REAL(strcat
)(to
, from
);
515 INTERCEPTOR(char*, strncat
, char *to
, const char *from
, uptr size
) {
517 ASAN_INTERCEPTOR_ENTER(ctx
, strncat
);
518 ENSURE_ASAN_INITED();
519 if (flags()->replace_str
) {
520 uptr from_length
= MaybeRealStrnlen(from
, size
);
521 uptr copy_length
= Min(size
, from_length
+ 1);
522 ASAN_READ_RANGE(ctx
, from
, copy_length
);
523 uptr to_length
= internal_strlen(to
);
524 ASAN_READ_STRING_OF_LEN(ctx
, to
, to_length
, to_length
);
525 ASAN_WRITE_RANGE(ctx
, to
+ to_length
, from_length
+ 1);
526 if (from_length
> 0) {
527 CHECK_RANGES_OVERLAP("strncat", to
, to_length
+ copy_length
+ 1,
531 return REAL(strncat
)(to
, from
, size
);
534 INTERCEPTOR(char *, strcpy
, char *to
, const char *from
) {
536 ASAN_INTERCEPTOR_ENTER(ctx
, strcpy
);
538 if (UNLIKELY(!asan_inited
))
539 return REAL(strcpy
)(to
, from
);
541 // strcpy is called from malloc_default_purgeable_zone()
542 // in __asan::ReplaceSystemAlloc() on Mac.
543 if (asan_init_is_running
) {
544 return REAL(strcpy
)(to
, from
);
546 ENSURE_ASAN_INITED();
547 if (flags()->replace_str
) {
548 uptr from_size
= internal_strlen(from
) + 1;
549 CHECK_RANGES_OVERLAP("strcpy", to
, from_size
, from
, from_size
);
550 ASAN_READ_RANGE(ctx
, from
, from_size
);
551 ASAN_WRITE_RANGE(ctx
, to
, from_size
);
553 return REAL(strcpy
)(to
, from
);
556 INTERCEPTOR(char*, strdup
, const char *s
) {
558 ASAN_INTERCEPTOR_ENTER(ctx
, strdup
);
559 if (UNLIKELY(!asan_inited
)) return internal_strdup(s
);
560 ENSURE_ASAN_INITED();
561 uptr length
= internal_strlen(s
);
562 if (flags()->replace_str
) {
563 ASAN_READ_RANGE(ctx
, s
, length
+ 1);
565 GET_STACK_TRACE_MALLOC
;
566 void *new_mem
= asan_malloc(length
+ 1, &stack
);
568 REAL(memcpy
)(new_mem
, s
, length
+ 1);
570 return reinterpret_cast<char*>(new_mem
);
573 #if ASAN_INTERCEPT___STRDUP
574 INTERCEPTOR(char*, __strdup
, const char *s
) {
576 ASAN_INTERCEPTOR_ENTER(ctx
, strdup
);
577 if (UNLIKELY(!asan_inited
)) return internal_strdup(s
);
578 ENSURE_ASAN_INITED();
579 uptr length
= internal_strlen(s
);
580 if (flags()->replace_str
) {
581 ASAN_READ_RANGE(ctx
, s
, length
+ 1);
583 GET_STACK_TRACE_MALLOC
;
584 void *new_mem
= asan_malloc(length
+ 1, &stack
);
586 REAL(memcpy
)(new_mem
, s
, length
+ 1);
588 return reinterpret_cast<char*>(new_mem
);
590 #endif // ASAN_INTERCEPT___STRDUP
592 INTERCEPTOR(char*, strncpy
, char *to
, const char *from
, uptr size
) {
594 ASAN_INTERCEPTOR_ENTER(ctx
, strncpy
);
595 ENSURE_ASAN_INITED();
596 if (flags()->replace_str
) {
597 uptr from_size
= Min(size
, MaybeRealStrnlen(from
, size
) + 1);
598 CHECK_RANGES_OVERLAP("strncpy", to
, from_size
, from
, from_size
);
599 ASAN_READ_RANGE(ctx
, from
, from_size
);
600 ASAN_WRITE_RANGE(ctx
, to
, size
);
602 return REAL(strncpy
)(to
, from
, size
);
605 template <typename Fn
>
606 static ALWAYS_INLINE
auto StrtolImpl(void *ctx
, Fn real
, const char *nptr
,
607 char **endptr
, int base
)
608 -> decltype(real(nullptr, nullptr, 0)) {
609 if (!flags()->replace_str
)
610 return real(nptr
, endptr
, base
);
612 auto res
= real(nptr
, &real_endptr
, base
);
613 StrtolFixAndCheck(ctx
, nptr
, endptr
, real_endptr
, base
);
617 # define INTERCEPTOR_STRTO_BASE(ret_type, func) \
618 INTERCEPTOR(ret_type, func, const char *nptr, char **endptr, int base) { \
620 ASAN_INTERCEPTOR_ENTER(ctx, func); \
621 ENSURE_ASAN_INITED(); \
622 return StrtolImpl(ctx, REAL(func), nptr, endptr, base); \
625 INTERCEPTOR_STRTO_BASE(long, strtol
)
626 INTERCEPTOR_STRTO_BASE(long long, strtoll
)
629 INTERCEPTOR_STRTO_BASE(long, __isoc23_strtol
)
630 INTERCEPTOR_STRTO_BASE(long long, __isoc23_strtoll
)
633 INTERCEPTOR(int, atoi
, const char *nptr
) {
635 ASAN_INTERCEPTOR_ENTER(ctx
, atoi
);
637 if (UNLIKELY(!asan_inited
)) return REAL(atoi
)(nptr
);
639 ENSURE_ASAN_INITED();
640 if (!flags()->replace_str
) {
641 return REAL(atoi
)(nptr
);
644 // "man atoi" tells that behavior of atoi(nptr) is the same as
645 // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
646 // parsed integer can't be stored in *long* type (even if it's
647 // different from int). So, we just imitate this behavior.
648 int result
= REAL(strtol
)(nptr
, &real_endptr
, 10);
649 FixRealStrtolEndptr(nptr
, &real_endptr
);
650 ASAN_READ_STRING(ctx
, nptr
, (real_endptr
- nptr
) + 1);
654 INTERCEPTOR(long, atol
, const char *nptr
) {
656 ASAN_INTERCEPTOR_ENTER(ctx
, atol
);
658 if (UNLIKELY(!asan_inited
)) return REAL(atol
)(nptr
);
660 ENSURE_ASAN_INITED();
661 if (!flags()->replace_str
) {
662 return REAL(atol
)(nptr
);
665 long result
= REAL(strtol
)(nptr
, &real_endptr
, 10);
666 FixRealStrtolEndptr(nptr
, &real_endptr
);
667 ASAN_READ_STRING(ctx
, nptr
, (real_endptr
- nptr
) + 1);
671 INTERCEPTOR(long long, atoll
, const char *nptr
) {
673 ASAN_INTERCEPTOR_ENTER(ctx
, atoll
);
674 ENSURE_ASAN_INITED();
675 if (!flags()->replace_str
) {
676 return REAL(atoll
)(nptr
);
679 long long result
= REAL(strtoll
)(nptr
, &real_endptr
, 10);
680 FixRealStrtolEndptr(nptr
, &real_endptr
);
681 ASAN_READ_STRING(ctx
, nptr
, (real_endptr
- nptr
) + 1);
685 #if ASAN_INTERCEPT___CXA_ATEXIT || ASAN_INTERCEPT_ATEXIT
686 static void AtCxaAtexit(void *unused
) {
688 StopInitOrderChecking();
692 #if ASAN_INTERCEPT___CXA_ATEXIT
693 INTERCEPTOR(int, __cxa_atexit
, void (*func
)(void *), void *arg
,
696 if (UNLIKELY(!asan_inited
)) return REAL(__cxa_atexit
)(func
, arg
, dso_handle
);
698 ENSURE_ASAN_INITED();
699 #if CAN_SANITIZE_LEAKS
700 __lsan::ScopedInterceptorDisabler disabler
;
702 int res
= REAL(__cxa_atexit
)(func
, arg
, dso_handle
);
703 REAL(__cxa_atexit
)(AtCxaAtexit
, nullptr, nullptr);
706 #endif // ASAN_INTERCEPT___CXA_ATEXIT
708 #if ASAN_INTERCEPT_ATEXIT
709 INTERCEPTOR(int, atexit
, void (*func
)()) {
710 ENSURE_ASAN_INITED();
711 #if CAN_SANITIZE_LEAKS
712 __lsan::ScopedInterceptorDisabler disabler
;
714 // Avoid calling real atexit as it is unreachable on at least on Linux.
715 int res
= REAL(__cxa_atexit
)((void (*)(void *a
))func
, nullptr, nullptr);
716 REAL(__cxa_atexit
)(AtCxaAtexit
, nullptr, nullptr);
721 #if ASAN_INTERCEPT_PTHREAD_ATFORK
723 extern int _pthread_atfork(void (*prepare
)(), void (*parent
)(),
727 INTERCEPTOR(int, pthread_atfork
, void (*prepare
)(), void (*parent
)(),
729 #if CAN_SANITIZE_LEAKS
730 __lsan::ScopedInterceptorDisabler disabler
;
732 // REAL(pthread_atfork) cannot be called due to symbol indirections at least
734 return _pthread_atfork(prepare
, parent
, child
);
738 #if ASAN_INTERCEPT_VFORK
739 DEFINE_REAL(int, vfork
)
740 DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(int, vfork
)
743 // ---------------------- InitializeAsanInterceptors ---------------- {{{1
745 void InitializeAsanInterceptors() {
746 static bool was_called_once
;
747 CHECK(!was_called_once
);
748 was_called_once
= true;
749 InitializePlatformInterceptors();
750 InitializeCommonInterceptors();
751 InitializeSignalInterceptors();
753 // Intercept str* functions.
754 ASAN_INTERCEPT_FUNC(strcat
);
755 ASAN_INTERCEPT_FUNC(strcpy
);
756 ASAN_INTERCEPT_FUNC(strncat
);
757 ASAN_INTERCEPT_FUNC(strncpy
);
758 ASAN_INTERCEPT_FUNC(strdup
);
759 #if ASAN_INTERCEPT___STRDUP
760 ASAN_INTERCEPT_FUNC(__strdup
);
762 #if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
763 ASAN_INTERCEPT_FUNC(index
);
766 ASAN_INTERCEPT_FUNC(atoi
);
767 ASAN_INTERCEPT_FUNC(atol
);
768 ASAN_INTERCEPT_FUNC(atoll
);
769 ASAN_INTERCEPT_FUNC(strtol
);
770 ASAN_INTERCEPT_FUNC(strtoll
);
772 ASAN_INTERCEPT_FUNC(__isoc23_strtol
);
773 ASAN_INTERCEPT_FUNC(__isoc23_strtoll
);
776 // Intecept jump-related functions.
777 ASAN_INTERCEPT_FUNC(longjmp
);
779 # if ASAN_INTERCEPT_SWAPCONTEXT
780 ASAN_INTERCEPT_FUNC(swapcontext
);
781 ASAN_INTERCEPT_FUNC(makecontext
);
783 # if ASAN_INTERCEPT__LONGJMP
784 ASAN_INTERCEPT_FUNC(_longjmp
);
786 #if ASAN_INTERCEPT___LONGJMP_CHK
787 ASAN_INTERCEPT_FUNC(__longjmp_chk
);
789 #if ASAN_INTERCEPT_SIGLONGJMP
790 ASAN_INTERCEPT_FUNC(siglongjmp
);
793 // Intercept exception handling functions.
794 #if ASAN_INTERCEPT___CXA_THROW
795 ASAN_INTERCEPT_FUNC(__cxa_throw
);
797 #if ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION
798 ASAN_INTERCEPT_FUNC(__cxa_rethrow_primary_exception
);
800 // Indirectly intercept std::rethrow_exception.
801 #if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION
802 ASAN_INTERCEPT_FUNC(_Unwind_RaiseException
);
804 // Indirectly intercept std::rethrow_exception.
805 #if ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION
806 ASAN_INTERCEPT_FUNC(_Unwind_SjLj_RaiseException
);
809 // Intercept threading-related functions
810 #if ASAN_INTERCEPT_PTHREAD_CREATE
811 // TODO: this should probably have an unversioned fallback for newer arches?
812 #if defined(ASAN_PTHREAD_CREATE_VERSION)
813 ASAN_INTERCEPT_FUNC_VER(pthread_create
, ASAN_PTHREAD_CREATE_VERSION
);
815 ASAN_INTERCEPT_FUNC(pthread_create
);
817 ASAN_INTERCEPT_FUNC(pthread_join
);
818 ASAN_INTERCEPT_FUNC(pthread_detach
);
819 ASAN_INTERCEPT_FUNC(pthread_exit
);
822 # if ASAN_INTERCEPT_TIMEDJOIN
823 ASAN_INTERCEPT_FUNC(pthread_timedjoin_np
);
826 #if ASAN_INTERCEPT_TRYJOIN
827 ASAN_INTERCEPT_FUNC(pthread_tryjoin_np
);
830 // Intercept atexit function.
831 #if ASAN_INTERCEPT___CXA_ATEXIT
832 ASAN_INTERCEPT_FUNC(__cxa_atexit
);
835 #if ASAN_INTERCEPT_ATEXIT
836 ASAN_INTERCEPT_FUNC(atexit
);
839 #if ASAN_INTERCEPT_PTHREAD_ATFORK
840 ASAN_INTERCEPT_FUNC(pthread_atfork
);
843 #if ASAN_INTERCEPT_VFORK
844 ASAN_INTERCEPT_FUNC(vfork
);
847 VReport(1, "AddressSanitizer: libc interceptors initialized\n");
850 } // namespace __asan
852 #endif // !SANITIZER_FUCHSIA