xref: /freebsd/contrib/llvm-project/compiler-rt/lib/asan/asan_interceptors.cpp (revision c8e7f78a3d28ff6e6223ed136ada8e1e2f34965e)
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.
10 //
11 // Intercept various libc functions.
12 //===----------------------------------------------------------------------===//
13 
14 #include "asan_interceptors.h"
15 
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"
29 
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
34 
35 #  if SANITIZER_POSIX
36 #    include "sanitizer_common/sanitizer_posix.h"
37 #  endif
38 
39 #  if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION || \
40       ASAN_INTERCEPT__SJLJ_UNWIND_RAISEEXCEPTION
41 #    include <unwind.h>
42 #  endif
43 
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
49 
50 namespace __asan {
51 
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))
55 
56 #  define ASAN_READ_STRING(ctx, s, n) \
57     ASAN_READ_STRING_OF_LEN((ctx), (s), internal_strlen(s), (n))
58 
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);
63   }
64 #endif
65   return internal_strnlen(s, maxlen);
66 }
67 
68 void SetThreadName(const char *name) {
69   AsanThread *t = GetCurrentThread();
70   if (t)
71     asanThreadRegistry().SetThreadName(t->tid(), name);
72 }
73 
74 int OnExit() {
75   if (CAN_SANITIZE_LEAKS && common_flags()->detect_leaks &&
76       __lsan::HasReportedLeaks()) {
77     return common_flags()->exitcode;
78   }
79   // FIXME: ask frontend whether we need to return failure.
80   return 0;
81 }
82 
83 } // namespace __asan
84 
85 // ---------------------- Wrappers ---------------- {{{1
86 using namespace __asan;
87 
88 DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr)
89 DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
90 
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 (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();                                                      \
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);                 \
137     })
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();                             \
146     } else {                                           \
147       *begin = *end = 0;                               \
148     }
149 
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);
161   }
162   return res;
163 }
164 
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);
175   }
176   return real_munmap(addr, length);
177 }
178 
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)
185 
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)
191 
192 #if CAN_SANITIZE_LEAKS
193 #define COMMON_INTERCEPTOR_STRERROR()                       \
194   __lsan::ScopedInterceptorDisabler disabler
195 #endif
196 
197 #define SIGNAL_INTERCEPTOR_ENTER() ENSURE_ASAN_INITED()
198 
199 #include "sanitizer_common/sanitizer_common_interceptors.inc"
200 #include "sanitizer_common/sanitizer_signal_interceptors.inc"
201 
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"
218 
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   thread_return_t retval = t->ThreadStart(GetTid());
226   asanThreadArgRetval().Finish(self, retval);
227   CHECK_EQ(args.arg_retval, t->get_arg());
228   return retval;
229 }
230 
231 INTERCEPTOR(int, pthread_create, void *thread, void *attr,
232             void *(*start_routine)(void *), void *arg) {
233   EnsureMainThreadIDIsCorrect();
234   // Strict init-order checking is thread-hostile.
235   if (flags()->strict_init_order)
236     StopInitOrderChecking();
237   GET_STACK_TRACE_THREAD;
238   bool detached = [attr]() {
239     int d = 0;
240     return attr && !REAL(pthread_attr_getdetachstate)(attr, &d) &&
241            IsStateDetached(d);
242   }();
243 
244   u32 current_tid = GetCurrentTidOrInvalid();
245   AsanThread *t =
246       AsanThread::Create(start_routine, arg, current_tid, &stack, detached);
247 
248   int result;
249   {
250     // Ignore all allocations made by pthread_create: thread stack/TLS may be
251     // stored by pthread for future reuse even after thread destruction, and
252     // the linked list it's stored in doesn't even hold valid pointers to the
253     // objects, the latter are calculated by obscure pointer arithmetic.
254 #    if CAN_SANITIZE_LEAKS
255     __lsan::ScopedInterceptorDisabler disabler;
256 #    endif
257     asanThreadArgRetval().Create(detached, {start_routine, arg}, [&]() -> uptr {
258       result = REAL(pthread_create)(thread, attr, asan_thread_start, t);
259       return result ? 0 : *(uptr *)(thread);
260     });
261   }
262   if (result != 0) {
263     // If the thread didn't start delete the AsanThread to avoid leaking it.
264     // Note AsanThreadContexts never get destroyed so the AsanThreadContext
265     // that was just created for the AsanThread is wasted.
266     t->Destroy();
267   }
268   return result;
269 }
270 
271 INTERCEPTOR(int, pthread_join, void *thread, void **retval) {
272   int result;
273   asanThreadArgRetval().Join((uptr)thread, [&]() {
274     result = REAL(pthread_join)(thread, retval);
275     return !result;
276   });
277   return result;
278 }
279 
280 INTERCEPTOR(int, pthread_detach, void *thread) {
281   int result;
282   asanThreadArgRetval().Detach((uptr)thread, [&]() {
283     result = REAL(pthread_detach)(thread);
284     return !result;
285   });
286   return result;
287 }
288 
289 INTERCEPTOR(int, pthread_exit, void *retval) {
290   asanThreadArgRetval().Finish(GetThreadSelf(), retval);
291   return REAL(pthread_exit)(retval);
292 }
293 
294 #    if ASAN_INTERCEPT_TRYJOIN
295 INTERCEPTOR(int, pthread_tryjoin_np, void *thread, void **ret) {
296   int result;
297   asanThreadArgRetval().Join((uptr)thread, [&]() {
298     result = REAL(pthread_tryjoin_np)(thread, ret);
299     return !result;
300   });
301   return result;
302 }
303 #    endif
304 
305 #    if ASAN_INTERCEPT_TIMEDJOIN
306 INTERCEPTOR(int, pthread_timedjoin_np, void *thread, void **ret,
307             const struct timespec *abstime) {
308   int result;
309   asanThreadArgRetval().Join((uptr)thread, [&]() {
310     result = REAL(pthread_timedjoin_np)(thread, ret, abstime);
311     return !result;
312   });
313   return result;
314 }
315 #    endif
316 
317 DEFINE_REAL_PTHREAD_FUNCTIONS
318 #endif  // ASAN_INTERCEPT_PTHREAD_CREATE
319 
320 #if ASAN_INTERCEPT_SWAPCONTEXT
321 static void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) {
322   // Only clear if we know the stack. This should be true only for contexts
323   // created with makecontext().
324   if (!ssize)
325     return;
326   // Align to page size.
327   uptr PageSize = GetPageSizeCached();
328   uptr bottom = RoundDownTo(stack, PageSize);
329   if (!AddrIsInMem(bottom))
330     return;
331   ssize += stack - bottom;
332   ssize = RoundUpTo(ssize, PageSize);
333   PoisonShadow(bottom, ssize, 0);
334 }
335 
336 INTERCEPTOR(void, makecontext, struct ucontext_t *ucp, void (*func)(), int argc,
337             ...) {
338   va_list ap;
339   uptr args[64];
340   // We don't know a better way to forward ... into REAL function. We can
341   // increase args size if neccecary.
342   CHECK_LE(argc, ARRAY_SIZE(args));
343   internal_memset(args, 0, sizeof(args));
344   va_start(ap, argc);
345   for (int i = 0; i < argc; ++i) args[i] = va_arg(ap, uptr);
346   va_end(ap);
347 
348 #    define ENUMERATE_ARRAY_4(start) \
349       args[start], args[start + 1], args[start + 2], args[start + 3]
350 #    define ENUMERATE_ARRAY_16(start)                         \
351       ENUMERATE_ARRAY_4(start), ENUMERATE_ARRAY_4(start + 4), \
352           ENUMERATE_ARRAY_4(start + 8), ENUMERATE_ARRAY_4(start + 12)
353 #    define ENUMERATE_ARRAY_64()                                             \
354       ENUMERATE_ARRAY_16(0), ENUMERATE_ARRAY_16(16), ENUMERATE_ARRAY_16(32), \
355           ENUMERATE_ARRAY_16(48)
356 
357   REAL(makecontext)
358   ((struct ucontext_t *)ucp, func, argc, ENUMERATE_ARRAY_64());
359 
360 #    undef ENUMERATE_ARRAY_4
361 #    undef ENUMERATE_ARRAY_16
362 #    undef ENUMERATE_ARRAY_64
363 
364   // Sign the stack so we can identify it for unpoisoning.
365   SignContextStack(ucp);
366 }
367 
368 INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp,
369             struct ucontext_t *ucp) {
370   static bool reported_warning = false;
371   if (!reported_warning) {
372     Report("WARNING: ASan doesn't fully support makecontext/swapcontext "
373            "functions and may produce false positives in some cases!\n");
374     reported_warning = true;
375   }
376   // Clear shadow memory for new context (it may share stack
377   // with current context).
378   uptr stack, ssize;
379   ReadContextStack(ucp, &stack, &ssize);
380   ClearShadowMemoryForContextStack(stack, ssize);
381 
382 #    if __has_attribute(__indirect_return__) && \
383         (defined(__x86_64__) || defined(__i386__))
384   int (*real_swapcontext)(struct ucontext_t *, struct ucontext_t *)
385       __attribute__((__indirect_return__)) = REAL(swapcontext);
386   int res = real_swapcontext(oucp, ucp);
387 #    else
388   int res = REAL(swapcontext)(oucp, ucp);
389 #    endif
390   // swapcontext technically does not return, but program may swap context to
391   // "oucp" later, that would look as if swapcontext() returned 0.
392   // We need to clear shadow for ucp once again, as it may be in arbitrary
393   // state.
394   ClearShadowMemoryForContextStack(stack, ssize);
395   return res;
396 }
397 #endif  // ASAN_INTERCEPT_SWAPCONTEXT
398 
399 #if SANITIZER_NETBSD
400 #define longjmp __longjmp14
401 #define siglongjmp __siglongjmp14
402 #endif
403 
404 INTERCEPTOR(void, longjmp, void *env, int val) {
405   __asan_handle_no_return();
406   REAL(longjmp)(env, val);
407 }
408 
409 #if ASAN_INTERCEPT__LONGJMP
410 INTERCEPTOR(void, _longjmp, void *env, int val) {
411   __asan_handle_no_return();
412   REAL(_longjmp)(env, val);
413 }
414 #endif
415 
416 #if ASAN_INTERCEPT___LONGJMP_CHK
417 INTERCEPTOR(void, __longjmp_chk, void *env, int val) {
418   __asan_handle_no_return();
419   REAL(__longjmp_chk)(env, val);
420 }
421 #endif
422 
423 #if ASAN_INTERCEPT_SIGLONGJMP
424 INTERCEPTOR(void, siglongjmp, void *env, int val) {
425   __asan_handle_no_return();
426   REAL(siglongjmp)(env, val);
427 }
428 #endif
429 
430 #if ASAN_INTERCEPT___CXA_THROW
431 INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
432   CHECK(REAL(__cxa_throw));
433   __asan_handle_no_return();
434   REAL(__cxa_throw)(a, b, c);
435 }
436 #endif
437 
438 #if ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION
439 INTERCEPTOR(void, __cxa_rethrow_primary_exception, void *a) {
440   CHECK(REAL(__cxa_rethrow_primary_exception));
441   __asan_handle_no_return();
442   REAL(__cxa_rethrow_primary_exception)(a);
443 }
444 #endif
445 
446 #if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION
447 INTERCEPTOR(_Unwind_Reason_Code, _Unwind_RaiseException,
448             _Unwind_Exception *object) {
449   CHECK(REAL(_Unwind_RaiseException));
450   __asan_handle_no_return();
451   return REAL(_Unwind_RaiseException)(object);
452 }
453 #endif
454 
455 #if ASAN_INTERCEPT__SJLJ_UNWIND_RAISEEXCEPTION
456 INTERCEPTOR(_Unwind_Reason_Code, _Unwind_SjLj_RaiseException,
457             _Unwind_Exception *object) {
458   CHECK(REAL(_Unwind_SjLj_RaiseException));
459   __asan_handle_no_return();
460   return REAL(_Unwind_SjLj_RaiseException)(object);
461 }
462 #endif
463 
464 #if ASAN_INTERCEPT_INDEX
465 # if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
466 INTERCEPTOR(char*, index, const char *string, int c)
467   ALIAS(WRAP(strchr));
468 # else
469 #  if SANITIZER_APPLE
470 DECLARE_REAL(char*, index, const char *string, int c)
471 OVERRIDE_FUNCTION(index, strchr);
472 #  else
473 DEFINE_REAL(char*, index, const char *string, int c)
474 #  endif
475 # endif
476 #endif  // ASAN_INTERCEPT_INDEX
477 
478 // For both strcat() and strncat() we need to check the validity of |to|
479 // argument irrespective of the |from| length.
480   INTERCEPTOR(char *, strcat, char *to, const char *from) {
481     void *ctx;
482     ASAN_INTERCEPTOR_ENTER(ctx, strcat);
483     ENSURE_ASAN_INITED();
484     if (flags()->replace_str) {
485       uptr from_length = internal_strlen(from);
486       ASAN_READ_RANGE(ctx, from, from_length + 1);
487       uptr to_length = internal_strlen(to);
488       ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
489       ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
490       // If the copying actually happens, the |from| string should not overlap
491       // with the resulting string starting at |to|, which has a length of
492       // to_length + from_length + 1.
493       if (from_length > 0) {
494         CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1, from,
495                              from_length + 1);
496       }
497     }
498     return REAL(strcat)(to, from);
499   }
500 
501 INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
502   void *ctx;
503   ASAN_INTERCEPTOR_ENTER(ctx, strncat);
504   ENSURE_ASAN_INITED();
505   if (flags()->replace_str) {
506     uptr from_length = MaybeRealStrnlen(from, size);
507     uptr copy_length = Min(size, from_length + 1);
508     ASAN_READ_RANGE(ctx, from, copy_length);
509     uptr to_length = internal_strlen(to);
510     ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
511     ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
512     if (from_length > 0) {
513       CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1,
514                            from, copy_length);
515     }
516   }
517   return REAL(strncat)(to, from, size);
518 }
519 
520 INTERCEPTOR(char *, strcpy, char *to, const char *from) {
521   void *ctx;
522   ASAN_INTERCEPTOR_ENTER(ctx, strcpy);
523 #if SANITIZER_APPLE
524   if (UNLIKELY(!asan_inited))
525     return REAL(strcpy)(to, from);
526 #endif
527   // strcpy is called from malloc_default_purgeable_zone()
528   // in __asan::ReplaceSystemAlloc() on Mac.
529   if (asan_init_is_running) {
530     return REAL(strcpy)(to, from);
531   }
532   ENSURE_ASAN_INITED();
533   if (flags()->replace_str) {
534     uptr from_size = internal_strlen(from) + 1;
535     CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size);
536     ASAN_READ_RANGE(ctx, from, from_size);
537     ASAN_WRITE_RANGE(ctx, to, from_size);
538   }
539   return REAL(strcpy)(to, from);
540 }
541 
542 INTERCEPTOR(char*, strdup, const char *s) {
543   void *ctx;
544   ASAN_INTERCEPTOR_ENTER(ctx, strdup);
545   if (UNLIKELY(!asan_inited)) return internal_strdup(s);
546   ENSURE_ASAN_INITED();
547   uptr length = internal_strlen(s);
548   if (flags()->replace_str) {
549     ASAN_READ_RANGE(ctx, s, length + 1);
550   }
551   GET_STACK_TRACE_MALLOC;
552   void *new_mem = asan_malloc(length + 1, &stack);
553   if (new_mem) {
554     REAL(memcpy)(new_mem, s, length + 1);
555   }
556   return reinterpret_cast<char*>(new_mem);
557 }
558 
559 #if ASAN_INTERCEPT___STRDUP
560 INTERCEPTOR(char*, __strdup, const char *s) {
561   void *ctx;
562   ASAN_INTERCEPTOR_ENTER(ctx, strdup);
563   if (UNLIKELY(!asan_inited)) return internal_strdup(s);
564   ENSURE_ASAN_INITED();
565   uptr length = internal_strlen(s);
566   if (flags()->replace_str) {
567     ASAN_READ_RANGE(ctx, s, length + 1);
568   }
569   GET_STACK_TRACE_MALLOC;
570   void *new_mem = asan_malloc(length + 1, &stack);
571   if (new_mem) {
572     REAL(memcpy)(new_mem, s, length + 1);
573   }
574   return reinterpret_cast<char*>(new_mem);
575 }
576 #endif // ASAN_INTERCEPT___STRDUP
577 
578 INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) {
579   void *ctx;
580   ASAN_INTERCEPTOR_ENTER(ctx, strncpy);
581   ENSURE_ASAN_INITED();
582   if (flags()->replace_str) {
583     uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1);
584     CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size);
585     ASAN_READ_RANGE(ctx, from, from_size);
586     ASAN_WRITE_RANGE(ctx, to, size);
587   }
588   return REAL(strncpy)(to, from, size);
589 }
590 
591 template <typename Fn>
592 static ALWAYS_INLINE auto StrtolImpl(void *ctx, Fn real, const char *nptr,
593                                      char **endptr, int base)
594     -> decltype(real(nullptr, nullptr, 0)) {
595   if (!flags()->replace_str)
596     return real(nptr, endptr, base);
597   char *real_endptr;
598   auto res = real(nptr, &real_endptr, base);
599   StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
600   return res;
601 }
602 
603 #  define INTERCEPTOR_STRTO_BASE(ret_type, func)                             \
604     INTERCEPTOR(ret_type, func, const char *nptr, char **endptr, int base) { \
605       void *ctx;                                                             \
606       ASAN_INTERCEPTOR_ENTER(ctx, func);                                     \
607       ENSURE_ASAN_INITED();                                                  \
608       return StrtolImpl(ctx, REAL(func), nptr, endptr, base);                \
609     }
610 
611 INTERCEPTOR_STRTO_BASE(long, strtol)
612 INTERCEPTOR_STRTO_BASE(long long, strtoll)
613 
614 #  if SANITIZER_GLIBC
615 INTERCEPTOR_STRTO_BASE(long, __isoc23_strtol)
616 INTERCEPTOR_STRTO_BASE(long long, __isoc23_strtoll)
617 #  endif
618 
619 INTERCEPTOR(int, atoi, const char *nptr) {
620   void *ctx;
621   ASAN_INTERCEPTOR_ENTER(ctx, atoi);
622 #if SANITIZER_APPLE
623   if (UNLIKELY(!asan_inited)) return REAL(atoi)(nptr);
624 #endif
625   ENSURE_ASAN_INITED();
626   if (!flags()->replace_str) {
627     return REAL(atoi)(nptr);
628   }
629   char *real_endptr;
630   // "man atoi" tells that behavior of atoi(nptr) is the same as
631   // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
632   // parsed integer can't be stored in *long* type (even if it's
633   // different from int). So, we just imitate this behavior.
634   int result = REAL(strtol)(nptr, &real_endptr, 10);
635   FixRealStrtolEndptr(nptr, &real_endptr);
636   ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
637   return result;
638 }
639 
640 INTERCEPTOR(long, atol, const char *nptr) {
641   void *ctx;
642   ASAN_INTERCEPTOR_ENTER(ctx, atol);
643 #if SANITIZER_APPLE
644   if (UNLIKELY(!asan_inited)) return REAL(atol)(nptr);
645 #endif
646   ENSURE_ASAN_INITED();
647   if (!flags()->replace_str) {
648     return REAL(atol)(nptr);
649   }
650   char *real_endptr;
651   long 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;
655 }
656 
657 INTERCEPTOR(long long, atoll, const char *nptr) {
658   void *ctx;
659   ASAN_INTERCEPTOR_ENTER(ctx, atoll);
660   ENSURE_ASAN_INITED();
661   if (!flags()->replace_str) {
662     return REAL(atoll)(nptr);
663   }
664   char *real_endptr;
665   long long result = REAL(strtoll)(nptr, &real_endptr, 10);
666   FixRealStrtolEndptr(nptr, &real_endptr);
667   ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
668   return result;
669 }
670 
671 #if ASAN_INTERCEPT___CXA_ATEXIT || ASAN_INTERCEPT_ATEXIT
672 static void AtCxaAtexit(void *unused) {
673   (void)unused;
674   StopInitOrderChecking();
675 }
676 #endif
677 
678 #if ASAN_INTERCEPT___CXA_ATEXIT
679 INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
680             void *dso_handle) {
681 #if SANITIZER_APPLE
682   if (UNLIKELY(!asan_inited)) return REAL(__cxa_atexit)(func, arg, dso_handle);
683 #endif
684   ENSURE_ASAN_INITED();
685 #if CAN_SANITIZE_LEAKS
686   __lsan::ScopedInterceptorDisabler disabler;
687 #endif
688   int res = REAL(__cxa_atexit)(func, arg, dso_handle);
689   REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr);
690   return res;
691 }
692 #endif  // ASAN_INTERCEPT___CXA_ATEXIT
693 
694 #if ASAN_INTERCEPT_ATEXIT
695 INTERCEPTOR(int, atexit, void (*func)()) {
696   ENSURE_ASAN_INITED();
697 #if CAN_SANITIZE_LEAKS
698   __lsan::ScopedInterceptorDisabler disabler;
699 #endif
700   // Avoid calling real atexit as it is unreachable on at least on Linux.
701   int res = REAL(__cxa_atexit)((void (*)(void *a))func, nullptr, nullptr);
702   REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr);
703   return res;
704 }
705 #endif
706 
707 #if ASAN_INTERCEPT_PTHREAD_ATFORK
708 extern "C" {
709 extern int _pthread_atfork(void (*prepare)(), void (*parent)(),
710                            void (*child)());
711 };
712 
713 INTERCEPTOR(int, pthread_atfork, void (*prepare)(), void (*parent)(),
714             void (*child)()) {
715 #if CAN_SANITIZE_LEAKS
716   __lsan::ScopedInterceptorDisabler disabler;
717 #endif
718   // REAL(pthread_atfork) cannot be called due to symbol indirections at least
719   // on NetBSD
720   return _pthread_atfork(prepare, parent, child);
721 }
722 #endif
723 
724 #if ASAN_INTERCEPT_VFORK
725 DEFINE_REAL(int, vfork)
726 DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(int, vfork)
727 #endif
728 
729 // ---------------------- InitializeAsanInterceptors ---------------- {{{1
730 namespace __asan {
731 void InitializeAsanInterceptors() {
732   static bool was_called_once;
733   CHECK(!was_called_once);
734   was_called_once = true;
735   InitializePlatformInterceptors();
736   InitializeCommonInterceptors();
737   InitializeSignalInterceptors();
738 
739   // Intercept str* functions.
740   ASAN_INTERCEPT_FUNC(strcat);
741   ASAN_INTERCEPT_FUNC(strcpy);
742   ASAN_INTERCEPT_FUNC(strncat);
743   ASAN_INTERCEPT_FUNC(strncpy);
744   ASAN_INTERCEPT_FUNC(strdup);
745 #if ASAN_INTERCEPT___STRDUP
746   ASAN_INTERCEPT_FUNC(__strdup);
747 #endif
748 #if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
749   ASAN_INTERCEPT_FUNC(index);
750 #endif
751 
752   ASAN_INTERCEPT_FUNC(atoi);
753   ASAN_INTERCEPT_FUNC(atol);
754   ASAN_INTERCEPT_FUNC(atoll);
755   ASAN_INTERCEPT_FUNC(strtol);
756   ASAN_INTERCEPT_FUNC(strtoll);
757 #  if SANITIZER_GLIBC
758   ASAN_INTERCEPT_FUNC(__isoc23_strtol);
759   ASAN_INTERCEPT_FUNC(__isoc23_strtoll);
760 #  endif
761 
762   // Intecept jump-related functions.
763   ASAN_INTERCEPT_FUNC(longjmp);
764 
765 #  if ASAN_INTERCEPT_SWAPCONTEXT
766   ASAN_INTERCEPT_FUNC(swapcontext);
767   ASAN_INTERCEPT_FUNC(makecontext);
768 #  endif
769 #  if ASAN_INTERCEPT__LONGJMP
770   ASAN_INTERCEPT_FUNC(_longjmp);
771 #endif
772 #if ASAN_INTERCEPT___LONGJMP_CHK
773   ASAN_INTERCEPT_FUNC(__longjmp_chk);
774 #endif
775 #if ASAN_INTERCEPT_SIGLONGJMP
776   ASAN_INTERCEPT_FUNC(siglongjmp);
777 #endif
778 
779   // Intercept exception handling functions.
780 #if ASAN_INTERCEPT___CXA_THROW
781   ASAN_INTERCEPT_FUNC(__cxa_throw);
782 #endif
783 #if ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION
784   ASAN_INTERCEPT_FUNC(__cxa_rethrow_primary_exception);
785 #endif
786   // Indirectly intercept std::rethrow_exception.
787 #if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION
788   ASAN_INTERCEPT_FUNC(_Unwind_RaiseException);
789 #endif
790   // Indirectly intercept std::rethrow_exception.
791 #if ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION
792   ASAN_INTERCEPT_FUNC(_Unwind_SjLj_RaiseException);
793 #endif
794 
795   // Intercept threading-related functions
796 #if ASAN_INTERCEPT_PTHREAD_CREATE
797 // TODO: this should probably have an unversioned fallback for newer arches?
798 #if defined(ASAN_PTHREAD_CREATE_VERSION)
799   ASAN_INTERCEPT_FUNC_VER(pthread_create, ASAN_PTHREAD_CREATE_VERSION);
800 #else
801   ASAN_INTERCEPT_FUNC(pthread_create);
802 #endif
803   ASAN_INTERCEPT_FUNC(pthread_join);
804   ASAN_INTERCEPT_FUNC(pthread_detach);
805   ASAN_INTERCEPT_FUNC(pthread_exit);
806 #  endif
807 
808 #  if ASAN_INTERCEPT_TIMEDJOIN
809   ASAN_INTERCEPT_FUNC(pthread_timedjoin_np);
810 #endif
811 
812 #if ASAN_INTERCEPT_TRYJOIN
813   ASAN_INTERCEPT_FUNC(pthread_tryjoin_np);
814 #endif
815 
816   // Intercept atexit function.
817 #if ASAN_INTERCEPT___CXA_ATEXIT
818   ASAN_INTERCEPT_FUNC(__cxa_atexit);
819 #endif
820 
821 #if ASAN_INTERCEPT_ATEXIT
822   ASAN_INTERCEPT_FUNC(atexit);
823 #endif
824 
825 #if ASAN_INTERCEPT_PTHREAD_ATFORK
826   ASAN_INTERCEPT_FUNC(pthread_atfork);
827 #endif
828 
829 #if ASAN_INTERCEPT_VFORK
830   ASAN_INTERCEPT_FUNC(vfork);
831 #endif
832 
833   VReport(1, "AddressSanitizer: libc interceptors initialized\n");
834 }
835 
836 } // namespace __asan
837 
838 #endif  // !SANITIZER_FUCHSIA
839