Home | History | Annotate | 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 #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 "sanitizer_common/sanitizer_libc.h"
     24 
     25 namespace __asan {
     26 
     27 // Return true if we can quickly decide that the region is unpoisoned.
     28 static inline bool QuickCheckForUnpoisonedRegion(uptr beg, uptr size) {
     29   if (size == 0) return true;
     30   if (size <= 32)
     31     return !AddressIsPoisoned(beg) &&
     32            !AddressIsPoisoned(beg + size - 1) &&
     33            !AddressIsPoisoned(beg + size / 2);
     34   return false;
     35 }
     36 
     37 // We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE,
     38 // and ASAN_WRITE_RANGE as macro instead of function so
     39 // that no extra frames are created, and stack trace contains
     40 // relevant information only.
     41 // We check all shadow bytes.
     42 #define ACCESS_MEMORY_RANGE(offset, size, isWrite) do {                 \
     43     uptr __offset = (uptr)(offset);                                     \
     44     uptr __size = (uptr)(size);                                         \
     45     uptr __bad = 0;                                                     \
     46     if (__offset > __offset + __size) {                                 \
     47       GET_STACK_TRACE_FATAL_HERE;                                       \
     48       ReportStringFunctionSizeOverflow(__offset, __size, &stack);       \
     49     }                                                                   \
     50     if (!QuickCheckForUnpoisonedRegion(__offset, __size) &&             \
     51         (__bad = __asan_region_is_poisoned(__offset, __size))) {        \
     52       GET_CURRENT_PC_BP_SP;                                             \
     53       __asan_report_error(pc, bp, sp, __bad, isWrite, __size);          \
     54     }                                                                   \
     55   } while (0)
     56 
     57 #define ASAN_READ_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size, false)
     58 #define ASAN_WRITE_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size, true)
     59 
     60 // Behavior of functions like "memcpy" or "strcpy" is undefined
     61 // if memory intervals overlap. We report error in this case.
     62 // Macro is used to avoid creation of new frames.
     63 static inline bool RangesOverlap(const char *offset1, uptr length1,
     64                                  const char *offset2, uptr length2) {
     65   return !((offset1 + length1 <= offset2) || (offset2 + length2 <= offset1));
     66 }
     67 #define CHECK_RANGES_OVERLAP(name, _offset1, length1, _offset2, length2) do { \
     68   const char *offset1 = (const char*)_offset1; \
     69   const char *offset2 = (const char*)_offset2; \
     70   if (RangesOverlap(offset1, length1, offset2, length2)) { \
     71     GET_STACK_TRACE_FATAL_HERE; \
     72     ReportStringFunctionMemoryRangesOverlap(name, offset1, length1, \
     73                                             offset2, length2, &stack); \
     74   } \
     75 } while (0)
     76 
     77 static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) {
     78 #if ASAN_INTERCEPT_STRNLEN
     79   if (REAL(strnlen) != 0) {
     80     return REAL(strnlen)(s, maxlen);
     81   }
     82 #endif
     83   return internal_strnlen(s, maxlen);
     84 }
     85 
     86 void SetThreadName(const char *name) {
     87   AsanThread *t = GetCurrentThread();
     88   if (t)
     89     asanThreadRegistry().SetThreadName(t->tid(), name);
     90 }
     91 
     92 int OnExit() {
     93   // FIXME: ask frontend whether we need to return failure.
     94   return 0;
     95 }
     96 
     97 }  // namespace __asan
     98 
     99 // ---------------------- Wrappers ---------------- {{{1
    100 using namespace __asan;  // NOLINT
    101 
    102 DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr)
    103 DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
    104 
    105 #if !SANITIZER_MAC
    106 #define ASAN_INTERCEPT_FUNC(name)                                        \
    107   do {                                                                   \
    108     if ((!INTERCEPT_FUNCTION(name) || !REAL(name)))                      \
    109       VReport(1, "AddressSanitizer: failed to intercept '" #name "'\n"); \
    110   } while (0)
    111 #else
    112 // OS X interceptors don't need to be initialized with INTERCEPT_FUNCTION.
    113 #define ASAN_INTERCEPT_FUNC(name)
    114 #endif  // SANITIZER_MAC
    115 
    116 #define COMMON_INTERCEPT_FUNCTION(name) ASAN_INTERCEPT_FUNC(name)
    117 #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
    118   ASAN_WRITE_RANGE(ptr, size)
    119 #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) ASAN_READ_RANGE(ptr, size)
    120 #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...)                               \
    121   do {                                                                         \
    122     if (asan_init_is_running)                                                  \
    123       return REAL(func)(__VA_ARGS__);                                          \
    124     ctx = 0;                                                                   \
    125     (void) ctx;                                                                \
    126     if (SANITIZER_MAC && UNLIKELY(!asan_inited))                               \
    127       return REAL(func)(__VA_ARGS__);                                          \
    128     ENSURE_ASAN_INITED();                                                      \
    129   } while (false)
    130 #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
    131   do {                                         \
    132   } while (false)
    133 #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
    134   do {                                         \
    135   } while (false)
    136 #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
    137   do {                                                      \
    138   } while (false)
    139 #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name)
    140 // Should be asanThreadRegistry().SetThreadNameByUserId(thread, name)
    141 // But asan does not remember UserId's for threads (pthread_t);
    142 // and remembers all ever existed threads, so the linear search by UserId
    143 // can be slow.
    144 #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
    145   do {                                                         \
    146   } while (false)
    147 #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
    148 #define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
    149 #define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, res) CovUpdateMapping()
    150 #define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() CovUpdateMapping()
    151 #include "sanitizer_common/sanitizer_common_interceptors.inc"
    152 
    153 #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) ASAN_READ_RANGE(p, s)
    154 #define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) ASAN_WRITE_RANGE(p, s)
    155 #define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
    156   do {                                       \
    157     (void)(p);                               \
    158     (void)(s);                               \
    159   } while (false)
    160 #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \
    161   do {                                        \
    162     (void)(p);                                \
    163     (void)(s);                                \
    164   } while (false)
    165 #include "sanitizer_common/sanitizer_common_syscalls.inc"
    166 
    167 static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
    168   AsanThread *t = (AsanThread*)arg;
    169   SetCurrentThread(t);
    170   return t->ThreadStart(GetTid());
    171 }
    172 
    173 #if ASAN_INTERCEPT_PTHREAD_CREATE
    174 INTERCEPTOR(int, pthread_create, void *thread,
    175     void *attr, void *(*start_routine)(void*), void *arg) {
    176   EnsureMainThreadIDIsCorrect();
    177   // Strict init-order checking in thread-hostile.
    178   if (flags()->strict_init_order)
    179     StopInitOrderChecking();
    180   GET_STACK_TRACE_THREAD;
    181   int detached = 0;
    182   if (attr != 0)
    183     REAL(pthread_attr_getdetachstate)(attr, &detached);
    184 
    185   u32 current_tid = GetCurrentTidOrInvalid();
    186   AsanThread *t = AsanThread::Create(start_routine, arg);
    187   CreateThreadContextArgs args = { t, &stack };
    188   asanThreadRegistry().CreateThread(*(uptr*)t, detached, current_tid, &args);
    189   return REAL(pthread_create)(thread, attr, asan_thread_start, t);
    190 }
    191 #endif  // ASAN_INTERCEPT_PTHREAD_CREATE
    192 
    193 #if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
    194 
    195 #if SANITIZER_ANDROID
    196 INTERCEPTOR(void*, bsd_signal, int signum, void *handler) {
    197   if (!AsanInterceptsSignal(signum) ||
    198       common_flags()->allow_user_segv_handler) {
    199     return REAL(bsd_signal)(signum, handler);
    200   }
    201   return 0;
    202 }
    203 #else
    204 INTERCEPTOR(void*, signal, int signum, void *handler) {
    205   if (!AsanInterceptsSignal(signum) ||
    206       common_flags()->allow_user_segv_handler) {
    207     return REAL(signal)(signum, handler);
    208   }
    209   return 0;
    210 }
    211 #endif
    212 
    213 INTERCEPTOR(int, sigaction, int signum, const struct sigaction *act,
    214                             struct sigaction *oldact) {
    215   if (!AsanInterceptsSignal(signum) ||
    216       common_flags()->allow_user_segv_handler) {
    217     return REAL(sigaction)(signum, act, oldact);
    218   }
    219   return 0;
    220 }
    221 
    222 namespace __sanitizer {
    223 int real_sigaction(int signum, const void *act, void *oldact) {
    224   return REAL(sigaction)(signum,
    225                          (struct sigaction *)act, (struct sigaction *)oldact);
    226 }
    227 }  // namespace __sanitizer
    228 
    229 #elif SANITIZER_POSIX
    230 // We need to have defined REAL(sigaction) on posix systems.
    231 DEFINE_REAL(int, sigaction, int signum, const struct sigaction *act,
    232     struct sigaction *oldact)
    233 #endif  // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
    234 
    235 #if ASAN_INTERCEPT_SWAPCONTEXT
    236 static void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) {
    237   // Align to page size.
    238   uptr PageSize = GetPageSizeCached();
    239   uptr bottom = stack & ~(PageSize - 1);
    240   ssize += stack - bottom;
    241   ssize = RoundUpTo(ssize, PageSize);
    242   static const uptr kMaxSaneContextStackSize = 1 << 22;  // 4 Mb
    243   if (ssize && ssize <= kMaxSaneContextStackSize) {
    244     PoisonShadow(bottom, ssize, 0);
    245   }
    246 }
    247 
    248 INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp,
    249             struct ucontext_t *ucp) {
    250   static bool reported_warning = false;
    251   if (!reported_warning) {
    252     Report("WARNING: ASan doesn't fully support makecontext/swapcontext "
    253            "functions and may produce false positives in some cases!\n");
    254     reported_warning = true;
    255   }
    256   // Clear shadow memory for new context (it may share stack
    257   // with current context).
    258   uptr stack, ssize;
    259   ReadContextStack(ucp, &stack, &ssize);
    260   ClearShadowMemoryForContextStack(stack, ssize);
    261   int res = REAL(swapcontext)(oucp, ucp);
    262   // swapcontext technically does not return, but program may swap context to
    263   // "oucp" later, that would look as if swapcontext() returned 0.
    264   // We need to clear shadow for ucp once again, as it may be in arbitrary
    265   // state.
    266   ClearShadowMemoryForContextStack(stack, ssize);
    267   return res;
    268 }
    269 #endif  // ASAN_INTERCEPT_SWAPCONTEXT
    270 
    271 INTERCEPTOR(void, longjmp, void *env, int val) {
    272   __asan_handle_no_return();
    273   REAL(longjmp)(env, val);
    274 }
    275 
    276 #if ASAN_INTERCEPT__LONGJMP
    277 INTERCEPTOR(void, _longjmp, void *env, int val) {
    278   __asan_handle_no_return();
    279   REAL(_longjmp)(env, val);
    280 }
    281 #endif
    282 
    283 #if ASAN_INTERCEPT_SIGLONGJMP
    284 INTERCEPTOR(void, siglongjmp, void *env, int val) {
    285   __asan_handle_no_return();
    286   REAL(siglongjmp)(env, val);
    287 }
    288 #endif
    289 
    290 #if ASAN_INTERCEPT___CXA_THROW
    291 INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
    292   CHECK(REAL(__cxa_throw));
    293   __asan_handle_no_return();
    294   REAL(__cxa_throw)(a, b, c);
    295 }
    296 #endif
    297 
    298 #if ASAN_INTERCEPT_MLOCKX
    299 // intercept mlock and friends.
    300 // Since asan maps 16T of RAM, mlock is completely unfriendly to asan.
    301 // All functions return 0 (success).
    302 static void MlockIsUnsupported() {
    303   static bool printed = false;
    304   if (printed) return;
    305   printed = true;
    306   VPrintf(1,
    307           "INFO: AddressSanitizer ignores "
    308           "mlock/mlockall/munlock/munlockall\n");
    309 }
    310 
    311 INTERCEPTOR(int, mlock, const void *addr, uptr len) {
    312   MlockIsUnsupported();
    313   return 0;
    314 }
    315 
    316 INTERCEPTOR(int, munlock, const void *addr, uptr len) {
    317   MlockIsUnsupported();
    318   return 0;
    319 }
    320 
    321 INTERCEPTOR(int, mlockall, int flags) {
    322   MlockIsUnsupported();
    323   return 0;
    324 }
    325 
    326 INTERCEPTOR(int, munlockall, void) {
    327   MlockIsUnsupported();
    328   return 0;
    329 }
    330 #endif
    331 
    332 static inline int CharCmp(unsigned char c1, unsigned char c2) {
    333   return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
    334 }
    335 
    336 INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {
    337   if (UNLIKELY(!asan_inited)) return internal_memcmp(a1, a2, size);
    338   ENSURE_ASAN_INITED();
    339   if (flags()->replace_intrin) {
    340     if (flags()->strict_memcmp) {
    341       // Check the entire regions even if the first bytes of the buffers are
    342       // different.
    343       ASAN_READ_RANGE(a1, size);
    344       ASAN_READ_RANGE(a2, size);
    345       // Fallthrough to REAL(memcmp) below.
    346     } else {
    347       unsigned char c1 = 0, c2 = 0;
    348       const unsigned char *s1 = (const unsigned char*)a1;
    349       const unsigned char *s2 = (const unsigned char*)a2;
    350       uptr i;
    351       for (i = 0; i < size; i++) {
    352         c1 = s1[i];
    353         c2 = s2[i];
    354         if (c1 != c2) break;
    355       }
    356       ASAN_READ_RANGE(s1, Min(i + 1, size));
    357       ASAN_READ_RANGE(s2, Min(i + 1, size));
    358       return CharCmp(c1, c2);
    359     }
    360   }
    361   return REAL(memcmp(a1, a2, size));
    362 }
    363 
    364 void *__asan_memcpy(void *to, const void *from, uptr size) {
    365   if (UNLIKELY(!asan_inited)) return internal_memcpy(to, from, size);
    366   // memcpy is called during __asan_init() from the internals
    367   // of printf(...).
    368   if (asan_init_is_running) {
    369     return REAL(memcpy)(to, from, size);
    370   }
    371   ENSURE_ASAN_INITED();
    372   if (flags()->replace_intrin) {
    373     if (to != from) {
    374       // We do not treat memcpy with to==from as a bug.
    375       // See http://llvm.org/bugs/show_bug.cgi?id=11763.
    376       CHECK_RANGES_OVERLAP("memcpy", to, size, from, size);
    377     }
    378     ASAN_READ_RANGE(from, size);
    379     ASAN_WRITE_RANGE(to, size);
    380   }
    381   return REAL(memcpy)(to, from, size);
    382 }
    383 
    384 void *__asan_memset(void *block, int c, uptr size) {
    385   if (UNLIKELY(!asan_inited)) return internal_memset(block, c, size);
    386   // memset is called inside Printf.
    387   if (asan_init_is_running) {
    388     return REAL(memset)(block, c, size);
    389   }
    390   ENSURE_ASAN_INITED();
    391   if (flags()->replace_intrin) {
    392     ASAN_WRITE_RANGE(block, size);
    393   }
    394   return REAL(memset)(block, c, size);
    395 }
    396 
    397 void *__asan_memmove(void *to, const void *from, uptr size) {
    398   if (UNLIKELY(!asan_inited))
    399     return internal_memmove(to, from, size);
    400   ENSURE_ASAN_INITED();
    401   if (flags()->replace_intrin) {
    402     ASAN_READ_RANGE(from, size);
    403     ASAN_WRITE_RANGE(to, size);
    404   }
    405   return internal_memmove(to, from, size);
    406 }
    407 
    408 INTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) {
    409   return __asan_memmove(to, from, size);
    410 }
    411 
    412 INTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) {
    413 #if !SANITIZER_MAC
    414   return __asan_memcpy(to, from, size);
    415 #else
    416   // At least on 10.7 and 10.8 both memcpy() and memmove() are being replaced
    417   // with WRAP(memcpy). As a result, false positives are reported for memmove()
    418   // calls. If we just disable error reporting with
    419   // ASAN_OPTIONS=replace_intrin=0, memmove() is still replaced with
    420   // internal_memcpy(), which may lead to crashes, see
    421   // http://llvm.org/bugs/show_bug.cgi?id=16362.
    422   return __asan_memmove(to, from, size);
    423 #endif  // !SANITIZER_MAC
    424 }
    425 
    426 INTERCEPTOR(void*, memset, void *block, int c, uptr size) {
    427   return __asan_memset(block, c, size);
    428 }
    429 
    430 INTERCEPTOR(char*, strchr, const char *str, int c) {
    431   if (UNLIKELY(!asan_inited)) return internal_strchr(str, c);
    432   // strchr is called inside create_purgeable_zone() when MallocGuardEdges=1 is
    433   // used.
    434   if (asan_init_is_running) {
    435     return REAL(strchr)(str, c);
    436   }
    437   ENSURE_ASAN_INITED();
    438   char *result = REAL(strchr)(str, c);
    439   if (flags()->replace_str) {
    440     uptr bytes_read = (result ? result - str : REAL(strlen)(str)) + 1;
    441     ASAN_READ_RANGE(str, bytes_read);
    442   }
    443   return result;
    444 }
    445 
    446 #if ASAN_INTERCEPT_INDEX
    447 # if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
    448 INTERCEPTOR(char*, index, const char *string, int c)
    449   ALIAS(WRAPPER_NAME(strchr));
    450 # else
    451 #  if SANITIZER_MAC
    452 DECLARE_REAL(char*, index, const char *string, int c)
    453 OVERRIDE_FUNCTION(index, strchr);
    454 #  else
    455 DEFINE_REAL(char*, index, const char *string, int c)
    456 #  endif
    457 # endif
    458 #endif  // ASAN_INTERCEPT_INDEX
    459 
    460 // For both strcat() and strncat() we need to check the validity of |to|
    461 // argument irrespective of the |from| length.
    462 INTERCEPTOR(char*, strcat, char *to, const char *from) {  // NOLINT
    463   ENSURE_ASAN_INITED();
    464   if (flags()->replace_str) {
    465     uptr from_length = REAL(strlen)(from);
    466     ASAN_READ_RANGE(from, from_length + 1);
    467     uptr to_length = REAL(strlen)(to);
    468     ASAN_READ_RANGE(to, to_length);
    469     ASAN_WRITE_RANGE(to + to_length, from_length + 1);
    470     // If the copying actually happens, the |from| string should not overlap
    471     // with the resulting string starting at |to|, which has a length of
    472     // to_length + from_length + 1.
    473     if (from_length > 0) {
    474       CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1,
    475                            from, from_length + 1);
    476     }
    477   }
    478   return REAL(strcat)(to, from);  // NOLINT
    479 }
    480 
    481 INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
    482   ENSURE_ASAN_INITED();
    483   if (flags()->replace_str) {
    484     uptr from_length = MaybeRealStrnlen(from, size);
    485     uptr copy_length = Min(size, from_length + 1);
    486     ASAN_READ_RANGE(from, copy_length);
    487     uptr to_length = REAL(strlen)(to);
    488     ASAN_READ_RANGE(to, to_length);
    489     ASAN_WRITE_RANGE(to + to_length, from_length + 1);
    490     if (from_length > 0) {
    491       CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1,
    492                            from, copy_length);
    493     }
    494   }
    495   return REAL(strncat)(to, from, size);
    496 }
    497 
    498 INTERCEPTOR(char*, strcpy, char *to, const char *from) {  // NOLINT
    499 #if SANITIZER_MAC
    500   if (UNLIKELY(!asan_inited)) return REAL(strcpy)(to, from);  // NOLINT
    501 #endif
    502   // strcpy is called from malloc_default_purgeable_zone()
    503   // in __asan::ReplaceSystemAlloc() on Mac.
    504   if (asan_init_is_running) {
    505     return REAL(strcpy)(to, from);  // NOLINT
    506   }
    507   ENSURE_ASAN_INITED();
    508   if (flags()->replace_str) {
    509     uptr from_size = REAL(strlen)(from) + 1;
    510     CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size);
    511     ASAN_READ_RANGE(from, from_size);
    512     ASAN_WRITE_RANGE(to, from_size);
    513   }
    514   return REAL(strcpy)(to, from);  // NOLINT
    515 }
    516 
    517 #if ASAN_INTERCEPT_STRDUP
    518 INTERCEPTOR(char*, strdup, const char *s) {
    519   if (UNLIKELY(!asan_inited)) return internal_strdup(s);
    520   ENSURE_ASAN_INITED();
    521   uptr length = REAL(strlen)(s);
    522   if (flags()->replace_str) {
    523     ASAN_READ_RANGE(s, length + 1);
    524   }
    525   GET_STACK_TRACE_MALLOC;
    526   void *new_mem = asan_malloc(length + 1, &stack);
    527   REAL(memcpy)(new_mem, s, length + 1);
    528   return reinterpret_cast<char*>(new_mem);
    529 }
    530 #endif
    531 
    532 INTERCEPTOR(uptr, strlen, const char *s) {
    533   if (UNLIKELY(!asan_inited)) return internal_strlen(s);
    534   // strlen is called from malloc_default_purgeable_zone()
    535   // in __asan::ReplaceSystemAlloc() on Mac.
    536   if (asan_init_is_running) {
    537     return REAL(strlen)(s);
    538   }
    539   ENSURE_ASAN_INITED();
    540   uptr length = REAL(strlen)(s);
    541   if (flags()->replace_str) {
    542     ASAN_READ_RANGE(s, length + 1);
    543   }
    544   return length;
    545 }
    546 
    547 INTERCEPTOR(uptr, wcslen, const wchar_t *s) {
    548   uptr length = REAL(wcslen)(s);
    549   if (!asan_init_is_running) {
    550     ENSURE_ASAN_INITED();
    551     ASAN_READ_RANGE(s, (length + 1) * sizeof(wchar_t));
    552   }
    553   return length;
    554 }
    555 
    556 INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) {
    557   ENSURE_ASAN_INITED();
    558   if (flags()->replace_str) {
    559     uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1);
    560     CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size);
    561     ASAN_READ_RANGE(from, from_size);
    562     ASAN_WRITE_RANGE(to, size);
    563   }
    564   return REAL(strncpy)(to, from, size);
    565 }
    566 
    567 #if ASAN_INTERCEPT_STRNLEN
    568 INTERCEPTOR(uptr, strnlen, const char *s, uptr maxlen) {
    569   ENSURE_ASAN_INITED();
    570   uptr length = REAL(strnlen)(s, maxlen);
    571   if (flags()->replace_str) {
    572     ASAN_READ_RANGE(s, Min(length + 1, maxlen));
    573   }
    574   return length;
    575 }
    576 #endif  // ASAN_INTERCEPT_STRNLEN
    577 
    578 static inline bool IsValidStrtolBase(int base) {
    579   return (base == 0) || (2 <= base && base <= 36);
    580 }
    581 
    582 static inline void FixRealStrtolEndptr(const char *nptr, char **endptr) {
    583   CHECK(endptr);
    584   if (nptr == *endptr) {
    585     // No digits were found at strtol call, we need to find out the last
    586     // symbol accessed by strtoll on our own.
    587     // We get this symbol by skipping leading blanks and optional +/- sign.
    588     while (IsSpace(*nptr)) nptr++;
    589     if (*nptr == '+' || *nptr == '-') nptr++;
    590     *endptr = (char*)nptr;
    591   }
    592   CHECK(*endptr >= nptr);
    593 }
    594 
    595 INTERCEPTOR(long, strtol, const char *nptr,  // NOLINT
    596             char **endptr, int base) {
    597   ENSURE_ASAN_INITED();
    598   if (!flags()->replace_str) {
    599     return REAL(strtol)(nptr, endptr, base);
    600   }
    601   char *real_endptr;
    602   long result = REAL(strtol)(nptr, &real_endptr, base);  // NOLINT
    603   if (endptr != 0) {
    604     *endptr = real_endptr;
    605   }
    606   if (IsValidStrtolBase(base)) {
    607     FixRealStrtolEndptr(nptr, &real_endptr);
    608     ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
    609   }
    610   return result;
    611 }
    612 
    613 INTERCEPTOR(int, atoi, const char *nptr) {
    614 #if SANITIZER_MAC
    615   if (UNLIKELY(!asan_inited)) return REAL(atoi)(nptr);
    616 #endif
    617   ENSURE_ASAN_INITED();
    618   if (!flags()->replace_str) {
    619     return REAL(atoi)(nptr);
    620   }
    621   char *real_endptr;
    622   // "man atoi" tells that behavior of atoi(nptr) is the same as
    623   // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
    624   // parsed integer can't be stored in *long* type (even if it's
    625   // different from int). So, we just imitate this behavior.
    626   int result = REAL(strtol)(nptr, &real_endptr, 10);
    627   FixRealStrtolEndptr(nptr, &real_endptr);
    628   ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
    629   return result;
    630 }
    631 
    632 INTERCEPTOR(long, atol, const char *nptr) {  // NOLINT
    633 #if SANITIZER_MAC
    634   if (UNLIKELY(!asan_inited)) return REAL(atol)(nptr);
    635 #endif
    636   ENSURE_ASAN_INITED();
    637   if (!flags()->replace_str) {
    638     return REAL(atol)(nptr);
    639   }
    640   char *real_endptr;
    641   long result = REAL(strtol)(nptr, &real_endptr, 10);  // NOLINT
    642   FixRealStrtolEndptr(nptr, &real_endptr);
    643   ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
    644   return result;
    645 }
    646 
    647 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
    648 INTERCEPTOR(long long, strtoll, const char *nptr,  // NOLINT
    649             char **endptr, int base) {
    650   ENSURE_ASAN_INITED();
    651   if (!flags()->replace_str) {
    652     return REAL(strtoll)(nptr, endptr, base);
    653   }
    654   char *real_endptr;
    655   long long result = REAL(strtoll)(nptr, &real_endptr, base);  // NOLINT
    656   if (endptr != 0) {
    657     *endptr = real_endptr;
    658   }
    659   // If base has unsupported value, strtoll can exit with EINVAL
    660   // without reading any characters. So do additional checks only
    661   // if base is valid.
    662   if (IsValidStrtolBase(base)) {
    663     FixRealStrtolEndptr(nptr, &real_endptr);
    664     ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
    665   }
    666   return result;
    667 }
    668 
    669 INTERCEPTOR(long long, atoll, const char *nptr) {  // NOLINT
    670   ENSURE_ASAN_INITED();
    671   if (!flags()->replace_str) {
    672     return REAL(atoll)(nptr);
    673   }
    674   char *real_endptr;
    675   long long result = REAL(strtoll)(nptr, &real_endptr, 10);  // NOLINT
    676   FixRealStrtolEndptr(nptr, &real_endptr);
    677   ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
    678   return result;
    679 }
    680 #endif  // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
    681 
    682 static void AtCxaAtexit(void *unused) {
    683   (void)unused;
    684   StopInitOrderChecking();
    685 }
    686 
    687 #if ASAN_INTERCEPT___CXA_ATEXIT
    688 INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
    689             void *dso_handle) {
    690 #if SANITIZER_MAC
    691   if (UNLIKELY(!asan_inited)) return REAL(__cxa_atexit)(func, arg, dso_handle);
    692 #endif
    693   ENSURE_ASAN_INITED();
    694   int res = REAL(__cxa_atexit)(func, arg, dso_handle);
    695   REAL(__cxa_atexit)(AtCxaAtexit, 0, 0);
    696   return res;
    697 }
    698 #endif  // ASAN_INTERCEPT___CXA_ATEXIT
    699 
    700 #if ASAN_INTERCEPT_FORK
    701 INTERCEPTOR(int, fork, void) {
    702   ENSURE_ASAN_INITED();
    703   if (common_flags()->coverage) CovBeforeFork();
    704   int pid = REAL(fork)();
    705   if (common_flags()->coverage) CovAfterFork(pid);
    706   return pid;
    707 }
    708 #endif  // ASAN_INTERCEPT_FORK
    709 
    710 #if SANITIZER_WINDOWS
    711 INTERCEPTOR_WINAPI(DWORD, CreateThread,
    712                    void* security, uptr stack_size,
    713                    DWORD (__stdcall *start_routine)(void*), void* arg,
    714                    DWORD thr_flags, void* tid) {
    715   // Strict init-order checking in thread-hostile.
    716   if (flags()->strict_init_order)
    717     StopInitOrderChecking();
    718   GET_STACK_TRACE_THREAD;
    719   u32 current_tid = GetCurrentTidOrInvalid();
    720   AsanThread *t = AsanThread::Create(start_routine, arg);
    721   CreateThreadContextArgs args = { t, &stack };
    722   bool detached = false;  // FIXME: how can we determine it on Windows?
    723   asanThreadRegistry().CreateThread(*(uptr*)t, detached, current_tid, &args);
    724   return REAL(CreateThread)(security, stack_size,
    725                             asan_thread_start, t, thr_flags, tid);
    726 }
    727 
    728 namespace __asan {
    729 void InitializeWindowsInterceptors() {
    730   ASAN_INTERCEPT_FUNC(CreateThread);
    731 }
    732 
    733 }  // namespace __asan
    734 #endif
    735 
    736 // ---------------------- InitializeAsanInterceptors ---------------- {{{1
    737 namespace __asan {
    738 void InitializeAsanInterceptors() {
    739   static bool was_called_once;
    740   CHECK(was_called_once == false);
    741   was_called_once = true;
    742   InitializeCommonInterceptors();
    743 
    744   // Intercept mem* functions.
    745   ASAN_INTERCEPT_FUNC(memcmp);
    746   ASAN_INTERCEPT_FUNC(memmove);
    747   ASAN_INTERCEPT_FUNC(memset);
    748   if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) {
    749     ASAN_INTERCEPT_FUNC(memcpy);
    750   }
    751 
    752   // Intercept str* functions.
    753   ASAN_INTERCEPT_FUNC(strcat);  // NOLINT
    754   ASAN_INTERCEPT_FUNC(strchr);
    755   ASAN_INTERCEPT_FUNC(strcpy);  // NOLINT
    756   ASAN_INTERCEPT_FUNC(strlen);
    757   ASAN_INTERCEPT_FUNC(wcslen);
    758   ASAN_INTERCEPT_FUNC(strncat);
    759   ASAN_INTERCEPT_FUNC(strncpy);
    760 #if ASAN_INTERCEPT_STRDUP
    761   ASAN_INTERCEPT_FUNC(strdup);
    762 #endif
    763 #if ASAN_INTERCEPT_STRNLEN
    764   ASAN_INTERCEPT_FUNC(strnlen);
    765 #endif
    766 #if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
    767   ASAN_INTERCEPT_FUNC(index);
    768 #endif
    769 
    770   ASAN_INTERCEPT_FUNC(atoi);
    771   ASAN_INTERCEPT_FUNC(atol);
    772   ASAN_INTERCEPT_FUNC(strtol);
    773 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
    774   ASAN_INTERCEPT_FUNC(atoll);
    775   ASAN_INTERCEPT_FUNC(strtoll);
    776 #endif
    777 
    778 #if ASAN_INTERCEPT_MLOCKX
    779   // Intercept mlock/munlock.
    780   ASAN_INTERCEPT_FUNC(mlock);
    781   ASAN_INTERCEPT_FUNC(munlock);
    782   ASAN_INTERCEPT_FUNC(mlockall);
    783   ASAN_INTERCEPT_FUNC(munlockall);
    784 #endif
    785 
    786   // Intecept signal- and jump-related functions.
    787   ASAN_INTERCEPT_FUNC(longjmp);
    788 #if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
    789   ASAN_INTERCEPT_FUNC(sigaction);
    790 #if SANITIZER_ANDROID
    791   ASAN_INTERCEPT_FUNC(bsd_signal);
    792 #else
    793   ASAN_INTERCEPT_FUNC(signal);
    794 #endif
    795 #endif
    796 #if ASAN_INTERCEPT_SWAPCONTEXT
    797   ASAN_INTERCEPT_FUNC(swapcontext);
    798 #endif
    799 #if ASAN_INTERCEPT__LONGJMP
    800   ASAN_INTERCEPT_FUNC(_longjmp);
    801 #endif
    802 #if ASAN_INTERCEPT_SIGLONGJMP
    803   ASAN_INTERCEPT_FUNC(siglongjmp);
    804 #endif
    805 
    806   // Intercept exception handling functions.
    807 #if ASAN_INTERCEPT___CXA_THROW
    808   INTERCEPT_FUNCTION(__cxa_throw);
    809 #endif
    810 
    811   // Intercept threading-related functions
    812 #if ASAN_INTERCEPT_PTHREAD_CREATE
    813   ASAN_INTERCEPT_FUNC(pthread_create);
    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_FORK
    822   ASAN_INTERCEPT_FUNC(fork);
    823 #endif
    824 
    825   // Some Windows-specific interceptors.
    826 #if SANITIZER_WINDOWS
    827   InitializeWindowsInterceptors();
    828 #endif
    829 
    830   VReport(1, "AddressSanitizer: libc interceptors initialized\n");
    831 }
    832 
    833 }  // namespace __asan
    834