Home | History | Annotate | Line # | Download | only in asan
      1 //===-- asan_interceptors.cc ----------------------------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file is a part of AddressSanitizer, an address sanity checker.
     11 //
     12 // Intercept various libc functions.
     13 //===----------------------------------------------------------------------===//
     14 
     15 #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 "lsan/lsan_common.h"
     25 #include "sanitizer_common/sanitizer_libc.h"
     26 
     27 // There is no general interception at all on Fuchsia and RTEMS.
     28 // Only the functions in asan_interceptors_memintrinsics.cc are
     29 // really defined to replace libc functions.
     30 #if !SANITIZER_FUCHSIA && !SANITIZER_RTEMS
     31 
     32 #if SANITIZER_POSIX
     33 #include "sanitizer_common/sanitizer_posix.h"
     34 #endif
     35 
     36 #if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION || \
     37     ASAN_INTERCEPT__SJLJ_UNWIND_RAISEEXCEPTION
     38 #include <unwind.h>
     39 #endif
     40 
     41 #if defined(__i386) && SANITIZER_LINUX
     42 #define ASAN_PTHREAD_CREATE_VERSION "GLIBC_2.1"
     43 #elif defined(__mips__) && SANITIZER_LINUX
     44 #define ASAN_PTHREAD_CREATE_VERSION "GLIBC_2.2"
     45 #endif
     46 
     47 namespace __asan {
     48 
     49 #define ASAN_READ_STRING_OF_LEN(ctx, s, len, n)                 \
     50   ASAN_READ_RANGE((ctx), (s),                                   \
     51     common_flags()->strict_string_checks ? (len) + 1 : (n))
     52 
     53 #define ASAN_READ_STRING(ctx, s, n)                             \
     54   ASAN_READ_STRING_OF_LEN((ctx), (s), REAL(strlen)(s), (n))
     55 
     56 static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) {
     57 #if SANITIZER_INTERCEPT_STRNLEN
     58   if (REAL(strnlen)) {
     59     return REAL(strnlen)(s, maxlen);
     60   }
     61 #endif
     62   return internal_strnlen(s, maxlen);
     63 }
     64 
     65 void SetThreadName(const char *name) {
     66   AsanThread *t = GetCurrentThread();
     67   if (t)
     68     asanThreadRegistry().SetThreadName(t->tid(), name);
     69 }
     70 
     71 int OnExit() {
     72   if (CAN_SANITIZE_LEAKS && common_flags()->detect_leaks &&
     73       __lsan::HasReportedLeaks()) {
     74     return common_flags()->exitcode;
     75   }
     76   // FIXME: ask frontend whether we need to return failure.
     77   return 0;
     78 }
     79 
     80 } // namespace __asan
     81 
     82 // ---------------------- Wrappers ---------------- {{{1
     83 using namespace __asan;  // NOLINT
     84 
     85 DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr)
     86 DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
     87 
     88 #define ASAN_INTERCEPTOR_ENTER(ctx, func)                                      \
     89   AsanInterceptorContext _ctx = {#func};                                       \
     90   ctx = (void *)&_ctx;                                                         \
     91   (void) ctx;                                                                  \
     92 
     93 #define COMMON_INTERCEPT_FUNCTION(name) ASAN_INTERCEPT_FUNC(name)
     94 #define COMMON_INTERCEPT_FUNCTION_VER(name, ver)                          \
     95   ASAN_INTERCEPT_FUNC_VER(name, ver)
     96 #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
     97   ASAN_WRITE_RANGE(ctx, ptr, size)
     98 #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
     99   ASAN_READ_RANGE(ctx, ptr, size)
    100 #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...)                               \
    101   ASAN_INTERCEPTOR_ENTER(ctx, func);                                           \
    102   do {                                                                         \
    103     if (asan_init_is_running)                                                  \
    104       return REAL(func)(__VA_ARGS__);                                          \
    105     if (SANITIZER_MAC && UNLIKELY(!asan_inited))                               \
    106       return REAL(func)(__VA_ARGS__);                                          \
    107     ENSURE_ASAN_INITED();                                                      \
    108   } while (false)
    109 #define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \
    110   do {                                            \
    111   } while (false)
    112 #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
    113   do {                                         \
    114   } while (false)
    115 #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
    116   do {                                         \
    117   } while (false)
    118 #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
    119   do {                                                      \
    120   } while (false)
    121 #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name)
    122 // Should be asanThreadRegistry().SetThreadNameByUserId(thread, name)
    123 // But asan does not remember UserId's for threads (pthread_t);
    124 // and remembers all ever existed threads, so the linear search by UserId
    125 // can be slow.
    126 #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
    127   do {                                                         \
    128   } while (false)
    129 #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
    130 // Strict init-order checking is dlopen-hostile:
    131 // https://github.com/google/sanitizers/issues/178
    132 #define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag)                           \
    133   do {                                                                         \
    134     if (flags()->strict_init_order)                                            \
    135       StopInitOrderChecking();                                                 \
    136     CheckNoDeepBind(filename, flag);                                           \
    137   } while (false)
    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 #define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size) \
    151   do {                                                       \
    152     ASAN_INTERCEPTOR_ENTER(ctx, memmove);                    \
    153     ASAN_MEMMOVE_IMPL(ctx, to, from, size);                  \
    154   } while (false)
    155 
    156 #define COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size) \
    157   do {                                                      \
    158     ASAN_INTERCEPTOR_ENTER(ctx, memcpy);                    \
    159     ASAN_MEMCPY_IMPL(ctx, to, from, size);                  \
    160   } while (false)
    161 
    162 #define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size) \
    163   do {                                                      \
    164     ASAN_INTERCEPTOR_ENTER(ctx, memset);                    \
    165     ASAN_MEMSET_IMPL(ctx, block, c, size);                  \
    166   } while (false)
    167 
    168 #include "sanitizer_common/sanitizer_common_interceptors.inc"
    169 #include "sanitizer_common/sanitizer_signal_interceptors.inc"
    170 
    171 // Syscall interceptors don't have contexts, we don't support suppressions
    172 // for them.
    173 #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) ASAN_READ_RANGE(nullptr, p, s)
    174 #define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) ASAN_WRITE_RANGE(nullptr, p, s)
    175 #define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
    176   do {                                       \
    177     (void)(p);                               \
    178     (void)(s);                               \
    179   } while (false)
    180 #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \
    181   do {                                        \
    182     (void)(p);                                \
    183     (void)(s);                                \
    184   } while (false)
    185 #include "sanitizer_common/sanitizer_common_syscalls.inc"
    186 #include "sanitizer_common/sanitizer_syscalls_netbsd.inc"
    187 
    188 struct ThreadStartParam {
    189   atomic_uintptr_t t;
    190   atomic_uintptr_t is_registered;
    191 };
    192 
    193 #if ASAN_INTERCEPT_PTHREAD_CREATE
    194 static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
    195   ThreadStartParam *param = reinterpret_cast<ThreadStartParam *>(arg);
    196   AsanThread *t = nullptr;
    197   while ((t = reinterpret_cast<AsanThread *>(
    198               atomic_load(&param->t, memory_order_acquire))) == nullptr)
    199     internal_sched_yield();
    200   SetCurrentThread(t);
    201   return t->ThreadStart(GetTid(), &param->is_registered);
    202 }
    203 
    204 INTERCEPTOR(int, pthread_create, void *thread,
    205     void *attr, void *(*start_routine)(void*), void *arg) {
    206   EnsureMainThreadIDIsCorrect();
    207   // Strict init-order checking is thread-hostile.
    208   if (flags()->strict_init_order)
    209     StopInitOrderChecking();
    210   GET_STACK_TRACE_THREAD;
    211   int detached = 0;
    212   if (attr)
    213     REAL(pthread_attr_getdetachstate)(attr, &detached);
    214   ThreadStartParam param;
    215   atomic_store(&param.t, 0, memory_order_relaxed);
    216   atomic_store(&param.is_registered, 0, memory_order_relaxed);
    217   int result;
    218   {
    219     // Ignore all allocations made by pthread_create: thread stack/TLS may be
    220     // stored by pthread for future reuse even after thread destruction, and
    221     // the linked list it's stored in doesn't even hold valid pointers to the
    222     // objects, the latter are calculated by obscure pointer arithmetic.
    223 #if CAN_SANITIZE_LEAKS
    224     __lsan::ScopedInterceptorDisabler disabler;
    225 #endif
    226     result = REAL(pthread_create)(thread, attr, asan_thread_start, &param);
    227   }
    228   if (result == 0) {
    229     u32 current_tid = GetCurrentTidOrInvalid();
    230     AsanThread *t =
    231         AsanThread::Create(start_routine, arg, current_tid, &stack, detached);
    232     atomic_store(&param.t, reinterpret_cast<uptr>(t), memory_order_release);
    233     // Wait until the AsanThread object is initialized and the ThreadRegistry
    234     // entry is in "started" state. One reason for this is that after this
    235     // interceptor exits, the child thread's stack may be the only thing holding
    236     // the |arg| pointer. This may cause LSan to report a leak if leak checking
    237     // happens at a point when the interceptor has already exited, but the stack
    238     // range for the child thread is not yet known.
    239     while (atomic_load(&param.is_registered, memory_order_acquire) == 0)
    240       internal_sched_yield();
    241   }
    242   return result;
    243 }
    244 
    245 INTERCEPTOR(int, pthread_join, void *t, void **arg) {
    246   return real_pthread_join(t, arg);
    247 }
    248 
    249 DEFINE_REAL_PTHREAD_FUNCTIONS
    250 #endif  // ASAN_INTERCEPT_PTHREAD_CREATE
    251 
    252 #if ASAN_INTERCEPT_SWAPCONTEXT
    253 static void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) {
    254   // Align to page size.
    255   uptr PageSize = GetPageSizeCached();
    256   uptr bottom = stack & ~(PageSize - 1);
    257   ssize += stack - bottom;
    258   ssize = RoundUpTo(ssize, PageSize);
    259   static const uptr kMaxSaneContextStackSize = 1 << 22;  // 4 Mb
    260   if (AddrIsInMem(bottom) && ssize && ssize <= kMaxSaneContextStackSize) {
    261     PoisonShadow(bottom, ssize, 0);
    262   }
    263 }
    264 
    265 INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp,
    266             struct ucontext_t *ucp) {
    267   static bool reported_warning = false;
    268   if (!reported_warning) {
    269     Report("WARNING: ASan doesn't fully support makecontext/swapcontext "
    270            "functions and may produce false positives in some cases!\n");
    271     reported_warning = true;
    272   }
    273   // Clear shadow memory for new context (it may share stack
    274   // with current context).
    275   uptr stack, ssize;
    276   ReadContextStack(ucp, &stack, &ssize);
    277   ClearShadowMemoryForContextStack(stack, ssize);
    278 #if __has_attribute(__indirect_return__) && \
    279     (defined(__x86_64__) || defined(__i386__))
    280   int (*real_swapcontext)(struct ucontext_t *, struct ucontext_t *)
    281     __attribute__((__indirect_return__))
    282     = REAL(swapcontext);
    283   int res = real_swapcontext(oucp, ucp);
    284 #else
    285   int res = REAL(swapcontext)(oucp, ucp);
    286 #endif
    287   // swapcontext technically does not return, but program may swap context to
    288   // "oucp" later, that would look as if swapcontext() returned 0.
    289   // We need to clear shadow for ucp once again, as it may be in arbitrary
    290   // state.
    291   ClearShadowMemoryForContextStack(stack, ssize);
    292   return res;
    293 }
    294 #endif  // ASAN_INTERCEPT_SWAPCONTEXT
    295 
    296 #if SANITIZER_NETBSD
    297 #define longjmp __longjmp14
    298 #define siglongjmp __siglongjmp14
    299 #endif
    300 
    301 INTERCEPTOR(void, longjmp, void *env, int val) {
    302   __asan_handle_no_return();
    303   REAL(longjmp)(env, val);
    304 }
    305 
    306 #if ASAN_INTERCEPT__LONGJMP
    307 INTERCEPTOR(void, _longjmp, void *env, int val) {
    308   __asan_handle_no_return();
    309   REAL(_longjmp)(env, val);
    310 }
    311 #endif
    312 
    313 #if ASAN_INTERCEPT___LONGJMP_CHK
    314 INTERCEPTOR(void, __longjmp_chk, void *env, int val) {
    315   __asan_handle_no_return();
    316   REAL(__longjmp_chk)(env, val);
    317 }
    318 #endif
    319 
    320 #if ASAN_INTERCEPT_SIGLONGJMP
    321 INTERCEPTOR(void, siglongjmp, void *env, int val) {
    322   __asan_handle_no_return();
    323   REAL(siglongjmp)(env, val);
    324 }
    325 #endif
    326 
    327 #if ASAN_INTERCEPT___CXA_THROW
    328 INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
    329   CHECK(REAL(__cxa_throw));
    330   __asan_handle_no_return();
    331   REAL(__cxa_throw)(a, b, c);
    332 }
    333 #endif
    334 
    335 #if ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION
    336 INTERCEPTOR(void, __cxa_rethrow_primary_exception, void *a) {
    337   CHECK(REAL(__cxa_rethrow_primary_exception));
    338   __asan_handle_no_return();
    339   REAL(__cxa_rethrow_primary_exception)(a);
    340 }
    341 #endif
    342 
    343 #if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION
    344 INTERCEPTOR(_Unwind_Reason_Code, _Unwind_RaiseException,
    345             _Unwind_Exception *object) {
    346   CHECK(REAL(_Unwind_RaiseException));
    347   __asan_handle_no_return();
    348   return REAL(_Unwind_RaiseException)(object);
    349 }
    350 #endif
    351 
    352 #if ASAN_INTERCEPT__SJLJ_UNWIND_RAISEEXCEPTION
    353 INTERCEPTOR(_Unwind_Reason_Code, _Unwind_SjLj_RaiseException,
    354             _Unwind_Exception *object) {
    355   CHECK(REAL(_Unwind_SjLj_RaiseException));
    356   __asan_handle_no_return();
    357   return REAL(_Unwind_SjLj_RaiseException)(object);
    358 }
    359 #endif
    360 
    361 #if ASAN_INTERCEPT_INDEX
    362 # if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
    363 INTERCEPTOR(char*, index, const char *string, int c)
    364   ALIAS(WRAPPER_NAME(strchr));
    365 # else
    366 #  if SANITIZER_MAC
    367 DECLARE_REAL(char*, index, const char *string, int c)
    368 OVERRIDE_FUNCTION(index, strchr);
    369 #  else
    370 DEFINE_REAL(char*, index, const char *string, int c)
    371 #  endif
    372 # endif
    373 #endif  // ASAN_INTERCEPT_INDEX
    374 
    375 // For both strcat() and strncat() we need to check the validity of |to|
    376 // argument irrespective of the |from| length.
    377 INTERCEPTOR(char*, strcat, char *to, const char *from) {  // NOLINT
    378   void *ctx;
    379   ASAN_INTERCEPTOR_ENTER(ctx, strcat);  // NOLINT
    380   ENSURE_ASAN_INITED();
    381   if (flags()->replace_str) {
    382     uptr from_length = REAL(strlen)(from);
    383     ASAN_READ_RANGE(ctx, from, from_length + 1);
    384     uptr to_length = REAL(strlen)(to);
    385     ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
    386     ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
    387     // If the copying actually happens, the |from| string should not overlap
    388     // with the resulting string starting at |to|, which has a length of
    389     // to_length + from_length + 1.
    390     if (from_length > 0) {
    391       CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1,
    392                            from, from_length + 1);
    393     }
    394   }
    395   return REAL(strcat)(to, from);  // NOLINT
    396 }
    397 
    398 INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
    399   void *ctx;
    400   ASAN_INTERCEPTOR_ENTER(ctx, strncat);
    401   ENSURE_ASAN_INITED();
    402   if (flags()->replace_str) {
    403     uptr from_length = MaybeRealStrnlen(from, size);
    404     uptr copy_length = Min(size, from_length + 1);
    405     ASAN_READ_RANGE(ctx, from, copy_length);
    406     uptr to_length = REAL(strlen)(to);
    407     ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
    408     ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
    409     if (from_length > 0) {
    410       CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1,
    411                            from, copy_length);
    412     }
    413   }
    414   return REAL(strncat)(to, from, size);
    415 }
    416 
    417 INTERCEPTOR(char*, strcpy, char *to, const char *from) {  // NOLINT
    418   void *ctx;
    419   ASAN_INTERCEPTOR_ENTER(ctx, strcpy);  // NOLINT
    420 #if SANITIZER_MAC
    421   if (UNLIKELY(!asan_inited)) return REAL(strcpy)(to, from);  // NOLINT
    422 #endif
    423   // strcpy is called from malloc_default_purgeable_zone()
    424   // in __asan::ReplaceSystemAlloc() on Mac.
    425   if (asan_init_is_running) {
    426     return REAL(strcpy)(to, from);  // NOLINT
    427   }
    428   ENSURE_ASAN_INITED();
    429   if (flags()->replace_str) {
    430     uptr from_size = REAL(strlen)(from) + 1;
    431     CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size);
    432     ASAN_READ_RANGE(ctx, from, from_size);
    433     ASAN_WRITE_RANGE(ctx, to, from_size);
    434   }
    435   return REAL(strcpy)(to, from);  // NOLINT
    436 }
    437 
    438 INTERCEPTOR(char*, strdup, const char *s) {
    439   void *ctx;
    440   ASAN_INTERCEPTOR_ENTER(ctx, strdup);
    441   if (UNLIKELY(!asan_inited)) return internal_strdup(s);
    442   ENSURE_ASAN_INITED();
    443   uptr length = REAL(strlen)(s);
    444   if (flags()->replace_str) {
    445     ASAN_READ_RANGE(ctx, s, length + 1);
    446   }
    447   GET_STACK_TRACE_MALLOC;
    448   void *new_mem = asan_malloc(length + 1, &stack);
    449   REAL(memcpy)(new_mem, s, length + 1);
    450   return reinterpret_cast<char*>(new_mem);
    451 }
    452 
    453 #if ASAN_INTERCEPT___STRDUP
    454 INTERCEPTOR(char*, __strdup, const char *s) {
    455   void *ctx;
    456   ASAN_INTERCEPTOR_ENTER(ctx, strdup);
    457   if (UNLIKELY(!asan_inited)) return internal_strdup(s);
    458   ENSURE_ASAN_INITED();
    459   uptr length = REAL(strlen)(s);
    460   if (flags()->replace_str) {
    461     ASAN_READ_RANGE(ctx, s, length + 1);
    462   }
    463   GET_STACK_TRACE_MALLOC;
    464   void *new_mem = asan_malloc(length + 1, &stack);
    465   REAL(memcpy)(new_mem, s, length + 1);
    466   return reinterpret_cast<char*>(new_mem);
    467 }
    468 #endif // ASAN_INTERCEPT___STRDUP
    469 
    470 INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) {
    471   void *ctx;
    472   ASAN_INTERCEPTOR_ENTER(ctx, strncpy);
    473   ENSURE_ASAN_INITED();
    474   if (flags()->replace_str) {
    475     uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1);
    476     CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size);
    477     ASAN_READ_RANGE(ctx, from, from_size);
    478     ASAN_WRITE_RANGE(ctx, to, size);
    479   }
    480   return REAL(strncpy)(to, from, size);
    481 }
    482 
    483 INTERCEPTOR(long, strtol, const char *nptr,  // NOLINT
    484             char **endptr, int base) {
    485   void *ctx;
    486   ASAN_INTERCEPTOR_ENTER(ctx, strtol);
    487   ENSURE_ASAN_INITED();
    488   if (!flags()->replace_str) {
    489     return REAL(strtol)(nptr, endptr, base);
    490   }
    491   char *real_endptr;
    492   long result = REAL(strtol)(nptr, &real_endptr, base);  // NOLINT
    493   StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
    494   return result;
    495 }
    496 
    497 INTERCEPTOR(int, atoi, const char *nptr) {
    498   void *ctx;
    499   ASAN_INTERCEPTOR_ENTER(ctx, atoi);
    500 #if SANITIZER_MAC
    501   if (UNLIKELY(!asan_inited)) return REAL(atoi)(nptr);
    502 #endif
    503   ENSURE_ASAN_INITED();
    504   if (!flags()->replace_str) {
    505     return REAL(atoi)(nptr);
    506   }
    507   char *real_endptr;
    508   // "man atoi" tells that behavior of atoi(nptr) is the same as
    509   // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
    510   // parsed integer can't be stored in *long* type (even if it's
    511   // different from int). So, we just imitate this behavior.
    512   int result = REAL(strtol)(nptr, &real_endptr, 10);
    513   FixRealStrtolEndptr(nptr, &real_endptr);
    514   ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
    515   return result;
    516 }
    517 
    518 INTERCEPTOR(long, atol, const char *nptr) {  // NOLINT
    519   void *ctx;
    520   ASAN_INTERCEPTOR_ENTER(ctx, atol);
    521 #if SANITIZER_MAC
    522   if (UNLIKELY(!asan_inited)) return REAL(atol)(nptr);
    523 #endif
    524   ENSURE_ASAN_INITED();
    525   if (!flags()->replace_str) {
    526     return REAL(atol)(nptr);
    527   }
    528   char *real_endptr;
    529   long result = REAL(strtol)(nptr, &real_endptr, 10);  // NOLINT
    530   FixRealStrtolEndptr(nptr, &real_endptr);
    531   ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
    532   return result;
    533 }
    534 
    535 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
    536 INTERCEPTOR(long long, strtoll, const char *nptr,  // NOLINT
    537             char **endptr, int base) {
    538   void *ctx;
    539   ASAN_INTERCEPTOR_ENTER(ctx, strtoll);
    540   ENSURE_ASAN_INITED();
    541   if (!flags()->replace_str) {
    542     return REAL(strtoll)(nptr, endptr, base);
    543   }
    544   char *real_endptr;
    545   long long result = REAL(strtoll)(nptr, &real_endptr, base);  // NOLINT
    546   StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
    547   return result;
    548 }
    549 
    550 INTERCEPTOR(long long, atoll, const char *nptr) {  // NOLINT
    551   void *ctx;
    552   ASAN_INTERCEPTOR_ENTER(ctx, atoll);
    553   ENSURE_ASAN_INITED();
    554   if (!flags()->replace_str) {
    555     return REAL(atoll)(nptr);
    556   }
    557   char *real_endptr;
    558   long long result = REAL(strtoll)(nptr, &real_endptr, 10);  // NOLINT
    559   FixRealStrtolEndptr(nptr, &real_endptr);
    560   ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
    561   return result;
    562 }
    563 #endif  // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
    564 
    565 #if ASAN_INTERCEPT___CXA_ATEXIT
    566 static void AtCxaAtexit(void *unused) {
    567   (void)unused;
    568   StopInitOrderChecking();
    569 }
    570 
    571 INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
    572             void *dso_handle) {
    573 #if SANITIZER_MAC
    574   if (UNLIKELY(!asan_inited)) return REAL(__cxa_atexit)(func, arg, dso_handle);
    575 #endif
    576   ENSURE_ASAN_INITED();
    577   int res = REAL(__cxa_atexit)(func, arg, dso_handle);
    578   REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr);
    579   return res;
    580 }
    581 #endif  // ASAN_INTERCEPT___CXA_ATEXIT
    582 
    583 // ---------------------- InitializeAsanInterceptors ---------------- {{{1
    584 namespace __asan {
    585 void InitializeAsanInterceptors() {
    586   static bool was_called_once;
    587   CHECK(!was_called_once);
    588   was_called_once = true;
    589   InitializeCommonInterceptors();
    590   InitializeSignalInterceptors();
    591 
    592   // Intercept str* functions.
    593   ASAN_INTERCEPT_FUNC(strcat);  // NOLINT
    594   ASAN_INTERCEPT_FUNC(strcpy);  // NOLINT
    595   ASAN_INTERCEPT_FUNC(strncat);
    596   ASAN_INTERCEPT_FUNC(strncpy);
    597   ASAN_INTERCEPT_FUNC(strdup);
    598 #if ASAN_INTERCEPT___STRDUP
    599   ASAN_INTERCEPT_FUNC(__strdup);
    600 #endif
    601 #if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
    602   ASAN_INTERCEPT_FUNC(index);
    603 #endif
    604 
    605   ASAN_INTERCEPT_FUNC(atoi);
    606   ASAN_INTERCEPT_FUNC(atol);
    607   ASAN_INTERCEPT_FUNC(strtol);
    608 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
    609   ASAN_INTERCEPT_FUNC(atoll);
    610   ASAN_INTERCEPT_FUNC(strtoll);
    611 #endif
    612 
    613   // Intecept jump-related functions.
    614   ASAN_INTERCEPT_FUNC(longjmp);
    615 
    616 #if ASAN_INTERCEPT_SWAPCONTEXT
    617   ASAN_INTERCEPT_FUNC(swapcontext);
    618 #endif
    619 #if ASAN_INTERCEPT__LONGJMP
    620   ASAN_INTERCEPT_FUNC(_longjmp);
    621 #endif
    622 #if ASAN_INTERCEPT___LONGJMP_CHK
    623   ASAN_INTERCEPT_FUNC(__longjmp_chk);
    624 #endif
    625 #if ASAN_INTERCEPT_SIGLONGJMP
    626   ASAN_INTERCEPT_FUNC(siglongjmp);
    627 #endif
    628 
    629   // Intercept exception handling functions.
    630 #if ASAN_INTERCEPT___CXA_THROW
    631   ASAN_INTERCEPT_FUNC(__cxa_throw);
    632 #endif
    633 #if ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION
    634   ASAN_INTERCEPT_FUNC(__cxa_rethrow_primary_exception);
    635 #endif
    636   // Indirectly intercept std::rethrow_exception.
    637 #if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION
    638   INTERCEPT_FUNCTION(_Unwind_RaiseException);
    639 #endif
    640   // Indirectly intercept std::rethrow_exception.
    641 #if ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION
    642   INTERCEPT_FUNCTION(_Unwind_SjLj_RaiseException);
    643 #endif
    644 
    645   // Intercept threading-related functions
    646 #if ASAN_INTERCEPT_PTHREAD_CREATE
    647 #if defined(ASAN_PTHREAD_CREATE_VERSION)
    648   ASAN_INTERCEPT_FUNC_VER(pthread_create, ASAN_PTHREAD_CREATE_VERSION);
    649 #else
    650   ASAN_INTERCEPT_FUNC(pthread_create);
    651 #endif
    652   ASAN_INTERCEPT_FUNC(pthread_join);
    653 #endif
    654 
    655   // Intercept atexit function.
    656 #if ASAN_INTERCEPT___CXA_ATEXIT
    657   ASAN_INTERCEPT_FUNC(__cxa_atexit);
    658 #endif
    659 
    660   InitializePlatformInterceptors();
    661 
    662   VReport(1, "AddressSanitizer: libc interceptors initialized\n");
    663 }
    664 
    665 } // namespace __asan
    666 
    667 #endif  // !SANITIZER_FUCHSIA
    668