[Clang][SME2] Enable multi-vector loads & stores for SME2 (#75821)
[llvm-project.git] / compiler-rt / lib / asan / asan_interceptors.cpp
blob4de2fa356374a693416de76470092cf022dc6c8c
1 //===-- asan_interceptors.cpp ---------------------------------------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 //
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
35 # if SANITIZER_POSIX
36 # include "sanitizer_common/sanitizer_posix.h"
37 # endif
39 # if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION || \
40 ASAN_INTERCEPT__SJLJ_UNWIND_RAISEEXCEPTION
41 # include <unwind.h>
42 # endif
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"
48 # endif
50 namespace __asan {
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
61 if (REAL(strnlen)) {
62 return REAL(strnlen)(s, maxlen);
64 #endif
65 return internal_strnlen(s, maxlen);
68 void SetThreadName(const char *name) {
69 AsanThread *t = GetCurrentThread();
70 if (t)
71 asanThreadRegistry().SetThreadName(t->tid(), name);
74 int OnExit() {
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.
80 return 0;
83 } // namespace __asan
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); \
101 do { \
102 if constexpr (SANITIZER_APPLE) { \
103 if (UNLIKELY(!AsanInited())) \
104 return REAL(func)(__VA_ARGS__); \
105 } else { \
106 if (!TryAsanInitFromRtl()) \
107 return REAL(func)(__VA_ARGS__); \
109 } while (false)
110 #define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \
111 do { \
112 } while (false)
113 #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
114 do { \
115 } while (false)
116 #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
117 do { \
118 } while (false)
119 #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
120 do { \
121 } while (false)
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
126 // can be slow.
127 #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
128 do { \
129 } while (false)
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) \
134 ({ \
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(); \
148 } else { \
149 *begin = *end = 0; \
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);
164 return res;
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, \
182 fd, offset) \
183 do { \
184 (void)(ctx); \
185 return mmap_interceptor(REAL(mmap), addr, sz, prot, flags, fd, off); \
186 } while (false)
188 # define COMMON_INTERCEPTOR_MUNMAP_IMPL(ctx, addr, length) \
189 do { \
190 (void)(ctx); \
191 return munmap_interceptor(REAL(munmap), addr, sz); \
192 } while (false)
194 #if CAN_SANITIZE_LEAKS
195 #define COMMON_INTERCEPTOR_STRERROR() \
196 __lsan::ScopedInterceptorDisabler disabler
197 #endif
199 # define SIGNAL_INTERCEPTOR_ENTER() \
200 do { \
201 AsanInitFromRtl(); \
202 } while (false)
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
208 // for them.
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) \
212 do { \
213 (void)(p); \
214 (void)(s); \
215 } while (false)
216 #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \
217 do { \
218 (void)(p); \
219 (void)(s); \
220 } while (false)
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;
227 SetCurrentThread(t);
228 auto self = GetThreadSelf();
229 auto args = asanThreadArgRetval().GetArgs(self);
230 t->ThreadStart(GetTid());
232 # if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
233 SANITIZER_SOLARIS
234 __sanitizer_sigset_t sigset;
235 t->GetStartData(sigset);
236 SetSigProcMask(&sigset, nullptr);
237 # endif
239 thread_return_t retval = (*args.routine)(args.arg_retval);
240 asanThreadArgRetval().Finish(self, retval);
241 return 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]() {
252 int d = 0;
253 return attr && !REAL(pthread_attr_getdetachstate)(attr, &d) &&
254 IsStateDetached(d);
255 }();
257 u32 current_tid = GetCurrentTidOrInvalid();
259 __sanitizer_sigset_t sigset = {};
260 # if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
261 SANITIZER_SOLARIS
262 ScopedBlockSignals block(&sigset);
263 # endif
265 AsanThread *t = AsanThread::Create(sigset, current_tid, &stack, detached);
267 int result;
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;
275 # endif
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);
281 if (result != 0) {
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.
285 t->Destroy();
287 return result;
290 INTERCEPTOR(int, pthread_join, void *thread, void **retval) {
291 int result;
292 asanThreadArgRetval().Join((uptr)thread, [&]() {
293 result = REAL(pthread_join)(thread, retval);
294 return !result;
296 return result;
299 INTERCEPTOR(int, pthread_detach, void *thread) {
300 int result;
301 asanThreadArgRetval().Detach((uptr)thread, [&]() {
302 result = REAL(pthread_detach)(thread);
303 return !result;
305 return result;
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) {
315 int result;
316 asanThreadArgRetval().Join((uptr)thread, [&]() {
317 result = REAL(pthread_tryjoin_np)(thread, ret);
318 return !result;
320 return result;
322 # endif
324 # if ASAN_INTERCEPT_TIMEDJOIN
325 INTERCEPTOR(int, pthread_timedjoin_np, void *thread, void **ret,
326 const struct timespec *abstime) {
327 int result;
328 asanThreadArgRetval().Join((uptr)thread, [&]() {
329 result = REAL(pthread_timedjoin_np)(thread, ret, abstime);
330 return !result;
332 return result;
334 # endif
336 DEFINE_REAL_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().
343 if (!ssize)
344 return;
345 // Align to page size.
346 uptr PageSize = GetPageSizeCached();
347 uptr bottom = RoundDownTo(stack, PageSize);
348 if (!AddrIsInMem(bottom))
349 return;
350 ssize += stack - bottom;
351 ssize = RoundUpTo(ssize, PageSize);
352 PoisonShadow(bottom, ssize, 0);
355 INTERCEPTOR(void, makecontext, struct ucontext_t *ucp, void (*func)(), int argc,
356 ...) {
357 va_list ap;
358 uptr args[64];
359 // We don't know a better way to forward ... into REAL function. We can
360 // increase args size if neccecary.
361 CHECK_LE(argc, ARRAY_SIZE(args));
362 internal_memset(args, 0, sizeof(args));
363 va_start(ap, argc);
364 for (int i = 0; i < argc; ++i) args[i] = va_arg(ap, uptr);
365 va_end(ap);
367 # define ENUMERATE_ARRAY_4(start) \
368 args[start], args[start + 1], args[start + 2], args[start + 3]
369 # define ENUMERATE_ARRAY_16(start) \
370 ENUMERATE_ARRAY_4(start), ENUMERATE_ARRAY_4(start + 4), \
371 ENUMERATE_ARRAY_4(start + 8), ENUMERATE_ARRAY_4(start + 12)
372 # define ENUMERATE_ARRAY_64() \
373 ENUMERATE_ARRAY_16(0), ENUMERATE_ARRAY_16(16), ENUMERATE_ARRAY_16(32), \
374 ENUMERATE_ARRAY_16(48)
376 REAL(makecontext)
377 ((struct ucontext_t *)ucp, func, argc, ENUMERATE_ARRAY_64());
379 # undef ENUMERATE_ARRAY_4
380 # undef ENUMERATE_ARRAY_16
381 # undef ENUMERATE_ARRAY_64
383 // Sign the stack so we can identify it for unpoisoning.
384 SignContextStack(ucp);
387 INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp,
388 struct ucontext_t *ucp) {
389 static bool reported_warning = false;
390 if (!reported_warning) {
391 Report("WARNING: ASan doesn't fully support makecontext/swapcontext "
392 "functions and may produce false positives in some cases!\n");
393 reported_warning = true;
395 // Clear shadow memory for new context (it may share stack
396 // with current context).
397 uptr stack, ssize;
398 ReadContextStack(ucp, &stack, &ssize);
399 ClearShadowMemoryForContextStack(stack, ssize);
401 # if __has_attribute(__indirect_return__) && \
402 (defined(__x86_64__) || defined(__i386__))
403 int (*real_swapcontext)(struct ucontext_t *, struct ucontext_t *)
404 __attribute__((__indirect_return__)) = REAL(swapcontext);
405 int res = real_swapcontext(oucp, ucp);
406 # else
407 int res = REAL(swapcontext)(oucp, ucp);
408 # endif
409 // swapcontext technically does not return, but program may swap context to
410 // "oucp" later, that would look as if swapcontext() returned 0.
411 // We need to clear shadow for ucp once again, as it may be in arbitrary
412 // state.
413 ClearShadowMemoryForContextStack(stack, ssize);
414 return res;
416 #endif // ASAN_INTERCEPT_SWAPCONTEXT
418 #if SANITIZER_NETBSD
419 #define longjmp __longjmp14
420 #define siglongjmp __siglongjmp14
421 #endif
423 INTERCEPTOR(void, longjmp, void *env, int val) {
424 __asan_handle_no_return();
425 REAL(longjmp)(env, val);
428 #if ASAN_INTERCEPT__LONGJMP
429 INTERCEPTOR(void, _longjmp, void *env, int val) {
430 __asan_handle_no_return();
431 REAL(_longjmp)(env, val);
433 #endif
435 #if ASAN_INTERCEPT___LONGJMP_CHK
436 INTERCEPTOR(void, __longjmp_chk, void *env, int val) {
437 __asan_handle_no_return();
438 REAL(__longjmp_chk)(env, val);
440 #endif
442 #if ASAN_INTERCEPT_SIGLONGJMP
443 INTERCEPTOR(void, siglongjmp, void *env, int val) {
444 __asan_handle_no_return();
445 REAL(siglongjmp)(env, val);
447 #endif
449 #if ASAN_INTERCEPT___CXA_THROW
450 INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
451 CHECK(REAL(__cxa_throw));
452 __asan_handle_no_return();
453 REAL(__cxa_throw)(a, b, c);
455 #endif
457 #if ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION
458 INTERCEPTOR(void, __cxa_rethrow_primary_exception, void *a) {
459 CHECK(REAL(__cxa_rethrow_primary_exception));
460 __asan_handle_no_return();
461 REAL(__cxa_rethrow_primary_exception)(a);
463 #endif
465 #if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION
466 INTERCEPTOR(_Unwind_Reason_Code, _Unwind_RaiseException,
467 _Unwind_Exception *object) {
468 CHECK(REAL(_Unwind_RaiseException));
469 __asan_handle_no_return();
470 return REAL(_Unwind_RaiseException)(object);
472 #endif
474 #if ASAN_INTERCEPT__SJLJ_UNWIND_RAISEEXCEPTION
475 INTERCEPTOR(_Unwind_Reason_Code, _Unwind_SjLj_RaiseException,
476 _Unwind_Exception *object) {
477 CHECK(REAL(_Unwind_SjLj_RaiseException));
478 __asan_handle_no_return();
479 return REAL(_Unwind_SjLj_RaiseException)(object);
481 #endif
483 #if ASAN_INTERCEPT_INDEX
484 # if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
485 INTERCEPTOR(char*, index, const char *string, int c)
486 ALIAS(WRAP(strchr));
487 # else
488 # if SANITIZER_APPLE
489 DECLARE_REAL(char*, index, const char *string, int c)
490 OVERRIDE_FUNCTION(index, strchr);
491 # else
492 DEFINE_REAL(char*, index, const char *string, int c)
493 # endif
494 # endif
495 #endif // ASAN_INTERCEPT_INDEX
497 // For both strcat() and strncat() we need to check the validity of |to|
498 // argument irrespective of the |from| length.
499 INTERCEPTOR(char *, strcat, char *to, const char *from) {
500 void *ctx;
501 ASAN_INTERCEPTOR_ENTER(ctx, strcat);
502 AsanInitFromRtl();
503 if (flags()->replace_str) {
504 uptr from_length = internal_strlen(from);
505 ASAN_READ_RANGE(ctx, from, from_length + 1);
506 uptr to_length = internal_strlen(to);
507 ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
508 ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
509 // If the copying actually happens, the |from| string should not overlap
510 // with the resulting string starting at |to|, which has a length of
511 // to_length + from_length + 1.
512 if (from_length > 0) {
513 CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1, from,
514 from_length + 1);
517 return REAL(strcat)(to, from);
520 INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
521 void *ctx;
522 ASAN_INTERCEPTOR_ENTER(ctx, strncat);
523 AsanInitFromRtl();
524 if (flags()->replace_str) {
525 uptr from_length = MaybeRealStrnlen(from, size);
526 uptr copy_length = Min(size, from_length + 1);
527 ASAN_READ_RANGE(ctx, from, copy_length);
528 uptr to_length = internal_strlen(to);
529 ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
530 ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
531 if (from_length > 0) {
532 CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1,
533 from, copy_length);
536 return REAL(strncat)(to, from, size);
539 INTERCEPTOR(char *, strcpy, char *to, const char *from) {
540 void *ctx;
541 ASAN_INTERCEPTOR_ENTER(ctx, strcpy);
542 if constexpr (SANITIZER_APPLE) {
543 // strcpy is called from malloc_default_purgeable_zone()
544 // in __asan::ReplaceSystemAlloc() on Mac.
545 if (UNLIKELY(!AsanInited()))
546 return REAL(strcpy)(to, from);
547 } else {
548 if (!TryAsanInitFromRtl())
549 return REAL(strcpy)(to, from);
552 if (flags()->replace_str) {
553 uptr from_size = internal_strlen(from) + 1;
554 CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size);
555 ASAN_READ_RANGE(ctx, from, from_size);
556 ASAN_WRITE_RANGE(ctx, to, from_size);
558 return REAL(strcpy)(to, from);
561 INTERCEPTOR(char*, strdup, const char *s) {
562 void *ctx;
563 ASAN_INTERCEPTOR_ENTER(ctx, strdup);
564 if (UNLIKELY(!TryAsanInitFromRtl()))
565 return internal_strdup(s);
566 uptr length = internal_strlen(s);
567 if (flags()->replace_str) {
568 ASAN_READ_RANGE(ctx, s, length + 1);
570 GET_STACK_TRACE_MALLOC;
571 void *new_mem = asan_malloc(length + 1, &stack);
572 if (new_mem) {
573 REAL(memcpy)(new_mem, s, length + 1);
575 return reinterpret_cast<char*>(new_mem);
578 #if ASAN_INTERCEPT___STRDUP
579 INTERCEPTOR(char*, __strdup, const char *s) {
580 void *ctx;
581 ASAN_INTERCEPTOR_ENTER(ctx, strdup);
582 if (UNLIKELY(!TryAsanInitFromRtl()))
583 return internal_strdup(s);
584 uptr length = internal_strlen(s);
585 if (flags()->replace_str) {
586 ASAN_READ_RANGE(ctx, s, length + 1);
588 GET_STACK_TRACE_MALLOC;
589 void *new_mem = asan_malloc(length + 1, &stack);
590 if (new_mem) {
591 REAL(memcpy)(new_mem, s, length + 1);
593 return reinterpret_cast<char*>(new_mem);
595 #endif // ASAN_INTERCEPT___STRDUP
597 INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) {
598 void *ctx;
599 ASAN_INTERCEPTOR_ENTER(ctx, strncpy);
600 AsanInitFromRtl();
601 if (flags()->replace_str) {
602 uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1);
603 CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size);
604 ASAN_READ_RANGE(ctx, from, from_size);
605 ASAN_WRITE_RANGE(ctx, to, size);
607 return REAL(strncpy)(to, from, size);
610 template <typename Fn>
611 static ALWAYS_INLINE auto StrtolImpl(void *ctx, Fn real, const char *nptr,
612 char **endptr, int base)
613 -> decltype(real(nullptr, nullptr, 0)) {
614 if (!flags()->replace_str)
615 return real(nptr, endptr, base);
616 char *real_endptr;
617 auto res = real(nptr, &real_endptr, base);
618 StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
619 return res;
622 # define INTERCEPTOR_STRTO_BASE(ret_type, func) \
623 INTERCEPTOR(ret_type, func, const char *nptr, char **endptr, int base) { \
624 void *ctx; \
625 ASAN_INTERCEPTOR_ENTER(ctx, func); \
626 AsanInitFromRtl(); \
627 return StrtolImpl(ctx, REAL(func), nptr, endptr, base); \
630 INTERCEPTOR_STRTO_BASE(long, strtol)
631 INTERCEPTOR_STRTO_BASE(long long, strtoll)
633 # if SANITIZER_GLIBC
634 INTERCEPTOR_STRTO_BASE(long, __isoc23_strtol)
635 INTERCEPTOR_STRTO_BASE(long long, __isoc23_strtoll)
636 # endif
638 INTERCEPTOR(int, atoi, const char *nptr) {
639 void *ctx;
640 ASAN_INTERCEPTOR_ENTER(ctx, atoi);
641 if (SANITIZER_APPLE && UNLIKELY(!AsanInited()))
642 return REAL(atoi)(nptr);
643 AsanInitFromRtl();
644 if (!flags()->replace_str) {
645 return REAL(atoi)(nptr);
647 char *real_endptr;
648 // "man atoi" tells that behavior of atoi(nptr) is the same as
649 // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
650 // parsed integer can't be stored in *long* type (even if it's
651 // different from int). So, we just imitate this behavior.
652 int result = REAL(strtol)(nptr, &real_endptr, 10);
653 FixRealStrtolEndptr(nptr, &real_endptr);
654 ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
655 return result;
658 INTERCEPTOR(long, atol, const char *nptr) {
659 void *ctx;
660 ASAN_INTERCEPTOR_ENTER(ctx, atol);
661 if (SANITIZER_APPLE && UNLIKELY(!AsanInited()))
662 return REAL(atol)(nptr);
663 AsanInitFromRtl();
664 if (!flags()->replace_str) {
665 return REAL(atol)(nptr);
667 char *real_endptr;
668 long result = REAL(strtol)(nptr, &real_endptr, 10);
669 FixRealStrtolEndptr(nptr, &real_endptr);
670 ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
671 return result;
674 INTERCEPTOR(long long, atoll, const char *nptr) {
675 void *ctx;
676 ASAN_INTERCEPTOR_ENTER(ctx, atoll);
677 AsanInitFromRtl();
678 if (!flags()->replace_str) {
679 return REAL(atoll)(nptr);
681 char *real_endptr;
682 long long result = REAL(strtoll)(nptr, &real_endptr, 10);
683 FixRealStrtolEndptr(nptr, &real_endptr);
684 ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
685 return result;
688 #if ASAN_INTERCEPT___CXA_ATEXIT || ASAN_INTERCEPT_ATEXIT
689 static void AtCxaAtexit(void *unused) {
690 (void)unused;
691 StopInitOrderChecking();
693 #endif
695 #if ASAN_INTERCEPT___CXA_ATEXIT
696 INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
697 void *dso_handle) {
698 if (SANITIZER_APPLE && UNLIKELY(!AsanInited()))
699 return REAL(__cxa_atexit)(func, arg, dso_handle);
700 AsanInitFromRtl();
701 # if CAN_SANITIZE_LEAKS
702 __lsan::ScopedInterceptorDisabler disabler;
703 #endif
704 int res = REAL(__cxa_atexit)(func, arg, dso_handle);
705 REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr);
706 return res;
708 #endif // ASAN_INTERCEPT___CXA_ATEXIT
710 #if ASAN_INTERCEPT_ATEXIT
711 INTERCEPTOR(int, atexit, void (*func)()) {
712 AsanInitFromRtl();
713 # if CAN_SANITIZE_LEAKS
714 __lsan::ScopedInterceptorDisabler disabler;
715 #endif
716 // Avoid calling real atexit as it is unreachable on at least on Linux.
717 int res = REAL(__cxa_atexit)((void (*)(void *a))func, nullptr, nullptr);
718 REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr);
719 return res;
721 #endif
723 #if ASAN_INTERCEPT_PTHREAD_ATFORK
724 extern "C" {
725 extern int _pthread_atfork(void (*prepare)(), void (*parent)(),
726 void (*child)());
729 INTERCEPTOR(int, pthread_atfork, void (*prepare)(), void (*parent)(),
730 void (*child)()) {
731 #if CAN_SANITIZE_LEAKS
732 __lsan::ScopedInterceptorDisabler disabler;
733 #endif
734 // REAL(pthread_atfork) cannot be called due to symbol indirections at least
735 // on NetBSD
736 return _pthread_atfork(prepare, parent, child);
738 #endif
740 #if ASAN_INTERCEPT_VFORK
741 DEFINE_REAL(int, vfork)
742 DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(int, vfork)
743 #endif
745 // ---------------------- InitializeAsanInterceptors ---------------- {{{1
746 namespace __asan {
747 void InitializeAsanInterceptors() {
748 static bool was_called_once;
749 CHECK(!was_called_once);
750 was_called_once = true;
751 InitializePlatformInterceptors();
752 InitializeCommonInterceptors();
753 InitializeSignalInterceptors();
755 // Intercept str* functions.
756 ASAN_INTERCEPT_FUNC(strcat);
757 ASAN_INTERCEPT_FUNC(strcpy);
758 ASAN_INTERCEPT_FUNC(strncat);
759 ASAN_INTERCEPT_FUNC(strncpy);
760 ASAN_INTERCEPT_FUNC(strdup);
761 #if ASAN_INTERCEPT___STRDUP
762 ASAN_INTERCEPT_FUNC(__strdup);
763 #endif
764 #if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
765 ASAN_INTERCEPT_FUNC(index);
766 #endif
768 ASAN_INTERCEPT_FUNC(atoi);
769 ASAN_INTERCEPT_FUNC(atol);
770 ASAN_INTERCEPT_FUNC(atoll);
771 ASAN_INTERCEPT_FUNC(strtol);
772 ASAN_INTERCEPT_FUNC(strtoll);
773 # if SANITIZER_GLIBC
774 ASAN_INTERCEPT_FUNC(__isoc23_strtol);
775 ASAN_INTERCEPT_FUNC(__isoc23_strtoll);
776 # endif
778 // Intecept jump-related functions.
779 ASAN_INTERCEPT_FUNC(longjmp);
781 # if ASAN_INTERCEPT_SWAPCONTEXT
782 ASAN_INTERCEPT_FUNC(swapcontext);
783 ASAN_INTERCEPT_FUNC(makecontext);
784 # endif
785 # if ASAN_INTERCEPT__LONGJMP
786 ASAN_INTERCEPT_FUNC(_longjmp);
787 #endif
788 #if ASAN_INTERCEPT___LONGJMP_CHK
789 ASAN_INTERCEPT_FUNC(__longjmp_chk);
790 #endif
791 #if ASAN_INTERCEPT_SIGLONGJMP
792 ASAN_INTERCEPT_FUNC(siglongjmp);
793 #endif
795 // Intercept exception handling functions.
796 #if ASAN_INTERCEPT___CXA_THROW
797 ASAN_INTERCEPT_FUNC(__cxa_throw);
798 #endif
799 #if ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION
800 ASAN_INTERCEPT_FUNC(__cxa_rethrow_primary_exception);
801 #endif
802 // Indirectly intercept std::rethrow_exception.
803 #if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION
804 ASAN_INTERCEPT_FUNC(_Unwind_RaiseException);
805 #endif
806 // Indirectly intercept std::rethrow_exception.
807 #if ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION
808 ASAN_INTERCEPT_FUNC(_Unwind_SjLj_RaiseException);
809 #endif
811 // Intercept threading-related functions
812 #if ASAN_INTERCEPT_PTHREAD_CREATE
813 // TODO: this should probably have an unversioned fallback for newer arches?
814 #if defined(ASAN_PTHREAD_CREATE_VERSION)
815 ASAN_INTERCEPT_FUNC_VER(pthread_create, ASAN_PTHREAD_CREATE_VERSION);
816 #else
817 ASAN_INTERCEPT_FUNC(pthread_create);
818 #endif
819 ASAN_INTERCEPT_FUNC(pthread_join);
820 ASAN_INTERCEPT_FUNC(pthread_detach);
821 ASAN_INTERCEPT_FUNC(pthread_exit);
822 # endif
824 # if ASAN_INTERCEPT_TIMEDJOIN
825 ASAN_INTERCEPT_FUNC(pthread_timedjoin_np);
826 #endif
828 #if ASAN_INTERCEPT_TRYJOIN
829 ASAN_INTERCEPT_FUNC(pthread_tryjoin_np);
830 #endif
832 // Intercept atexit function.
833 #if ASAN_INTERCEPT___CXA_ATEXIT
834 ASAN_INTERCEPT_FUNC(__cxa_atexit);
835 #endif
837 #if ASAN_INTERCEPT_ATEXIT
838 ASAN_INTERCEPT_FUNC(atexit);
839 #endif
841 #if ASAN_INTERCEPT_PTHREAD_ATFORK
842 ASAN_INTERCEPT_FUNC(pthread_atfork);
843 #endif
845 #if ASAN_INTERCEPT_VFORK
846 ASAN_INTERCEPT_FUNC(vfork);
847 #endif
849 VReport(1, "AddressSanitizer: libc interceptors initialized\n");
852 } // namespace __asan
854 #endif // !SANITIZER_FUCHSIA