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 constexpr (SANITIZER_APPLE) { \
103 if (UNLIKELY(!AsanInited())) \
104 return REAL(func)(__VA_ARGS__); \
106 if (!TryAsanInitFromRtl()) \
107 return REAL(func)(__VA_ARGS__); \
110 #define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \
113 #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
116 #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
119 #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
122 #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name)
123 // Should be asanThreadRegistry().SetThreadNameByUserId(thread, name)
124 // But asan does not remember UserId's for threads (pthread_t);
125 // and remembers all ever existed threads, so the linear search by UserId
127 #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
130 #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
131 // Strict init-order checking is dlopen-hostile:
132 // https://github.com/google/sanitizers/issues/178
133 # define COMMON_INTERCEPTOR_DLOPEN(filename, flag) \
135 if (flags()->strict_init_order) \
136 StopInitOrderChecking(); \
137 CheckNoDeepBind(filename, flag); \
138 REAL(dlopen)(filename, flag); \
140 # define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
141 # define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle)
142 # define COMMON_INTERCEPTOR_LIBRARY_UNLOADED()
143 # define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!AsanInited())
144 # define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \
145 if (AsanThread *t = GetCurrentThread()) { \
146 *begin = t->tls_begin(); \
147 *end = t->tls_end(); \
152 template <class Mmap
>
153 static void* mmap_interceptor(Mmap real_mmap
, void *addr
, SIZE_T length
,
154 int prot
, int flags
, int fd
, OFF64_T offset
) {
155 void *res
= real_mmap(addr
, length
, prot
, flags
, fd
, offset
);
156 if (length
&& res
!= (void *)-1) {
157 const uptr beg
= reinterpret_cast<uptr
>(res
);
158 DCHECK(IsAligned(beg
, GetPageSize()));
159 SIZE_T rounded_length
= RoundUpTo(length
, GetPageSize());
160 // Only unpoison shadow if it's an ASAN managed address.
161 if (AddrIsInMem(beg
) && AddrIsInMem(beg
+ rounded_length
- 1))
162 PoisonShadow(beg
, RoundUpTo(length
, GetPageSize()), 0);
167 template <class Munmap
>
168 static int munmap_interceptor(Munmap real_munmap
, void *addr
, SIZE_T length
) {
169 // We should not tag if munmap fail, but it's to late to tag after
170 // real_munmap, as the pages could be mmaped by another thread.
171 const uptr beg
= reinterpret_cast<uptr
>(addr
);
172 if (length
&& IsAligned(beg
, GetPageSize())) {
173 SIZE_T rounded_length
= RoundUpTo(length
, GetPageSize());
174 // Protect from unmapping the shadow.
175 if (AddrIsInMem(beg
) && AddrIsInMem(beg
+ rounded_length
- 1))
176 PoisonShadow(beg
, rounded_length
, 0);
178 return real_munmap(addr
, length
);
181 # define COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, length, prot, flags, \
185 return mmap_interceptor(REAL(mmap), addr, sz, prot, flags, fd, off); \
188 # define COMMON_INTERCEPTOR_MUNMAP_IMPL(ctx, addr, length) \
191 return munmap_interceptor(REAL(munmap), addr, sz); \
194 #if CAN_SANITIZE_LEAKS
195 #define COMMON_INTERCEPTOR_STRERROR() \
196 __lsan::ScopedInterceptorDisabler disabler
199 # define SIGNAL_INTERCEPTOR_ENTER() \
204 # include "sanitizer_common/sanitizer_common_interceptors.inc"
205 # include "sanitizer_common/sanitizer_signal_interceptors.inc"
207 // Syscall interceptors don't have contexts, we don't support suppressions
209 #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) ASAN_READ_RANGE(nullptr, p, s)
210 #define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) ASAN_WRITE_RANGE(nullptr, p, s)
211 #define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
216 #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \
221 #include "sanitizer_common/sanitizer_common_syscalls.inc"
222 #include "sanitizer_common/sanitizer_syscalls_netbsd.inc"
224 #if ASAN_INTERCEPT_PTHREAD_CREATE
225 static thread_return_t THREAD_CALLING_CONV
asan_thread_start(void *arg
) {
226 AsanThread
*t
= (AsanThread
*)arg
;
228 auto self
= GetThreadSelf();
229 auto args
= asanThreadArgRetval().GetArgs(self
);
230 t
->ThreadStart(GetTid());
232 # if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
234 __sanitizer_sigset_t sigset
;
235 t
->GetStartData(sigset
);
236 SetSigProcMask(&sigset
, nullptr);
239 thread_return_t retval
= (*args
.routine
)(args
.arg_retval
);
240 asanThreadArgRetval().Finish(self
, retval
);
244 INTERCEPTOR(int, pthread_create
, void *thread
, void *attr
,
245 void *(*start_routine
)(void *), void *arg
) {
246 EnsureMainThreadIDIsCorrect();
247 // Strict init-order checking is thread-hostile.
248 if (flags()->strict_init_order
)
249 StopInitOrderChecking();
250 GET_STACK_TRACE_THREAD
;
251 bool detached
= [attr
]() {
253 return attr
&& !REAL(pthread_attr_getdetachstate
)(attr
, &d
) &&
257 u32 current_tid
= GetCurrentTidOrInvalid();
259 __sanitizer_sigset_t sigset
= {};
260 # if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
262 ScopedBlockSignals
block(&sigset
);
265 AsanThread
*t
= AsanThread::Create(sigset
, current_tid
, &stack
, detached
);
269 // Ignore all allocations made by pthread_create: thread stack/TLS may be
270 // stored by pthread for future reuse even after thread destruction, and
271 // the linked list it's stored in doesn't even hold valid pointers to the
272 // objects, the latter are calculated by obscure pointer arithmetic.
273 # if CAN_SANITIZE_LEAKS
274 __lsan::ScopedInterceptorDisabler disabler
;
276 asanThreadArgRetval().Create(detached
, {start_routine
, arg
}, [&]() -> uptr
{
277 result
= REAL(pthread_create
)(thread
, attr
, asan_thread_start
, t
);
278 return result
? 0 : *(uptr
*)(thread
);
282 // If the thread didn't start delete the AsanThread to avoid leaking it.
283 // Note AsanThreadContexts never get destroyed so the AsanThreadContext
284 // that was just created for the AsanThread is wasted.
290 INTERCEPTOR(int, pthread_join
, void *thread
, void **retval
) {
292 asanThreadArgRetval().Join((uptr
)thread
, [&]() {
293 result
= REAL(pthread_join
)(thread
, retval
);
299 INTERCEPTOR(int, pthread_detach
, void *thread
) {
301 asanThreadArgRetval().Detach((uptr
)thread
, [&]() {
302 result
= REAL(pthread_detach
)(thread
);
308 INTERCEPTOR(void, pthread_exit
, void *retval
) {
309 asanThreadArgRetval().Finish(GetThreadSelf(), retval
);
310 REAL(pthread_exit
)(retval
);
313 # if ASAN_INTERCEPT_TRYJOIN
314 INTERCEPTOR(int, pthread_tryjoin_np
, void *thread
, void **ret
) {
316 asanThreadArgRetval().Join((uptr
)thread
, [&]() {
317 result
= REAL(pthread_tryjoin_np
)(thread
, ret
);
324 # if ASAN_INTERCEPT_TIMEDJOIN
325 INTERCEPTOR(int, pthread_timedjoin_np
, void *thread
, void **ret
,
326 const struct timespec
*abstime
) {
328 asanThreadArgRetval().Join((uptr
)thread
, [&]() {
329 result
= REAL(pthread_timedjoin_np
)(thread
, ret
, abstime
);
336 DEFINE_INTERNAL_PTHREAD_FUNCTIONS
337 #endif // ASAN_INTERCEPT_PTHREAD_CREATE
339 #if ASAN_INTERCEPT_SWAPCONTEXT
340 static void ClearShadowMemoryForContextStack(uptr stack
, uptr ssize
) {
341 // Only clear if we know the stack. This should be true only for contexts
342 // created with makecontext().
345 // Align to page size.
346 uptr PageSize
= GetPageSizeCached();
347 uptr bottom
= RoundDownTo(stack
, PageSize
);
348 if (!AddrIsInMem(bottom
))
350 ssize
+= stack
- bottom
;
351 ssize
= RoundUpTo(ssize
, PageSize
);
352 PoisonShadow(bottom
, ssize
, 0);
355 // Since Solaris 10/SPARC, ucp->uc_stack.ss_sp refers to the stack base address
356 // as on other targets. For binary compatibility, the new version uses a
357 // different external name, so we intercept that.
358 # if SANITIZER_SOLARIS && defined(__sparc__)
359 INTERCEPTOR(void, __makecontext_v2
, struct ucontext_t
*ucp
, void (*func
)(),
362 INTERCEPTOR(void, makecontext
, struct ucontext_t
*ucp
, void (*func
)(), int argc
,
367 // We don't know a better way to forward ... into REAL function. We can
368 // increase args size if neccecary.
369 CHECK_LE(argc
, ARRAY_SIZE(args
));
370 internal_memset(args
, 0, sizeof(args
));
372 for (int i
= 0; i
< argc
; ++i
) args
[i
] = va_arg(ap
, uptr
);
375 # define ENUMERATE_ARRAY_4(start) \
376 args[start], args[start + 1], args[start + 2], args[start + 3]
377 # define ENUMERATE_ARRAY_16(start) \
378 ENUMERATE_ARRAY_4(start), ENUMERATE_ARRAY_4(start + 4), \
379 ENUMERATE_ARRAY_4(start + 8), ENUMERATE_ARRAY_4(start + 12)
380 # define ENUMERATE_ARRAY_64() \
381 ENUMERATE_ARRAY_16(0), ENUMERATE_ARRAY_16(16), ENUMERATE_ARRAY_16(32), \
382 ENUMERATE_ARRAY_16(48)
384 # if SANITIZER_SOLARIS && defined(__sparc__)
385 REAL(__makecontext_v2
)
389 ((struct ucontext_t
*)ucp
, func
, argc
, ENUMERATE_ARRAY_64());
391 # undef ENUMERATE_ARRAY_4
392 # undef ENUMERATE_ARRAY_16
393 # undef ENUMERATE_ARRAY_64
395 // Sign the stack so we can identify it for unpoisoning.
396 SignContextStack(ucp
);
399 INTERCEPTOR(int, swapcontext
, struct ucontext_t
*oucp
,
400 struct ucontext_t
*ucp
) {
401 static bool reported_warning
= false;
402 if (!reported_warning
) {
403 Report("WARNING: ASan doesn't fully support makecontext/swapcontext "
404 "functions and may produce false positives in some cases!\n");
405 reported_warning
= true;
407 // Clear shadow memory for new context (it may share stack
408 // with current context).
410 ReadContextStack(ucp
, &stack
, &ssize
);
411 ClearShadowMemoryForContextStack(stack
, ssize
);
413 # if __has_attribute(__indirect_return__) && \
414 (defined(__x86_64__) || defined(__i386__))
415 int (*real_swapcontext
)(struct ucontext_t
*, struct ucontext_t
*)
416 __attribute__((__indirect_return__
)) = REAL(swapcontext
);
417 int res
= real_swapcontext(oucp
, ucp
);
419 int res
= REAL(swapcontext
)(oucp
, ucp
);
421 // swapcontext technically does not return, but program may swap context to
422 // "oucp" later, that would look as if swapcontext() returned 0.
423 // We need to clear shadow for ucp once again, as it may be in arbitrary
425 ClearShadowMemoryForContextStack(stack
, ssize
);
428 #endif // ASAN_INTERCEPT_SWAPCONTEXT
431 #define longjmp __longjmp14
432 #define siglongjmp __siglongjmp14
435 INTERCEPTOR(void, longjmp
, void *env
, int val
) {
436 __asan_handle_no_return();
437 REAL(longjmp
)(env
, val
);
440 #if ASAN_INTERCEPT__LONGJMP
441 INTERCEPTOR(void, _longjmp
, void *env
, int val
) {
442 __asan_handle_no_return();
443 REAL(_longjmp
)(env
, val
);
447 #if ASAN_INTERCEPT___LONGJMP_CHK
448 INTERCEPTOR(void, __longjmp_chk
, void *env
, int val
) {
449 __asan_handle_no_return();
450 REAL(__longjmp_chk
)(env
, val
);
454 #if ASAN_INTERCEPT_SIGLONGJMP
455 INTERCEPTOR(void, siglongjmp
, void *env
, int val
) {
456 __asan_handle_no_return();
457 REAL(siglongjmp
)(env
, val
);
461 #if ASAN_INTERCEPT___CXA_THROW
462 INTERCEPTOR(void, __cxa_throw
, void *a
, void *b
, void *c
) {
463 CHECK(REAL(__cxa_throw
));
464 __asan_handle_no_return();
465 REAL(__cxa_throw
)(a
, b
, c
);
469 #if ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION
470 INTERCEPTOR(void, __cxa_rethrow_primary_exception
, void *a
) {
471 CHECK(REAL(__cxa_rethrow_primary_exception
));
472 __asan_handle_no_return();
473 REAL(__cxa_rethrow_primary_exception
)(a
);
477 #if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION
478 INTERCEPTOR(_Unwind_Reason_Code
, _Unwind_RaiseException
,
479 _Unwind_Exception
*object
) {
480 CHECK(REAL(_Unwind_RaiseException
));
481 __asan_handle_no_return();
482 return REAL(_Unwind_RaiseException
)(object
);
486 #if ASAN_INTERCEPT__SJLJ_UNWIND_RAISEEXCEPTION
487 INTERCEPTOR(_Unwind_Reason_Code
, _Unwind_SjLj_RaiseException
,
488 _Unwind_Exception
*object
) {
489 CHECK(REAL(_Unwind_SjLj_RaiseException
));
490 __asan_handle_no_return();
491 return REAL(_Unwind_SjLj_RaiseException
)(object
);
495 #if ASAN_INTERCEPT_INDEX
496 # if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
497 INTERCEPTOR(char*, index
, const char *string
, int c
)
501 DECLARE_REAL(char*, index
, const char *string
, int c
)
502 OVERRIDE_FUNCTION(index
, strchr
);
504 DEFINE_REAL(char*, index
, const char *string
, int c
)
507 #endif // ASAN_INTERCEPT_INDEX
509 // For both strcat() and strncat() we need to check the validity of |to|
510 // argument irrespective of the |from| length.
511 INTERCEPTOR(char *, strcat
, char *to
, const char *from
) {
513 ASAN_INTERCEPTOR_ENTER(ctx
, strcat
);
515 if (flags()->replace_str
) {
516 uptr from_length
= internal_strlen(from
);
517 ASAN_READ_RANGE(ctx
, from
, from_length
+ 1);
518 uptr to_length
= internal_strlen(to
);
519 ASAN_READ_STRING_OF_LEN(ctx
, to
, to_length
, to_length
);
520 ASAN_WRITE_RANGE(ctx
, to
+ to_length
, from_length
+ 1);
521 // If the copying actually happens, the |from| string should not overlap
522 // with the resulting string starting at |to|, which has a length of
523 // to_length + from_length + 1.
524 if (from_length
> 0) {
525 CHECK_RANGES_OVERLAP("strcat", to
, from_length
+ to_length
+ 1, from
,
529 return REAL(strcat
)(to
, from
);
532 INTERCEPTOR(char*, strncat
, char *to
, const char *from
, uptr size
) {
534 ASAN_INTERCEPTOR_ENTER(ctx
, strncat
);
536 if (flags()->replace_str
) {
537 uptr from_length
= MaybeRealStrnlen(from
, size
);
538 uptr copy_length
= Min(size
, from_length
+ 1);
539 ASAN_READ_RANGE(ctx
, from
, copy_length
);
540 uptr to_length
= internal_strlen(to
);
541 ASAN_READ_STRING_OF_LEN(ctx
, to
, to_length
, to_length
);
542 ASAN_WRITE_RANGE(ctx
, to
+ to_length
, from_length
+ 1);
543 if (from_length
> 0) {
544 CHECK_RANGES_OVERLAP("strncat", to
, to_length
+ copy_length
+ 1,
548 return REAL(strncat
)(to
, from
, size
);
551 INTERCEPTOR(char *, strcpy
, char *to
, const char *from
) {
553 ASAN_INTERCEPTOR_ENTER(ctx
, strcpy
);
554 if constexpr (SANITIZER_APPLE
) {
555 // strcpy is called from malloc_default_purgeable_zone()
556 // in __asan::ReplaceSystemAlloc() on Mac.
557 if (UNLIKELY(!AsanInited()))
558 return REAL(strcpy
)(to
, from
);
560 if (!TryAsanInitFromRtl())
561 return REAL(strcpy
)(to
, from
);
564 if (flags()->replace_str
) {
565 uptr from_size
= internal_strlen(from
) + 1;
566 CHECK_RANGES_OVERLAP("strcpy", to
, from_size
, from
, from_size
);
567 ASAN_READ_RANGE(ctx
, from
, from_size
);
568 ASAN_WRITE_RANGE(ctx
, to
, from_size
);
570 return REAL(strcpy
)(to
, from
);
573 // Windows doesn't always define the strdup identifier,
574 // and when it does it's a macro defined to either _strdup
575 // or _strdup_dbg, _strdup_dbg ends up calling _strdup, so
576 // we want to intercept that. push/pop_macro are used to avoid problems
577 // if this file ends up including <string.h> in the future.
578 # if SANITIZER_WINDOWS
579 # pragma push_macro("strdup")
581 # define strdup _strdup
584 INTERCEPTOR(char*, strdup
, const char *s
) {
586 ASAN_INTERCEPTOR_ENTER(ctx
, strdup
);
587 if (UNLIKELY(!TryAsanInitFromRtl()))
588 return internal_strdup(s
);
589 uptr length
= internal_strlen(s
);
590 if (flags()->replace_str
) {
591 ASAN_READ_RANGE(ctx
, s
, length
+ 1);
593 GET_STACK_TRACE_MALLOC
;
594 void *new_mem
= asan_malloc(length
+ 1, &stack
);
596 REAL(memcpy
)(new_mem
, s
, length
+ 1);
598 return reinterpret_cast<char*>(new_mem
);
601 # if ASAN_INTERCEPT___STRDUP
602 INTERCEPTOR(char*, __strdup
, const char *s
) {
604 ASAN_INTERCEPTOR_ENTER(ctx
, strdup
);
605 if (UNLIKELY(!TryAsanInitFromRtl()))
606 return internal_strdup(s
);
607 uptr length
= internal_strlen(s
);
608 if (flags()->replace_str
) {
609 ASAN_READ_RANGE(ctx
, s
, length
+ 1);
611 GET_STACK_TRACE_MALLOC
;
612 void *new_mem
= asan_malloc(length
+ 1, &stack
);
614 REAL(memcpy
)(new_mem
, s
, length
+ 1);
616 return reinterpret_cast<char*>(new_mem
);
618 #endif // ASAN_INTERCEPT___STRDUP
620 INTERCEPTOR(char*, strncpy
, char *to
, const char *from
, uptr size
) {
622 ASAN_INTERCEPTOR_ENTER(ctx
, strncpy
);
624 if (flags()->replace_str
) {
625 uptr from_size
= Min(size
, MaybeRealStrnlen(from
, size
) + 1);
626 CHECK_RANGES_OVERLAP("strncpy", to
, from_size
, from
, from_size
);
627 ASAN_READ_RANGE(ctx
, from
, from_size
);
628 ASAN_WRITE_RANGE(ctx
, to
, size
);
630 return REAL(strncpy
)(to
, from
, size
);
633 template <typename Fn
>
634 static ALWAYS_INLINE
auto StrtolImpl(void *ctx
, Fn real
, const char *nptr
,
635 char **endptr
, int base
)
636 -> decltype(real(nullptr, nullptr, 0)) {
637 if (!flags()->replace_str
)
638 return real(nptr
, endptr
, base
);
640 auto res
= real(nptr
, &real_endptr
, base
);
641 StrtolFixAndCheck(ctx
, nptr
, endptr
, real_endptr
, base
);
645 # define INTERCEPTOR_STRTO_BASE(ret_type, func) \
646 INTERCEPTOR(ret_type, func, const char *nptr, char **endptr, int base) { \
648 ASAN_INTERCEPTOR_ENTER(ctx, func); \
650 return StrtolImpl(ctx, REAL(func), nptr, endptr, base); \
653 INTERCEPTOR_STRTO_BASE(long long, strtoll
)
655 # if SANITIZER_WINDOWS
656 INTERCEPTOR(long, strtol
, const char *nptr
, char **endptr
, int base
) {
657 // REAL(strtol) may be ntdll!strtol, which doesn't set errno. Instead,
658 // call REAL(strtoll) and do the range check ourselves.
659 COMPILER_CHECK(sizeof(long) == sizeof(u32
));
662 ASAN_INTERCEPTOR_ENTER(ctx
, strtol
);
665 long long result
= StrtolImpl(ctx
, REAL(strtoll
), nptr
, endptr
, base
);
667 if (result
> INT32_MAX
) {
668 errno
= errno_ERANGE
;
671 if (result
< INT32_MIN
) {
672 errno
= errno_ERANGE
;
678 INTERCEPTOR_STRTO_BASE(long, strtol
)
682 INTERCEPTOR_STRTO_BASE(long, __isoc23_strtol
)
683 INTERCEPTOR_STRTO_BASE(long long, __isoc23_strtoll
)
686 INTERCEPTOR(int, atoi
, const char *nptr
) {
688 ASAN_INTERCEPTOR_ENTER(ctx
, atoi
);
689 if (SANITIZER_APPLE
&& UNLIKELY(!AsanInited()))
690 return REAL(atoi
)(nptr
);
692 if (!flags()->replace_str
) {
693 return REAL(atoi
)(nptr
);
696 // "man atoi" tells that behavior of atoi(nptr) is the same as
697 // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
698 // parsed integer can't be stored in *long* type (even if it's
699 // different from int). So, we just imitate this behavior.
700 int result
= REAL(strtol
)(nptr
, &real_endptr
, 10);
701 FixRealStrtolEndptr(nptr
, &real_endptr
);
702 ASAN_READ_STRING(ctx
, nptr
, (real_endptr
- nptr
) + 1);
706 INTERCEPTOR(long, atol
, const char *nptr
) {
708 ASAN_INTERCEPTOR_ENTER(ctx
, atol
);
709 if (SANITIZER_APPLE
&& UNLIKELY(!AsanInited()))
710 return REAL(atol
)(nptr
);
712 if (!flags()->replace_str
) {
713 return REAL(atol
)(nptr
);
716 long result
= REAL(strtol
)(nptr
, &real_endptr
, 10);
717 FixRealStrtolEndptr(nptr
, &real_endptr
);
718 ASAN_READ_STRING(ctx
, nptr
, (real_endptr
- nptr
) + 1);
722 INTERCEPTOR(long long, atoll
, const char *nptr
) {
724 ASAN_INTERCEPTOR_ENTER(ctx
, atoll
);
726 if (!flags()->replace_str
) {
727 return REAL(atoll
)(nptr
);
730 long long result
= REAL(strtoll
)(nptr
, &real_endptr
, 10);
731 FixRealStrtolEndptr(nptr
, &real_endptr
);
732 ASAN_READ_STRING(ctx
, nptr
, (real_endptr
- nptr
) + 1);
736 #if ASAN_INTERCEPT___CXA_ATEXIT || ASAN_INTERCEPT_ATEXIT
737 static void AtCxaAtexit(void *unused
) {
739 StopInitOrderChecking();
743 #if ASAN_INTERCEPT___CXA_ATEXIT
744 INTERCEPTOR(int, __cxa_atexit
, void (*func
)(void *), void *arg
,
746 if (SANITIZER_APPLE
&& UNLIKELY(!AsanInited()))
747 return REAL(__cxa_atexit
)(func
, arg
, dso_handle
);
749 # if CAN_SANITIZE_LEAKS
750 __lsan::ScopedInterceptorDisabler disabler
;
752 int res
= REAL(__cxa_atexit
)(func
, arg
, dso_handle
);
753 REAL(__cxa_atexit
)(AtCxaAtexit
, nullptr, nullptr);
756 #endif // ASAN_INTERCEPT___CXA_ATEXIT
758 #if ASAN_INTERCEPT_ATEXIT
759 INTERCEPTOR(int, atexit
, void (*func
)()) {
761 # if CAN_SANITIZE_LEAKS
762 __lsan::ScopedInterceptorDisabler disabler
;
764 // Avoid calling real atexit as it is unreachable on at least on Linux.
765 int res
= REAL(__cxa_atexit
)((void (*)(void *a
))func
, nullptr, nullptr);
766 REAL(__cxa_atexit
)(AtCxaAtexit
, nullptr, nullptr);
771 #if ASAN_INTERCEPT_PTHREAD_ATFORK
773 extern int _pthread_atfork(void (*prepare
)(), void (*parent
)(),
777 INTERCEPTOR(int, pthread_atfork
, void (*prepare
)(), void (*parent
)(),
779 #if CAN_SANITIZE_LEAKS
780 __lsan::ScopedInterceptorDisabler disabler
;
782 // REAL(pthread_atfork) cannot be called due to symbol indirections at least
784 return _pthread_atfork(prepare
, parent
, child
);
788 #if ASAN_INTERCEPT_VFORK
789 DEFINE_REAL(int, vfork
,)
790 DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(int, vfork
,)
793 // ---------------------- InitializeAsanInterceptors ---------------- {{{1
795 void InitializeAsanInterceptors() {
796 static bool was_called_once
;
797 CHECK(!was_called_once
);
798 was_called_once
= true;
799 InitializePlatformInterceptors();
800 InitializeCommonInterceptors();
801 InitializeSignalInterceptors();
803 // Intercept str* functions.
804 ASAN_INTERCEPT_FUNC(strcat
);
805 ASAN_INTERCEPT_FUNC(strcpy
);
806 ASAN_INTERCEPT_FUNC(strncat
);
807 ASAN_INTERCEPT_FUNC(strncpy
);
808 ASAN_INTERCEPT_FUNC(strdup
);
809 # if ASAN_INTERCEPT___STRDUP
810 ASAN_INTERCEPT_FUNC(__strdup
);
812 #if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
813 ASAN_INTERCEPT_FUNC(index
);
816 ASAN_INTERCEPT_FUNC(atoi
);
817 ASAN_INTERCEPT_FUNC(atol
);
818 ASAN_INTERCEPT_FUNC(atoll
);
819 ASAN_INTERCEPT_FUNC(strtol
);
820 ASAN_INTERCEPT_FUNC(strtoll
);
822 ASAN_INTERCEPT_FUNC(__isoc23_strtol
);
823 ASAN_INTERCEPT_FUNC(__isoc23_strtoll
);
826 // Intecept jump-related functions.
827 ASAN_INTERCEPT_FUNC(longjmp
);
829 # if ASAN_INTERCEPT_SWAPCONTEXT
830 ASAN_INTERCEPT_FUNC(swapcontext
);
831 // See the makecontext interceptor above for an explanation.
832 # if SANITIZER_SOLARIS && defined(__sparc__)
833 ASAN_INTERCEPT_FUNC(__makecontext_v2
);
835 ASAN_INTERCEPT_FUNC(makecontext
);
838 # if ASAN_INTERCEPT__LONGJMP
839 ASAN_INTERCEPT_FUNC(_longjmp
);
841 #if ASAN_INTERCEPT___LONGJMP_CHK
842 ASAN_INTERCEPT_FUNC(__longjmp_chk
);
844 #if ASAN_INTERCEPT_SIGLONGJMP
845 ASAN_INTERCEPT_FUNC(siglongjmp
);
848 // Intercept exception handling functions.
849 #if ASAN_INTERCEPT___CXA_THROW
850 ASAN_INTERCEPT_FUNC(__cxa_throw
);
852 #if ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION
853 ASAN_INTERCEPT_FUNC(__cxa_rethrow_primary_exception
);
855 // Indirectly intercept std::rethrow_exception.
856 #if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION
857 ASAN_INTERCEPT_FUNC(_Unwind_RaiseException
);
859 // Indirectly intercept std::rethrow_exception.
860 #if ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION
861 ASAN_INTERCEPT_FUNC(_Unwind_SjLj_RaiseException
);
864 // Intercept threading-related functions
865 #if ASAN_INTERCEPT_PTHREAD_CREATE
866 // TODO: this should probably have an unversioned fallback for newer arches?
867 #if defined(ASAN_PTHREAD_CREATE_VERSION)
868 ASAN_INTERCEPT_FUNC_VER(pthread_create
, ASAN_PTHREAD_CREATE_VERSION
);
870 ASAN_INTERCEPT_FUNC(pthread_create
);
872 ASAN_INTERCEPT_FUNC(pthread_join
);
873 ASAN_INTERCEPT_FUNC(pthread_detach
);
874 ASAN_INTERCEPT_FUNC(pthread_exit
);
877 # if ASAN_INTERCEPT_TIMEDJOIN
878 ASAN_INTERCEPT_FUNC(pthread_timedjoin_np
);
881 #if ASAN_INTERCEPT_TRYJOIN
882 ASAN_INTERCEPT_FUNC(pthread_tryjoin_np
);
885 // Intercept atexit function.
886 #if ASAN_INTERCEPT___CXA_ATEXIT
887 ASAN_INTERCEPT_FUNC(__cxa_atexit
);
890 #if ASAN_INTERCEPT_ATEXIT
891 ASAN_INTERCEPT_FUNC(atexit
);
894 #if ASAN_INTERCEPT_PTHREAD_ATFORK
895 ASAN_INTERCEPT_FUNC(pthread_atfork
);
898 #if ASAN_INTERCEPT_VFORK
899 ASAN_INTERCEPT_FUNC(vfork
);
902 VReport(1, "AddressSanitizer: libc interceptors initialized\n");
905 # if SANITIZER_WINDOWS
906 # pragma pop_macro("strdup")
909 } // namespace __asan
911 #endif // !SANITIZER_FUCHSIA