asan_interceptors.cc revision 8bd5e74fa9d37a182088114918380e255e22e493
1e5f5895bda30f374b0b51412fd4d837fa59aed66Alexey Samsonov//===-- asan_interceptors.cc ----------------------------------------------===//
21e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//
31e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//                     The LLVM Compiler Infrastructure
41e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//
51e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// This file is distributed under the University of Illinois Open Source
61e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// License. See LICENSE.TXT for details.
71e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//
81e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===----------------------------------------------------------------------===//
91e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//
101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// This file is a part of AddressSanitizer, an address sanity checker.
111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//
12d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany// Intercept various libc functions.
131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===----------------------------------------------------------------------===//
141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_interceptors.h"
151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
161e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_allocator.h"
1705bf9a51dfeac0f84f6dbc2dacf987249c0fc612Alexander Potapenko#include "asan_intercepted_functions.h"
181e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_internal.h"
191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_mapping.h"
207e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov#include "asan_report.h"
21487fee7f6f7497906a00d7d2fe2c75e6d5d4feb1Alexey Samsonov#include "asan_stack.h"
221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_stats.h"
231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_thread_registry.h"
245b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov#include "interception/interception.h"
25c0d78c1de1f2607c874020d27b72cf989c5ce092Alexey Samsonov#include "sanitizer_common/sanitizer_libc.h"
26c0d78c1de1f2607c874020d27b72cf989c5ce092Alexey Samsonov
271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan {
281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
29a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany// Return true if we can quickly decide that the region is unpoisoned.
30a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryanystatic inline bool QuickCheckForUnpoisonedRegion(uptr beg, uptr size) {
31a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany  if (size == 0) return true;
32a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany  if (size <= 32)
33a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany    return !AddressIsPoisoned(beg) &&
34a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany           !AddressIsPoisoned(beg + size - 1) &&
35a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany           !AddressIsPoisoned(beg + size / 2);
36a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany  return false;
37a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany}
38a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany
391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE,
401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// and ASAN_WRITE_RANGE as macro instead of function so
411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// that no extra frames are created, and stack trace contains
421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// relevant information only.
43eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany// We check all shadow bytes.
44589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov#define ACCESS_MEMORY_RANGE(offset, size, isWrite) do {                 \
45589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov    uptr __offset = (uptr)(offset);                                     \
46589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov    uptr __size = (uptr)(size);                                         \
471b057b20db71ec6cc2bac460c8b2848f0889d47dKostya Serebryany    uptr __bad = 0;                                                     \
48a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany    if (!QuickCheckForUnpoisonedRegion(__offset, __size) &&             \
491b057b20db71ec6cc2bac460c8b2848f0889d47dKostya Serebryany        (__bad = __asan_region_is_poisoned(__offset, __size))) {        \
50589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov      GET_CURRENT_PC_BP_SP;                                             \
511b057b20db71ec6cc2bac460c8b2848f0889d47dKostya Serebryany      __asan_report_error(pc, bp, sp, __bad, isWrite, __size);          \
52589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov    }                                                                   \
53589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov  } while (0)
541e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
55eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany#define ASAN_READ_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size, false)
56341b9e63f63a8eacf1b699d4c79edee55241ebe6Evgeniy Stepanov#define ASAN_WRITE_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size, true);
571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Behavior of functions like "memcpy" or "strcpy" is undefined
591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// if memory intervals overlap. We report error in this case.
601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Macro is used to avoid creation of new frames.
613f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryanystatic inline bool RangesOverlap(const char *offset1, uptr length1,
623f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany                                 const char *offset2, uptr length2) {
630985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany  return !((offset1 + length1 <= offset2) || (offset2 + length2 <= offset1));
641e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
65c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany#define CHECK_RANGES_OVERLAP(name, _offset1, length1, _offset2, length2) do { \
661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  const char *offset1 = (const char*)_offset1; \
671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  const char *offset2 = (const char*)_offset2; \
680985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany  if (RangesOverlap(offset1, length1, offset2, length2)) { \
69a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany    GET_STACK_TRACE_FATAL_HERE; \
70487fee7f6f7497906a00d7d2fe2c75e6d5d4feb1Alexey Samsonov    ReportStringFunctionMemoryRangesOverlap(name, offset1, length1, \
71487fee7f6f7497906a00d7d2fe2c75e6d5d4feb1Alexey Samsonov                                            offset2, length2, &stack); \
721e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  } \
73e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany} while (0)
741e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
75e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany#define ENSURE_ASAN_INITED() do { \
76e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  CHECK(!asan_init_is_running); \
77e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  if (!asan_inited) { \
78e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany    __asan_init(); \
79e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  } \
80e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany} while (0)
811e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
82c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonovstatic inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) {
8381a7a4ab53c94e76c3b131d6f0ed82894640900bAlexey Samsonov#if ASAN_INTERCEPT_STRNLEN
843f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  if (REAL(strnlen) != 0) {
8509672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(strnlen)(s, maxlen);
861e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
87f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov#endif
88c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov  return internal_strnlen(s, maxlen);
89a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany}
901e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
91c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryanyvoid SetThreadName(const char *name) {
9289c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov  AsanThread *t = asanThreadRegistry().GetCurrent();
93c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany  if (t)
94def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov    t->summary()->set_name(name);
95c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany}
96c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany
978cde99fb9df913aaf7c1715cd134110dd5a15834Dmitry Vyukov}  // namespace __asan
9814dd980b384ad859099b499e12f320c4791fb674Dmitry Vyukov
9914dd980b384ad859099b499e12f320c4791fb674Dmitry Vyukov// ---------------------- Wrappers ---------------- {{{1
10014dd980b384ad859099b499e12f320c4791fb674Dmitry Vyukovusing namespace __asan;  // NOLINT
10114dd980b384ad859099b499e12f320c4791fb674Dmitry Vyukov
1021e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
1031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  ASAN_WRITE_RANGE(ptr, size)
1041e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) ASAN_READ_RANGE(ptr, size)
1051e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
1061e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  do {                                           \
10712eb79dd701d9d40551759330a9257316601373bEvgeniy Stepanov    ctx = 0;                                     \
10812eb79dd701d9d40551759330a9257316601373bEvgeniy Stepanov    (void)ctx;                                   \
10912eb79dd701d9d40551759330a9257316601373bEvgeniy Stepanov    ENSURE_ASAN_INITED();                        \
110a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov  } while (false)
111a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) do { } while (false)
112a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) do { } while (false)
113a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name)
114a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov#include "sanitizer_common/sanitizer_common_interceptors.inc"
115a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov
116a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanovstatic thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
117a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov  AsanThread *t = (AsanThread*)arg;
118a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov  asanThreadRegistry().SetCurrent(t);
119a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov  return t->ThreadStart();
120a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov}
121a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov
122a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov#if ASAN_INTERCEPT_PTHREAD_CREATE
1233fa122e6a8e12db6583793861f6cf776fe1c98a0Evgeniy StepanovINTERCEPTOR(int, pthread_create, void *thread,
1243fa122e6a8e12db6583793861f6cf776fe1c98a0Evgeniy Stepanov    void *attr, void *(*start_routine)(void*), void *arg) {
1253fa122e6a8e12db6583793861f6cf776fe1c98a0Evgeniy Stepanov  GET_STACK_TRACE_THREAD;
12682a9080eaff95d69b270cd863e9df63e3b4e59adEvgeniy Stepanov  u32 current_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
12782a9080eaff95d69b270cd863e9df63e3b4e59adEvgeniy Stepanov  AsanThread *t = AsanThread::Create(current_tid, start_routine, arg, &stack);
128996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  asanThreadRegistry().RegisterThread(t);
129b527f7de80001569542e3f0ef4c7f4b0cb15cb67Alexander Potapenko  return REAL(pthread_create)(thread, attr, asan_thread_start, t);
130b527f7de80001569542e3f0ef4c7f4b0cb15cb67Alexander Potapenko}
131b527f7de80001569542e3f0ef4c7f4b0cb15cb67Alexander Potapenko#endif  // ASAN_INTERCEPT_PTHREAD_CREATE
132b527f7de80001569542e3f0ef4c7f4b0cb15cb67Alexander Potapenko
133b527f7de80001569542e3f0ef4c7f4b0cb15cb67Alexander Potapenko#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
134b527f7de80001569542e3f0ef4c7f4b0cb15cb67Alexander PotapenkoINTERCEPTOR(void*, signal, int signum, void *handler) {
135b527f7de80001569542e3f0ef4c7f4b0cb15cb67Alexander Potapenko  if (!AsanInterceptsSignal(signum)) {
1369d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov    return REAL(signal)(signum, handler);
1379d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov  }
1389d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov  return 0;
1399d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov}
1409d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov
1419d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy StepanovINTERCEPTOR(int, sigaction, int signum, const struct sigaction *act,
1429d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov                            struct sigaction *oldact) {
1439d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov  if (!AsanInterceptsSignal(signum)) {
1449d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov    return REAL(sigaction)(signum, act, oldact);
14582a9080eaff95d69b270cd863e9df63e3b4e59adEvgeniy Stepanov  }
146996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  return 0;
147e767e350b1a6461bc29cfea28af75f908d7da56eDmitry Vyukov}
148e767e350b1a6461bc29cfea28af75f908d7da56eDmitry Vyukov#elif ASAN_POSIX
149e767e350b1a6461bc29cfea28af75f908d7da56eDmitry Vyukov// We need to have defined REAL(sigaction) on posix systems.
150e767e350b1a6461bc29cfea28af75f908d7da56eDmitry VyukovDEFINE_REAL(int, sigaction, int signum, const struct sigaction *act,
1515cf2c460e96e593b1c772f1b02d3a217f4837fdcDmitry Vyukov    struct sigaction *oldact);
152e767e350b1a6461bc29cfea28af75f908d7da56eDmitry Vyukov#endif  // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
153e767e350b1a6461bc29cfea28af75f908d7da56eDmitry Vyukov
154e18e3f07802c420eb4b2da407e148084b75cecc9Evgeniy Stepanov#if ASAN_INTERCEPT_SWAPCONTEXT
15514dd980b384ad859099b499e12f320c4791fb674Dmitry Vyukovstatic void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) {
1564f32c0beaa83ffbb84db23d2e6205bee57c39ce1Evgeniy Stepanov  // Align to page size.
1578530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany  uptr PageSize = GetPageSizeCached();
158881b677c189e65872fd315a75a0e56f077339189Evgeniy Stepanov  uptr bottom = stack & ~(PageSize - 1);
159881b677c189e65872fd315a75a0e56f077339189Evgeniy Stepanov  ssize += stack - bottom;
160ae4e6fd0300b13812a02a779619b1a451478cdd1Evgeniy Stepanov  ssize = RoundUpTo(ssize, PageSize);
161ae4e6fd0300b13812a02a779619b1a451478cdd1Evgeniy Stepanov  static const uptr kMaxSaneContextStackSize = 1 << 22;  // 4 Mb
162dfab31b93e954ee42622a13dd79e9e1092346035Evgeniy Stepanov  if (ssize && ssize <= kMaxSaneContextStackSize) {
163dfab31b93e954ee42622a13dd79e9e1092346035Evgeniy Stepanov    PoisonShadow(bottom, ssize, 0);
164ae4e6fd0300b13812a02a779619b1a451478cdd1Evgeniy Stepanov  }
165ae4e6fd0300b13812a02a779619b1a451478cdd1Evgeniy Stepanov}
166ae4e6fd0300b13812a02a779619b1a451478cdd1Evgeniy Stepanov
167dfab31b93e954ee42622a13dd79e9e1092346035Evgeniy StepanovINTERCEPTOR(int, swapcontext, struct ucontext_t *oucp,
168dfab31b93e954ee42622a13dd79e9e1092346035Evgeniy Stepanov            struct ucontext_t *ucp) {
169ae4e6fd0300b13812a02a779619b1a451478cdd1Evgeniy Stepanov  static bool reported_warning = false;
170881b677c189e65872fd315a75a0e56f077339189Evgeniy Stepanov  if (!reported_warning) {
171881b677c189e65872fd315a75a0e56f077339189Evgeniy Stepanov    Report("WARNING: ASan doesn't fully support makecontext/swapcontext "
172600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov           "functions and may produce false positives in some cases!\n");
1734803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany    reported_warning = true;
17489c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov  }
175def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  // Clear shadow memory for new context (it may share stack
1764803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  // with current context).
1774803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  uptr stack, ssize;
178fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  ReadContextStack(ucp, &stack, &ssize);
179b8ef925563f8dde5be837c4b0569082867c5f14cEvgeniy Stepanov  ClearShadowMemoryForContextStack(stack, ssize);
180b8ef925563f8dde5be837c4b0569082867c5f14cEvgeniy Stepanov  int res = REAL(swapcontext)(oucp, ucp);
181c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev  // swapcontext technically does not return, but program may swap context to
182bdd0966deb04068ea94cf416c7fb46516013bd26Alexey Samsonov  // "oucp" later, that would look as if swapcontext() returned 0.
1839465cbdbe73590746b57916f46ea1aa4bf3dd13dAlexey Samsonov  // We need to clear shadow for ucp once again, as it may be in arbitrary
1849465cbdbe73590746b57916f46ea1aa4bf3dd13dAlexey Samsonov  // state.
185a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  ClearShadowMemoryForContextStack(stack, ssize);
186def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  return res;
187def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov}
188bb6bc9a0ae534ada3c0c2c226462c351c078d761Evgeniy Stepanov#endif  // ASAN_INTERCEPT_SWAPCONTEXT
189def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov
19089c1384464848c1ad041becf8b97936fa10de21bAlexey SamsonovINTERCEPTOR(void, longjmp, void *env, int val) {
191def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  __asan_handle_no_return();
192def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  REAL(longjmp)(env, val);
193def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov}
19409672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov
1954803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany#if ASAN_INTERCEPT__LONGJMP
196fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey SamsonovINTERCEPTOR(void, _longjmp, void *env, int val) {
1974803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  __asan_handle_no_return();
19834a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov  REAL(_longjmp)(env, val);
199f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov}
200332bf3340435a85d39d6abefbf4d6a145e17da1cAlexey Samsonov#endif
201034bda5eab7cda14fac0bed3a39de4a3dbce3cffAlexander Potapenko
2024803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany#if ASAN_INTERCEPT_SIGLONGJMP
2033f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(void, siglongjmp, void *env, int val) {
2044803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  __asan_handle_no_return();
2054803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  REAL(siglongjmp)(env, val);
206da13ba833b046553f50b54538e4828287ddbf5c0Alexey Samsonov}
207da13ba833b046553f50b54538e4828287ddbf5c0Alexey Samsonov#endif
208332bf3340435a85d39d6abefbf4d6a145e17da1cAlexey Samsonov
209034bda5eab7cda14fac0bed3a39de4a3dbce3cffAlexander Potapenko#if ASAN_INTERCEPT___CXA_THROW
2104803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya SerebryanyINTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
211034bda5eab7cda14fac0bed3a39de4a3dbce3cffAlexander Potapenko  CHECK(REAL(__cxa_throw));
2124803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  __asan_handle_no_return();
213e1ba0009d5be18d513ffd29c1b6fccea1a3bffa0Evgeniy Stepanov  REAL(__cxa_throw)(a, b, c);
21434a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov}
21534a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov#endif
216fdde5a97a71b142297d7b2270c2a7f564a37dbaeAlexey Samsonov
21734a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov// intercept mlock and friends.
2184803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany// Since asan maps 16T of RAM, mlock is completely unfriendly to asan.
2190870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov// All functions return 0 (success).
22057db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonovstatic void MlockIsUnsupported() {
22157db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  static bool printed = 0;
22257db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  if (printed) return;
22357db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  printed = true;
22457db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  Printf("INFO: AddressSanitizer ignores mlock/mlockall/munlock/munlockall\n");
22557db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov}
22657db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov
227541cfb10f5daa17e48eb42365a74233cd551c545Kostya Serebryanyextern "C" {
22857db4bae483e7268dd7fc5bc42b0e55564014048Alexey SamsonovINTERCEPTOR(int, mlock, const void *addr, uptr len) {
22957db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  MlockIsUnsupported();
23057db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  return 0;
23157db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov}
2320870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov
2330870028410087e67a0049c76cb7c64f02c260d24Alexey SamsonovINTERCEPTOR(int, munlock, const void *addr, uptr len) {
2340870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  MlockIsUnsupported();
2350870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  return 0;
2360870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov}
2370870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov
2380870028410087e67a0049c76cb7c64f02c260d24Alexey SamsonovINTERCEPTOR(int, mlockall, int flags) {
2390870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  MlockIsUnsupported();
2400870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  return 0;
2410870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov}
24257db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov
24357db4bae483e7268dd7fc5bc42b0e55564014048Alexey SamsonovINTERCEPTOR(int, munlockall, void) {
24457db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  MlockIsUnsupported();
2450870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  return 0;
2460870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov}
2470870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov}  // extern "C"
2480870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov
2490870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonovstatic inline int CharCmp(unsigned char c1, unsigned char c2) {
25057db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
2510870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov}
2520870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov
25357db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonovstatic inline int CharCaseCmp(unsigned char c1, unsigned char c2) {
2540870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  int c1_low = ToLower(c1);
255f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov  int c2_low = ToLower(c2);
256f54b1f9b73a6855d77ee270c282bd61407fa73a0Kostya Serebryany  return c1_low - c2_low;
25709672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov}
2584803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
2594803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya SerebryanyINTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {
260fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  if (!asan_inited) return internal_memcmp(a1, a2, size);
261f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov  ENSURE_ASAN_INITED();
262f54b1f9b73a6855d77ee270c282bd61407fa73a0Kostya Serebryany  if (flags()->replace_intrin) {
26309672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    if (flags()->strict_memcmp) {
2644803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany      // Check the entire regions even if the first bytes of the buffers are
265fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov      // different.
2664803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany      ASAN_READ_RANGE(a1, size);
267fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov      ASAN_READ_RANGE(a2, size);
268f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov      // Fallthrough to REAL(memcmp) below.
269f54b1f9b73a6855d77ee270c282bd61407fa73a0Kostya Serebryany    } else {
27009672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov      unsigned char c1 = 0, c2 = 0;
2714803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany      const unsigned char *s1 = (const unsigned char*)a1;
27207bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov      const unsigned char *s2 = (const unsigned char*)a2;
2734803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany      uptr i;
274fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov      for (i = 0; i < size; i++) {
275f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov        c1 = s1[i];
27609672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov        c2 = s2[i];
277f54b1f9b73a6855d77ee270c282bd61407fa73a0Kostya Serebryany        if (c1 != c2) break;
27809672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov      }
2794803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany      ASAN_READ_RANGE(s1, Min(i + 1, size));
2804803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany      ASAN_READ_RANGE(s2, Min(i + 1, size));
2814803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany      return CharCmp(c1, c2);
2824803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany    }
2834803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  }
2844803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  return REAL(memcmp(a1, a2, size));
2854803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
2868d2438a7ebb01201c652f91d1e8043a1f3d03bffTimur Iskhodzhanov
2874803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya SerebryanyINTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) {
2884803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  if (!asan_inited) return internal_memcpy(to, from, size);
2896866dba92ac842fc513ba339ba849a953ffb7507Dmitry Vyukov  // memcpy is called during __asan_init() from the internals
290eaca82cf249021afa31dbc970278f2f28ea2a1aaTimur Iskhodzhanov  // of printf(...).
291eaca82cf249021afa31dbc970278f2f28ea2a1aaTimur Iskhodzhanov  if (asan_init_is_running) {
292eaca82cf249021afa31dbc970278f2f28ea2a1aaTimur Iskhodzhanov    return REAL(memcpy)(to, from, size);
2934803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  }
2943389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov  ENSURE_ASAN_INITED();
29500f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko  if (flags()->replace_intrin) {
2964803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany    if (to != from) {
2974803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany      // We do not treat memcpy with to==from as a bug.
2984803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany      // See http://llvm.org/bugs/show_bug.cgi?id=11763.
2993389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov      CHECK_RANGES_OVERLAP("memcpy", to, size, from, size);
30000f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko    }
3014803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany    ASAN_READ_RANGE(from, size);
3024803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany    ASAN_WRITE_RANGE(to, size);
3034803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  }
3043389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov  // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8.
30500f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko  // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116.
3064803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  return internal_memcpy(to, from, size);
3074803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
3084803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
3093389b8ea81f51a28365a421b2646d594bac490f5Alexey SamsonovINTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) {
31000f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko  if (!asan_inited) return internal_memmove(to, from, size);
3114803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  if (asan_init_is_running) {
3124803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany    return REAL(memmove)(to, from, size);
3134803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  }
3144803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  ENSURE_ASAN_INITED();
31552fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  if (flags()->replace_intrin) {
31652fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany    ASAN_READ_RANGE(from, size);
31752fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany    ASAN_WRITE_RANGE(to, size);
31852fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  }
3193f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8.
32050f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko  // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116.
32152fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  return internal_memmove(to, from, size);
3221b057b20db71ec6cc2bac460c8b2848f0889d47dKostya Serebryany}
3238bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko
3248bd5e74fa9d37a182088114918380e255e22e493Alexander PotapenkoINTERCEPTOR(void*, memset, void *block, int c, uptr size) {
3258bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko  if (!asan_inited) return internal_memset(block, c, size);
3268bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko  // memset is called inside Printf.
3278bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko  if (asan_init_is_running) {
3288bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko    return REAL(memset)(block, c, size);
3298bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko  }
3308bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko  ENSURE_ASAN_INITED();
3318bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko  if (flags()->replace_intrin) {
3328bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko    ASAN_WRITE_RANGE(block, size);
3338bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko  }
3348bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko  return REAL(memset)(block, c, size);
3358bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko}
3368bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko
3378bd5e74fa9d37a182088114918380e255e22e493Alexander PotapenkoINTERCEPTOR(char*, strchr, const char *str, int c) {
3388bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko  if (!asan_inited) return internal_strchr(str, c);
3398bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko  // strchr is called inside create_purgeable_zone() when MallocGuardEdges=1 is
3408bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko  // used.
3418bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko  if (asan_init_is_running) {
3428bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko    return REAL(strchr)(str, c);
34352fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  }
3441b057b20db71ec6cc2bac460c8b2848f0889d47dKostya Serebryany  ENSURE_ASAN_INITED();
34552fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  char *result = REAL(strchr)(str, c);
34652fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  if (flags()->replace_str) {
347d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko    uptr bytes_read = (result ? result - str : REAL(strlen)(str)) + 1;
348d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko    ASAN_READ_RANGE(str, bytes_read);
349d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko  }
350d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko  return result;
351d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko}
352d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko
353d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko#if ASAN_INTERCEPT_INDEX
354d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko# if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
355d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander PotapenkoINTERCEPTOR(char*, index, const char *string, int c)
356d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko  ALIAS(WRAPPER_NAME(strchr));
357d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko# else
358d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko#  if defined(__APPLE__)
359d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander PotapenkoDECLARE_REAL(char*, index, const char *string, int c)
360d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander PotapenkoOVERRIDE_FUNCTION(index, strchr);
361d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko#  else
3623f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyDEFINE_REAL(char*, index, const char *string, int c);
363d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko#  endif
36450f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko# endif
3651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#endif  // ASAN_INTERCEPT_INDEX
3661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
3671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// For both strcat() and strncat() we need to check the validity of |to|
36809672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov// argument irrespective of the |from| length.
3691e172b4bdec57329bf904f063a29f99cddf2d85fKostya SerebryanyINTERCEPTOR(char*, strcat, char *to, const char *from) {  // NOLINT
370e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
371cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_str) {
372c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany    uptr from_length = REAL(strlen)(from);
373c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany    ASAN_READ_RANGE(from, from_length + 1);
374c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany    uptr to_length = REAL(strlen)(to);
375c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany    ASAN_READ_RANGE(to, to_length);
376c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany    ASAN_WRITE_RANGE(to + to_length, from_length + 1);
377c75d8483e27528349620ccf4e997a72029a7ea17Alexander Potapenko    // If the copying actually happens, the |from| string should not overlap
378c75d8483e27528349620ccf4e997a72029a7ea17Alexander Potapenko    // with the resulting string starting at |to|, which has a length of
3791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    // to_length + from_length + 1.
380d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko    if (from_length > 0) {
381d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko      CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1,
382f1673e61768cb08d488a75584b61bfdf24ffdac1Alexander Potapenko                           from, from_length + 1);
383f1673e61768cb08d488a75584b61bfdf24ffdac1Alexander Potapenko    }
384d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko  }
385d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko  return REAL(strcat)(to, from);  // NOLINT
386d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko}
387d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko
388d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander PotapenkoINTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
389d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko  ENSURE_ASAN_INITED();
390d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko  if (flags()->replace_str) {
391d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko    uptr from_length = MaybeRealStrnlen(from, size);
392d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko    uptr copy_length = Min(size, from_length + 1);
3931e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(from, copy_length);
3941e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    uptr to_length = REAL(strlen)(to);
3953f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany    ASAN_READ_RANGE(to, to_length);
39650f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko    ASAN_WRITE_RANGE(to + to_length, from_length + 1);
397ebb9702cff96192c6a6ea963037929ca7ed60eaeAlexander Potapenko    if (from_length > 0) {
398e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany      CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1,
39909672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov                           from, copy_length);
400e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany    }
401e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  }
402cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  return REAL(strncat)(to, from, size);
4031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
4041e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
40509672caefb5694f1981a1712fdefa44840a95e67Alexey SamsonovINTERCEPTOR(int, strcmp, const char *s1, const char *s2) {
4061e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (!asan_inited) return internal_strcmp(s1, s2);
4071e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (asan_init_is_running) {
408f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov    return REAL(strcmp)(s1, s2);
40950f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko  }
4108d6e3f7d011970e35dadf831964260bcf6a4d8a9Alexander Potapenko  ENSURE_ASAN_INITED();
4118d6e3f7d011970e35dadf831964260bcf6a4d8a9Alexander Potapenko  unsigned char c1, c2;
4128d6e3f7d011970e35dadf831964260bcf6a4d8a9Alexander Potapenko  uptr i;
4138d6e3f7d011970e35dadf831964260bcf6a4d8a9Alexander Potapenko  for (i = 0; ; i++) {
4148d6e3f7d011970e35dadf831964260bcf6a4d8a9Alexander Potapenko    c1 = (unsigned char)s1[i];
415e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany    c2 = (unsigned char)s2[i];
41609672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    if (c1 != c2 || c1 == '\0') break;
417cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  }
4183f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  ASAN_READ_RANGE(s1, i + 1);
4191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  ASAN_READ_RANGE(s2, i + 1);
4201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return CharCmp(c1, c2);
4211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
4221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
4231e172b4bdec57329bf904f063a29f99cddf2d85fKostya SerebryanyINTERCEPTOR(char*, strcpy, char *to, const char *from) {  // NOLINT
424fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if defined(__APPLE__)
425fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  if (!asan_inited) return REAL(strcpy)(to, from);  // NOLINT
4264b0c5f240e71be4f375627e57d0f1b89600918a7Evgeniy Stepanov#endif
42772bbfd4f3a442afde281476bc6bd41b3b2152a4eAlexander Potapenko  // strcpy is called from malloc_default_purgeable_zone()
428fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  // in __asan::ReplaceSystemAlloc() on Mac.
42924e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov  if (asan_init_is_running) {
43050a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko    return REAL(strcpy)(to, from);  // NOLINT
43150a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko  }
43250a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko  ENSURE_ASAN_INITED();
433fdde5a97a71b142297d7b2270c2a7f564a37dbaeAlexey Samsonov  if (flags()->replace_str) {
43450a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko    uptr from_size = REAL(strlen)(from) + 1;
435fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov    CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size);
436fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov    ASAN_READ_RANGE(from, from_size);
437af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany    ASAN_WRITE_RANGE(to, from_size);
43837b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko  }
43937b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko  return REAL(strcpy)(to, from);  // NOLINT
440f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov}
4410985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany
442cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov#if ASAN_INTERCEPT_STRDUP
4433f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(char*, strdup, const char *s) {
4440985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany#if defined(__APPLE__)
44537b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko  // FIXME: because internal_strdup() uses InternalAlloc(), which currently
44637b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko  // just calls malloc() on Mac, we can't use internal_strdup() with the
44737b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko  // dynamic runtime. We can remove the call to REAL(strdup) once InternalAlloc
44837b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko  // starts using mmap() instead.
44937b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko  // See also http://code.google.com/p/address-sanitizer/issues/detail?id=123.
45037b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko  if (!asan_inited) return REAL(strdup)(s);
4510985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany#endif
45237b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko  if (!asan_inited) return internal_strdup(s);
45337b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko  ENSURE_ASAN_INITED();
4540985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany  if (flags()->replace_str) {
4550985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany    uptr length = REAL(strlen)(s);
45609672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    ASAN_READ_RANGE(s, length + 1);
4570985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany  }
4580985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany  return REAL(strdup)(s);
459c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov}
460c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov#endif
46137b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko
462c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey SamsonovINTERCEPTOR(uptr, strlen, const char *s) {
46337b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko  if (!asan_inited) return internal_strlen(s);
46437b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko  // strlen is called from malloc_default_purgeable_zone()
465c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov  // in __asan::ReplaceSystemAlloc() on Mac.
466c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov  if (asan_init_is_running) {
467c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov    return REAL(strlen)(s);
468c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov  }
46937b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko  ENSURE_ASAN_INITED();
47037b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko  uptr length = REAL(strlen)(s);
471c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov  if (flags()->replace_str) {
472c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov    ASAN_READ_RANGE(s, length + 1);
473c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov  }
474c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov  return length;
475c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov}
476f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov
47724e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#if ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP
478beda44f87166f91dbeef3d174d77395653bead4dAlexander PotapenkoINTERCEPTOR(int, strcasecmp, const char *s1, const char *s2) {
4790ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko  ENSURE_ASAN_INITED();
4801e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  unsigned char c1, c2;
4811e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  uptr i;
4821e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  for (i = 0; ; i++) {
48309672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    c1 = (unsigned char)s1[i];
4841e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    c2 = (unsigned char)s2[i];
485e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany    if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
486cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  }
4873f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  ASAN_READ_RANGE(s1, i + 1);
488c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany  ASAN_READ_RANGE(s2, i + 1);
4891e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return CharCaseCmp(c1, c2);
4901e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
4911e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
49209672caefb5694f1981a1712fdefa44840a95e67Alexey SamsonovINTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, uptr n) {
4931e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  ENSURE_ASAN_INITED();
4941e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  unsigned char c1 = 0, c2 = 0;
495fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  uptr i;
496f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov  for (i = 0; i < n; i++) {
49750f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko    c1 = (unsigned char)s1[i];
498e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany    c2 = (unsigned char)s2[i];
499d530d892b4958a9ae54e57472d5d0a0bae1f6ad8Alexey Samsonov    if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
500cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  }
5011e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  ASAN_READ_RANGE(s1, Min(i + 1, n));
5021e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  ASAN_READ_RANGE(s2, Min(i + 1, n));
503d530d892b4958a9ae54e57472d5d0a0bae1f6ad8Alexey Samsonov  return CharCaseCmp(c1, c2);
504d530d892b4958a9ae54e57472d5d0a0bae1f6ad8Alexey Samsonov}
505d530d892b4958a9ae54e57472d5d0a0bae1f6ad8Alexey Samsonov#endif  // ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP
506d530d892b4958a9ae54e57472d5d0a0bae1f6ad8Alexey Samsonov
5071e172b4bdec57329bf904f063a29f99cddf2d85fKostya SerebryanyINTERCEPTOR(int, strncmp, const char *s1, const char *s2, uptr size) {
508fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  if (!asan_inited) return internal_strncmp(s1, s2, size);
5091e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // strncmp is called from malloc_default_purgeable_zone()
5103f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  // in __asan::ReplaceSystemAlloc() on Mac.
51150f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko  if (asan_init_is_running) {
5121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    return REAL(strncmp)(s1, s2, size);
5131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
5141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  ENSURE_ASAN_INITED();
51509672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  unsigned char c1 = 0, c2 = 0;
5161e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  uptr i;
517e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  for (i = 0; i < size; i++) {
5183f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany    c1 = (unsigned char)s1[i];
519cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov    c2 = (unsigned char)s2[i];
5201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    if (c1 != c2 || c1 == '\0') break;
5211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
5221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  ASAN_READ_RANGE(s1, Min(i + 1, size));
5231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  ASAN_READ_RANGE(s2, Min(i + 1, size));
5241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return CharCmp(c1, c2);
525b99228de65b408b0acd9618b92774fb8add7e482Reid Kleckner}
526b99228de65b408b0acd9618b92774fb8add7e482Reid Kleckner
527b99228de65b408b0acd9618b92774fb8add7e482Reid KlecknerINTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) {
528b99228de65b408b0acd9618b92774fb8add7e482Reid Kleckner  ENSURE_ASAN_INITED();
529b99228de65b408b0acd9618b92774fb8add7e482Reid Kleckner  if (flags()->replace_str) {
530b99228de65b408b0acd9618b92774fb8add7e482Reid Kleckner    uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1);
531b99228de65b408b0acd9618b92774fb8add7e482Reid Kleckner    CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size);
532b99228de65b408b0acd9618b92774fb8add7e482Reid Kleckner    ASAN_READ_RANGE(from, from_size);
533b99228de65b408b0acd9618b92774fb8add7e482Reid Kleckner    ASAN_WRITE_RANGE(to, size);
5343f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  }
535e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  return REAL(strncpy)(to, from, size);
536cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov}
537c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov
538c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany#if ASAN_INTERCEPT_STRNLEN
5391e172b4bdec57329bf904f063a29f99cddf2d85fKostya SerebryanyINTERCEPTOR(uptr, strnlen, const char *s, uptr maxlen) {
5401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  ENSURE_ASAN_INITED();
5411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  uptr length = REAL(strnlen)(s, maxlen);
54209672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  if (flags()->replace_str) {
5431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(s, Min(length + 1, maxlen));
5441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
54581a7a4ab53c94e76c3b131d6f0ed82894640900bAlexey Samsonov  return length;
5463f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany}
547e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany#endif  // ASAN_INTERCEPT_STRNLEN
5483f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany
549cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonovstatic inline bool IsValidStrtolBase(int base) {
5502d8b3bdb112ebb8ed3f15ee41d4cebcd683b41b0Kostya Serebryany  return (base == 0) || (2 <= base && base <= 36);
5511e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
5521e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
5531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanystatic inline void FixRealStrtolEndptr(const char *nptr, char **endptr) {
55481a7a4ab53c94e76c3b131d6f0ed82894640900bAlexey Samsonov  CHECK(endptr != 0);
555547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  if (nptr == *endptr) {
5568f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    // No digits were found at strtol call, we need to find out the last
5578f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    // symbol accessed by strtoll on our own.
5588f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    // We get this symbol by skipping leading blanks and optional +/- sign.
5598f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    while (IsSpace(*nptr)) nptr++;
5608f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    if (*nptr == '+' || *nptr == '-') nptr++;
561a27bdf70ca24202dce21cf7c1a387aeaa400d889Kostya Serebryany    *endptr = (char*)nptr;
5628f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  }
5638f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  CHECK(*endptr >= nptr);
5648f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov}
5658f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov
5668f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey SamsonovINTERCEPTOR(long, strtol, const char *nptr,  // NOLINT
5678f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov            char **endptr, int base) {
5688f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  ENSURE_ASAN_INITED();
5698f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  if (!flags()->replace_str) {
5708f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    return REAL(strtol)(nptr, endptr, base);
57184ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov  }
57284ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov  char *real_endptr;
573847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  long result = REAL(strtol)(nptr, &real_endptr, base);  // NOLINT
57484ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov  if (endptr != 0) {
57584ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov    *endptr = real_endptr;
576cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  }
577847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  if (IsValidStrtolBase(base)) {
57884ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov    FixRealStrtolEndptr(nptr, &real_endptr);
57984ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov    ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
580847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  }
5813f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  return result;
58284ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov}
58384ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov
5848f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey SamsonovINTERCEPTOR(int, atoi, const char *nptr) {
5858f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov#if defined(__APPLE__)
58684ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov  if (!asan_inited) return REAL(atoi)(nptr);
58784ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov#endif
58884ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov  ENSURE_ASAN_INITED();
58984ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov  if (!flags()->replace_str) {
59084ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov    return REAL(atoi)(nptr);
591847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  }
59224e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov  char *real_endptr;
5930ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko  // "man atoi" tells that behavior of atoi(nptr) is the same as
5940ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko  // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
595847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  // parsed integer can't be stored in *long* type (even if it's
596cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  // different from int). So, we just imitate this behavior.
597847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  int result = REAL(strtol)(nptr, &real_endptr, 10);
598847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  FixRealStrtolEndptr(nptr, &real_endptr);
599847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
600847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  return result;
6013f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany}
602847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov
603847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR(long, atol, const char *nptr) {  // NOLINT
604847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov#if defined(__APPLE__)
605847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  if (!asan_inited) return REAL(atol)(nptr);
606847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov#endif
607847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  ENSURE_ASAN_INITED();
608847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  if (!flags()->replace_str) {
609847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov    return REAL(atol)(nptr);
610847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  }
61124e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov  char *real_endptr;
6120ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko  long result = REAL(strtol)(nptr, &real_endptr, 10);  // NOLINT
6130ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko  FixRealStrtolEndptr(nptr, &real_endptr);
614847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
615cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  return result;
616847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov}
617847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov
618847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
619847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR(long long, strtoll, const char *nptr,  // NOLINT
620847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov            char **endptr, int base) {
621847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  ENSURE_ASAN_INITED();
622847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  if (!flags()->replace_str) {
623847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov    return REAL(strtoll)(nptr, endptr, base);
624847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  }
625847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  char *real_endptr;
626847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  long long result = REAL(strtoll)(nptr, &real_endptr, base);  // NOLINT
6278f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  if (endptr != 0) {
6288f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    *endptr = real_endptr;
629cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  }
630847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  // If base has unsupported value, strtoll can exit with EINVAL
6318f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  // without reading any characters. So do additional checks only
6328f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  // if base is valid.
633847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  if (IsValidStrtolBase(base)) {
6343f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany    FixRealStrtolEndptr(nptr, &real_endptr);
6358f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
6368f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  }
637847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  return result;
638847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov}
639847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov
6408f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey SamsonovINTERCEPTOR(long long, atoll, const char *nptr) {  // NOLINT
6418f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  ENSURE_ASAN_INITED();
6428f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  if (!flags()->replace_str) {
6438f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    return REAL(atoll)(nptr);
6448f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  }
6458f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  char *real_endptr;
6468f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  long long result = REAL(strtoll)(nptr, &real_endptr, 10);  // NOLINT
647847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  FixRealStrtolEndptr(nptr, &real_endptr);
648847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
649cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  return result;
650847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov}
651847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov#endif  // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
652847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov
653847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov#define ASAN_INTERCEPT_FUNC(name) do { \
654847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov      if (!INTERCEPT_FUNCTION(name) && flags()->verbosity > 0) \
655847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov        Report("AddressSanitizer: failed to intercept '" #name "'\n"); \
656847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov    } while (0)
657847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov
658847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov#if defined(_WIN32)
659847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR_WINAPI(DWORD, CreateThread,
66046efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov                   void* security, uptr stack_size,
66146efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov                   DWORD (__stdcall *start_routine)(void*), void* arg,
66246efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov                   DWORD flags, void* tid) {
66346efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov  GET_STACK_TRACE_THREAD;
66446efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov  u32 current_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
66546efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov  AsanThread *t = AsanThread::Create(current_tid, start_routine, arg, &stack);
66646efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov  asanThreadRegistry().RegisterThread(t);
66746efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov  return REAL(CreateThread)(security, stack_size,
668b527f7de80001569542e3f0ef4c7f4b0cb15cb67Alexander Potapenko                            asan_thread_start, t, flags, tid);
669b527f7de80001569542e3f0ef4c7f4b0cb15cb67Alexander Potapenko}
670b527f7de80001569542e3f0ef4c7f4b0cb15cb67Alexander Potapenko
67146efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonovnamespace __asan {
67246efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonovvoid InitializeWindowsInterceptors() {
67346efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov  ASAN_INTERCEPT_FUNC(CreateThread);
67446efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov}
67546efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov
67646efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov}  // namespace __asan
67746efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov#endif
67824e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov
679600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov// ---------------------- InitializeAsanInterceptors ---------------- {{{1
6803f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryanynamespace __asan {
681600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanovvoid InitializeAsanInterceptors() {
682b9a928497168e177791f10f5042ff6f5e4e8a881Alexey Samsonov  static bool was_called_once;
683bdd0966deb04068ea94cf416c7fb46516013bd26Alexey Samsonov  CHECK(was_called_once == false);
6849465cbdbe73590746b57916f46ea1aa4bf3dd13dAlexey Samsonov  was_called_once = true;
6859465cbdbe73590746b57916f46ea1aa4bf3dd13dAlexey Samsonov#if defined(__APPLE__)
686a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  return;
68789c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov#else
688dfe3f9691d4700981566a4b57e1e482f72783950Alexey Samsonov  SANITIZER_COMMON_INTERCEPTORS_INIT;
689dfe3f9691d4700981566a4b57e1e482f72783950Alexey Samsonov
6908d2438a7ebb01201c652f91d1e8043a1f3d03bffTimur Iskhodzhanov  // Intercept mem* functions.
691dfe3f9691d4700981566a4b57e1e482f72783950Alexey Samsonov  ASAN_INTERCEPT_FUNC(memcmp);
692600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  ASAN_INTERCEPT_FUNC(memmove);
693b9a928497168e177791f10f5042ff6f5e4e8a881Alexey Samsonov  ASAN_INTERCEPT_FUNC(memset);
694600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) {
695600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov    ASAN_INTERCEPT_FUNC(memcpy);
696600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  }
697600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov
698580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  // Intercept str* functions.
699600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  ASAN_INTERCEPT_FUNC(strcat);  // NOLINT
700600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  ASAN_INTERCEPT_FUNC(strchr);
701600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  ASAN_INTERCEPT_FUNC(strcmp);
702600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  ASAN_INTERCEPT_FUNC(strcpy);  // NOLINT
703600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  ASAN_INTERCEPT_FUNC(strlen);
704547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  ASAN_INTERCEPT_FUNC(strncat);
705547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  ASAN_INTERCEPT_FUNC(strncmp);
706547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  ASAN_INTERCEPT_FUNC(strncpy);
707fdbdab5ff8de4c23b58bb411ea2358a78e2d9b2fKostya Serebryany#if ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP
708fdbdab5ff8de4c23b58bb411ea2358a78e2d9b2fKostya Serebryany  ASAN_INTERCEPT_FUNC(strcasecmp);
709fdbdab5ff8de4c23b58bb411ea2358a78e2d9b2fKostya Serebryany  ASAN_INTERCEPT_FUNC(strncasecmp);
7108530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany#endif
7118530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany#if ASAN_INTERCEPT_STRDUP
71207bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  ASAN_INTERCEPT_FUNC(strdup);
713580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov#endif
714580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov#if ASAN_INTERCEPT_STRNLEN
715580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strnlen);
71638dd4ed885e714c376466f6fe0d69f5f22d37014Alexey Samsonov#endif
717580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov#if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
718573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko  ASAN_INTERCEPT_FUNC(index);
71907bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov#endif
72007bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov
721580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(atoi);
722580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(atol);
723580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strtol);
724580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
725b99228de65b408b0acd9618b92774fb8add7e482Reid Kleckner  ASAN_INTERCEPT_FUNC(atoll);
726c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov  ASAN_INTERCEPT_FUNC(strtoll);
727580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov#endif
728fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov
729fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_MLOCKX
730fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  // Intercept mlock/munlock.
731fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  ASAN_INTERCEPT_FUNC(mlock);
732fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  ASAN_INTERCEPT_FUNC(munlock);
733fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  ASAN_INTERCEPT_FUNC(mlockall);
73469563986ca570ce750111a82264d51ddbf4107baAlexander Potapenko  ASAN_INTERCEPT_FUNC(munlockall);
735580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov#endif
73607bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov
7375b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  // Intecept signal- and jump-related functions.
738580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(longjmp);
739580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
740580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(sigaction);
741847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  ASAN_INTERCEPT_FUNC(signal);
742580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov#endif
743580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov#if ASAN_INTERCEPT_SWAPCONTEXT
74484ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov  ASAN_INTERCEPT_FUNC(swapcontext);
74584ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov#endif
746f0c6de3d91ba5cdfbb17a630e823523c7d433160Alexander Potapenko#if ASAN_INTERCEPT__LONGJMP
74700f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko  ASAN_INTERCEPT_FUNC(_longjmp);
74800f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko#endif
74900f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko#if ASAN_INTERCEPT_SIGLONGJMP
75000f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko  ASAN_INTERCEPT_FUNC(siglongjmp);
75100f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko#endif
752f0c6de3d91ba5cdfbb17a630e823523c7d433160Alexander Potapenko
75300f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko  // Intercept exception handling functions.
75407bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov#if ASAN_INTERCEPT___CXA_THROW
755580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  INTERCEPT_FUNCTION(__cxa_throw);
75634a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov#endif
757580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov
758580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  // Intercept threading-related functions
759919c24787a655597bdcf367e26c9dd1504e9f463Evgeniy Stepanov#if ASAN_INTERCEPT_PTHREAD_CREATE
7600870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  ASAN_INTERCEPT_FUNC(pthread_create);
7610870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov#endif
7620870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov
763fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  // Some Windows-specific interceptors.
764580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov#if defined(_WIN32)
765fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  InitializeWindowsInterceptors();
766fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif
767580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov
768fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  if (flags()->verbosity > 0) {
769fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov    Report("AddressSanitizer: libc interceptors initialized\n");
770fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  }
771fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif  // __APPLE__
772fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov}
7733e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov
7743e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov}  // namespace __asan
77507bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov