Daily bump.
[official-gcc.git] / libsanitizer / asan / asan_interceptors.cpp
blob234b18bd83aa541b299b4800e63814cb2aa5e1bb
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 (AsanInitIsRunning()) \
103 return REAL(func)(__VA_ARGS__); \
104 if (SANITIZER_APPLE && UNLIKELY(!AsanInited())) \
105 return REAL(func)(__VA_ARGS__); \
106 ENSURE_ASAN_INITED(); \
107 } while (false)
108 #define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \
109 do { \
110 } while (false)
111 #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
112 do { \
113 } while (false)
114 #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
115 do { \
116 } while (false)
117 #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
118 do { \
119 } while (false)
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
124 // can be slow.
125 #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
126 do { \
127 } while (false)
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) \
132 ({ \
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 (!AsanInited())
142 # define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \
143 if (AsanThread *t = GetCurrentThread()) { \
144 *begin = t->tls_begin(); \
145 *end = t->tls_end(); \
146 } else { \
147 *begin = *end = 0; \
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);
162 return res;
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, \
180 fd, offset) \
181 do { \
182 (void)(ctx); \
183 return mmap_interceptor(REAL(mmap), addr, sz, prot, flags, fd, off); \
184 } while (false)
186 # define COMMON_INTERCEPTOR_MUNMAP_IMPL(ctx, addr, length) \
187 do { \
188 (void)(ctx); \
189 return munmap_interceptor(REAL(munmap), addr, sz); \
190 } while (false)
192 #if CAN_SANITIZE_LEAKS
193 #define COMMON_INTERCEPTOR_STRERROR() \
194 __lsan::ScopedInterceptorDisabler disabler
195 #endif
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
203 // for them.
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) \
207 do { \
208 (void)(p); \
209 (void)(s); \
210 } while (false)
211 #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \
212 do { \
213 (void)(p); \
214 (void)(s); \
215 } while (false)
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;
222 SetCurrentThread(t);
223 auto self = GetThreadSelf();
224 auto args = asanThreadArgRetval().GetArgs(self);
225 t->ThreadStart(GetTid());
227 # if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
228 SANITIZER_SOLARIS
229 __sanitizer_sigset_t sigset;
230 t->GetStartData(sigset);
231 SetSigProcMask(&sigset, nullptr);
232 # endif
234 thread_return_t retval = (*args.routine)(args.arg_retval);
235 asanThreadArgRetval().Finish(self, retval);
236 return 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]() {
247 int d = 0;
248 return attr && !REAL(pthread_attr_getdetachstate)(attr, &d) &&
249 IsStateDetached(d);
250 }();
252 u32 current_tid = GetCurrentTidOrInvalid();
254 __sanitizer_sigset_t sigset = {};
255 # if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
256 SANITIZER_SOLARIS
257 ScopedBlockSignals block(&sigset);
258 # endif
260 AsanThread *t = AsanThread::Create(sigset, current_tid, &stack, detached);
262 int result;
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;
270 # endif
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);
276 if (result != 0) {
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.
280 t->Destroy();
282 return result;
285 INTERCEPTOR(int, pthread_join, void *thread, void **retval) {
286 int result;
287 asanThreadArgRetval().Join((uptr)thread, [&]() {
288 result = REAL(pthread_join)(thread, retval);
289 return !result;
291 return result;
294 INTERCEPTOR(int, pthread_detach, void *thread) {
295 int result;
296 asanThreadArgRetval().Detach((uptr)thread, [&]() {
297 result = REAL(pthread_detach)(thread);
298 return !result;
300 return result;
303 INTERCEPTOR(void, pthread_exit, void *retval) {
304 asanThreadArgRetval().Finish(GetThreadSelf(), retval);
305 REAL(pthread_exit)(retval);
308 # if ASAN_INTERCEPT_TRYJOIN
309 INTERCEPTOR(int, pthread_tryjoin_np, void *thread, void **ret) {
310 int result;
311 asanThreadArgRetval().Join((uptr)thread, [&]() {
312 result = REAL(pthread_tryjoin_np)(thread, ret);
313 return !result;
315 return result;
317 # endif
319 # if ASAN_INTERCEPT_TIMEDJOIN
320 INTERCEPTOR(int, pthread_timedjoin_np, void *thread, void **ret,
321 const struct timespec *abstime) {
322 int result;
323 asanThreadArgRetval().Join((uptr)thread, [&]() {
324 result = REAL(pthread_timedjoin_np)(thread, ret, abstime);
325 return !result;
327 return result;
329 # endif
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().
338 if (!ssize)
339 return;
340 // Align to page size.
341 uptr PageSize = GetPageSizeCached();
342 uptr bottom = RoundDownTo(stack, PageSize);
343 if (!AddrIsInMem(bottom))
344 return;
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,
351 ...) {
352 va_list ap;
353 uptr args[64];
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));
358 va_start(ap, argc);
359 for (int i = 0; i < argc; ++i) args[i] = va_arg(ap, uptr);
360 va_end(ap);
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)
371 REAL(makecontext)
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).
392 uptr stack, ssize;
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);
401 # else
402 int res = REAL(swapcontext)(oucp, ucp);
403 # endif
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
407 // state.
408 ClearShadowMemoryForContextStack(stack, ssize);
409 return res;
411 #endif // ASAN_INTERCEPT_SWAPCONTEXT
413 #if SANITIZER_NETBSD
414 #define longjmp __longjmp14
415 #define siglongjmp __siglongjmp14
416 #endif
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);
428 #endif
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);
435 #endif
437 #if ASAN_INTERCEPT_SIGLONGJMP
438 INTERCEPTOR(void, siglongjmp, void *env, int val) {
439 __asan_handle_no_return();
440 REAL(siglongjmp)(env, val);
442 #endif
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);
450 #endif
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);
458 #endif
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);
467 #endif
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);
476 #endif
478 #if ASAN_INTERCEPT_INDEX
479 # if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
480 INTERCEPTOR(char*, index, const char *string, int c)
481 ALIAS(WRAP(strchr));
482 # else
483 # if SANITIZER_APPLE
484 DECLARE_REAL(char*, index, const char *string, int c)
485 OVERRIDE_FUNCTION(index, strchr);
486 # else
487 DEFINE_REAL(char*, index, const char *string, int c)
488 # endif
489 # endif
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) {
495 void *ctx;
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,
509 from_length + 1);
512 return REAL(strcat)(to, from);
515 INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
516 void *ctx;
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,
528 from, copy_length);
531 return REAL(strncat)(to, from, size);
534 INTERCEPTOR(char *, strcpy, char *to, const char *from) {
535 void *ctx;
536 ASAN_INTERCEPTOR_ENTER(ctx, strcpy);
537 #if SANITIZER_APPLE
538 if (UNLIKELY(!AsanInited()))
539 return REAL(strcpy)(to, from);
540 #endif
541 // strcpy is called from malloc_default_purgeable_zone()
542 // in __asan::ReplaceSystemAlloc() on Mac.
543 if (AsanInitIsRunning()) {
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) {
557 void *ctx;
558 ASAN_INTERCEPTOR_ENTER(ctx, strdup);
559 if (UNLIKELY(!AsanInited()))
560 return internal_strdup(s);
561 ENSURE_ASAN_INITED();
562 uptr length = internal_strlen(s);
563 if (flags()->replace_str) {
564 ASAN_READ_RANGE(ctx, s, length + 1);
566 GET_STACK_TRACE_MALLOC;
567 void *new_mem = asan_malloc(length + 1, &stack);
568 if (new_mem) {
569 REAL(memcpy)(new_mem, s, length + 1);
571 return reinterpret_cast<char*>(new_mem);
574 #if ASAN_INTERCEPT___STRDUP
575 INTERCEPTOR(char*, __strdup, const char *s) {
576 void *ctx;
577 ASAN_INTERCEPTOR_ENTER(ctx, strdup);
578 if (UNLIKELY(!AsanInited()))
579 return internal_strdup(s);
580 ENSURE_ASAN_INITED();
581 uptr length = internal_strlen(s);
582 if (flags()->replace_str) {
583 ASAN_READ_RANGE(ctx, s, length + 1);
585 GET_STACK_TRACE_MALLOC;
586 void *new_mem = asan_malloc(length + 1, &stack);
587 if (new_mem) {
588 REAL(memcpy)(new_mem, s, length + 1);
590 return reinterpret_cast<char*>(new_mem);
592 #endif // ASAN_INTERCEPT___STRDUP
594 INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) {
595 void *ctx;
596 ASAN_INTERCEPTOR_ENTER(ctx, strncpy);
597 ENSURE_ASAN_INITED();
598 if (flags()->replace_str) {
599 uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1);
600 CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size);
601 ASAN_READ_RANGE(ctx, from, from_size);
602 ASAN_WRITE_RANGE(ctx, to, size);
604 return REAL(strncpy)(to, from, size);
607 template <typename Fn>
608 static ALWAYS_INLINE auto StrtolImpl(void *ctx, Fn real, const char *nptr,
609 char **endptr, int base)
610 -> decltype(real(nullptr, nullptr, 0)) {
611 if (!flags()->replace_str)
612 return real(nptr, endptr, base);
613 char *real_endptr;
614 auto res = real(nptr, &real_endptr, base);
615 StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
616 return res;
619 # define INTERCEPTOR_STRTO_BASE(ret_type, func) \
620 INTERCEPTOR(ret_type, func, const char *nptr, char **endptr, int base) { \
621 void *ctx; \
622 ASAN_INTERCEPTOR_ENTER(ctx, func); \
623 ENSURE_ASAN_INITED(); \
624 return StrtolImpl(ctx, REAL(func), nptr, endptr, base); \
627 INTERCEPTOR_STRTO_BASE(long, strtol)
628 INTERCEPTOR_STRTO_BASE(long long, strtoll)
630 # if SANITIZER_GLIBC
631 INTERCEPTOR_STRTO_BASE(long, __isoc23_strtol)
632 INTERCEPTOR_STRTO_BASE(long long, __isoc23_strtoll)
633 # endif
635 INTERCEPTOR(int, atoi, const char *nptr) {
636 void *ctx;
637 ASAN_INTERCEPTOR_ENTER(ctx, atoi);
638 #if SANITIZER_APPLE
639 if (UNLIKELY(!AsanInited()))
640 return REAL(atoi)(nptr);
641 # endif
642 ENSURE_ASAN_INITED();
643 if (!flags()->replace_str) {
644 return REAL(atoi)(nptr);
646 char *real_endptr;
647 // "man atoi" tells that behavior of atoi(nptr) is the same as
648 // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
649 // parsed integer can't be stored in *long* type (even if it's
650 // different from int). So, we just imitate this behavior.
651 int result = REAL(strtol)(nptr, &real_endptr, 10);
652 FixRealStrtolEndptr(nptr, &real_endptr);
653 ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
654 return result;
657 INTERCEPTOR(long, atol, const char *nptr) {
658 void *ctx;
659 ASAN_INTERCEPTOR_ENTER(ctx, atol);
660 #if SANITIZER_APPLE
661 if (UNLIKELY(!AsanInited()))
662 return REAL(atol)(nptr);
663 # endif
664 ENSURE_ASAN_INITED();
665 if (!flags()->replace_str) {
666 return REAL(atol)(nptr);
668 char *real_endptr;
669 long result = REAL(strtol)(nptr, &real_endptr, 10);
670 FixRealStrtolEndptr(nptr, &real_endptr);
671 ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
672 return result;
675 INTERCEPTOR(long long, atoll, const char *nptr) {
676 void *ctx;
677 ASAN_INTERCEPTOR_ENTER(ctx, atoll);
678 ENSURE_ASAN_INITED();
679 if (!flags()->replace_str) {
680 return REAL(atoll)(nptr);
682 char *real_endptr;
683 long long result = REAL(strtoll)(nptr, &real_endptr, 10);
684 FixRealStrtolEndptr(nptr, &real_endptr);
685 ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
686 return result;
689 #if ASAN_INTERCEPT___CXA_ATEXIT || ASAN_INTERCEPT_ATEXIT
690 static void AtCxaAtexit(void *unused) {
691 (void)unused;
692 StopInitOrderChecking();
694 #endif
696 #if ASAN_INTERCEPT___CXA_ATEXIT
697 INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
698 void *dso_handle) {
699 #if SANITIZER_APPLE
700 if (UNLIKELY(!AsanInited()))
701 return REAL(__cxa_atexit)(func, arg, dso_handle);
702 # endif
703 ENSURE_ASAN_INITED();
704 #if CAN_SANITIZE_LEAKS
705 __lsan::ScopedInterceptorDisabler disabler;
706 #endif
707 int res = REAL(__cxa_atexit)(func, arg, dso_handle);
708 REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr);
709 return res;
711 #endif // ASAN_INTERCEPT___CXA_ATEXIT
713 #if ASAN_INTERCEPT_ATEXIT
714 INTERCEPTOR(int, atexit, void (*func)()) {
715 ENSURE_ASAN_INITED();
716 #if CAN_SANITIZE_LEAKS
717 __lsan::ScopedInterceptorDisabler disabler;
718 #endif
719 // Avoid calling real atexit as it is unreachable on at least on Linux.
720 int res = REAL(__cxa_atexit)((void (*)(void *a))func, nullptr, nullptr);
721 REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr);
722 return res;
724 #endif
726 #if ASAN_INTERCEPT_PTHREAD_ATFORK
727 extern "C" {
728 extern int _pthread_atfork(void (*prepare)(), void (*parent)(),
729 void (*child)());
732 INTERCEPTOR(int, pthread_atfork, void (*prepare)(), void (*parent)(),
733 void (*child)()) {
734 #if CAN_SANITIZE_LEAKS
735 __lsan::ScopedInterceptorDisabler disabler;
736 #endif
737 // REAL(pthread_atfork) cannot be called due to symbol indirections at least
738 // on NetBSD
739 return _pthread_atfork(prepare, parent, child);
741 #endif
743 #if ASAN_INTERCEPT_VFORK
744 DEFINE_REAL(int, vfork)
745 DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(int, vfork)
746 #endif
748 // ---------------------- InitializeAsanInterceptors ---------------- {{{1
749 namespace __asan {
750 void InitializeAsanInterceptors() {
751 static bool was_called_once;
752 CHECK(!was_called_once);
753 was_called_once = true;
754 InitializePlatformInterceptors();
755 InitializeCommonInterceptors();
756 InitializeSignalInterceptors();
758 // Intercept str* functions.
759 ASAN_INTERCEPT_FUNC(strcat);
760 ASAN_INTERCEPT_FUNC(strcpy);
761 ASAN_INTERCEPT_FUNC(strncat);
762 ASAN_INTERCEPT_FUNC(strncpy);
763 ASAN_INTERCEPT_FUNC(strdup);
764 #if ASAN_INTERCEPT___STRDUP
765 ASAN_INTERCEPT_FUNC(__strdup);
766 #endif
767 #if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
768 ASAN_INTERCEPT_FUNC(index);
769 #endif
771 ASAN_INTERCEPT_FUNC(atoi);
772 ASAN_INTERCEPT_FUNC(atol);
773 ASAN_INTERCEPT_FUNC(atoll);
774 ASAN_INTERCEPT_FUNC(strtol);
775 ASAN_INTERCEPT_FUNC(strtoll);
776 # if SANITIZER_GLIBC
777 ASAN_INTERCEPT_FUNC(__isoc23_strtol);
778 ASAN_INTERCEPT_FUNC(__isoc23_strtoll);
779 # endif
781 // Intecept jump-related functions.
782 ASAN_INTERCEPT_FUNC(longjmp);
784 # if ASAN_INTERCEPT_SWAPCONTEXT
785 ASAN_INTERCEPT_FUNC(swapcontext);
786 ASAN_INTERCEPT_FUNC(makecontext);
787 # endif
788 # if ASAN_INTERCEPT__LONGJMP
789 ASAN_INTERCEPT_FUNC(_longjmp);
790 #endif
791 #if ASAN_INTERCEPT___LONGJMP_CHK
792 ASAN_INTERCEPT_FUNC(__longjmp_chk);
793 #endif
794 #if ASAN_INTERCEPT_SIGLONGJMP
795 ASAN_INTERCEPT_FUNC(siglongjmp);
796 #endif
798 // Intercept exception handling functions.
799 #if ASAN_INTERCEPT___CXA_THROW
800 ASAN_INTERCEPT_FUNC(__cxa_throw);
801 #endif
802 #if ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION
803 ASAN_INTERCEPT_FUNC(__cxa_rethrow_primary_exception);
804 #endif
805 // Indirectly intercept std::rethrow_exception.
806 #if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION
807 ASAN_INTERCEPT_FUNC(_Unwind_RaiseException);
808 #endif
809 // Indirectly intercept std::rethrow_exception.
810 #if ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION
811 ASAN_INTERCEPT_FUNC(_Unwind_SjLj_RaiseException);
812 #endif
814 // Intercept threading-related functions
815 #if ASAN_INTERCEPT_PTHREAD_CREATE
816 // TODO: this should probably have an unversioned fallback for newer arches?
817 #if defined(ASAN_PTHREAD_CREATE_VERSION)
818 ASAN_INTERCEPT_FUNC_VER(pthread_create, ASAN_PTHREAD_CREATE_VERSION);
819 #else
820 ASAN_INTERCEPT_FUNC(pthread_create);
821 #endif
822 ASAN_INTERCEPT_FUNC(pthread_join);
823 ASAN_INTERCEPT_FUNC(pthread_detach);
824 ASAN_INTERCEPT_FUNC(pthread_exit);
825 # endif
827 # if ASAN_INTERCEPT_TIMEDJOIN
828 ASAN_INTERCEPT_FUNC(pthread_timedjoin_np);
829 #endif
831 #if ASAN_INTERCEPT_TRYJOIN
832 ASAN_INTERCEPT_FUNC(pthread_tryjoin_np);
833 #endif
835 // Intercept atexit function.
836 #if ASAN_INTERCEPT___CXA_ATEXIT
837 ASAN_INTERCEPT_FUNC(__cxa_atexit);
838 #endif
840 #if ASAN_INTERCEPT_ATEXIT
841 ASAN_INTERCEPT_FUNC(atexit);
842 #endif
844 #if ASAN_INTERCEPT_PTHREAD_ATFORK
845 ASAN_INTERCEPT_FUNC(pthread_atfork);
846 #endif
848 #if ASAN_INTERCEPT_VFORK
849 ASAN_INTERCEPT_FUNC(vfork);
850 #endif
852 VReport(1, "AddressSanitizer: libc interceptors initialized\n");
855 } // namespace __asan
857 #endif // !SANITIZER_FUCHSIA