asan_interceptors.cc revision eaca82cf249021afa31dbc970278f2f28ea2a1aa
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_poisoning.h"
21487fee7f6f7497906a00d7d2fe2c75e6d5d4feb1Alexey Samsonov#include "asan_report.h"
221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_stack.h"
231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_stats.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 = GetCurrentThread();
93c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany  if (t)
94def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov    asanThreadRegistry().SetThreadName(t->tid(), name);
95c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany}
96c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany
971e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}  // namespace __asan
981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
991e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// ---------------------- Wrappers ---------------- {{{1
1001e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyusing namespace __asan;  // NOLINT
1011e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
10212eb79dd701d9d40551759330a9257316601373bEvgeniy StepanovDECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr)
10312eb79dd701d9d40551759330a9257316601373bEvgeniy StepanovDECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
10412eb79dd701d9d40551759330a9257316601373bEvgeniy Stepanov
1053fa122e6a8e12db6583793861f6cf776fe1c98a0Evgeniy Stepanov#define COMMON_INTERCEPTOR_UNPOISON_PARAM(ctx, count) \
1063fa122e6a8e12db6583793861f6cf776fe1c98a0Evgeniy Stepanov  do {                                                \
1073fa122e6a8e12db6583793861f6cf776fe1c98a0Evgeniy Stepanov  } while (false)
10882a9080eaff95d69b270cd863e9df63e3b4e59adEvgeniy Stepanov#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
10982a9080eaff95d69b270cd863e9df63e3b4e59adEvgeniy Stepanov  ASAN_WRITE_RANGE(ptr, size)
110996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) ASAN_READ_RANGE(ptr, size)
1119d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...)              \
1129d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov  do {                                                        \
1139d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov    if (asan_init_is_running) return REAL(func)(__VA_ARGS__); \
1149d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov    ctx = 0;                                                  \
1159d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov    (void) ctx;                                               \
1169d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov    ENSURE_ASAN_INITED();                                     \
1179d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov  } while (false)
1189d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
1199d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov  do {                                         \
1209d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov  } while (false)
1219d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
1229d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov  do {                                         \
1239d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov  } while (false)
1249d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov#define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
1259d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov  do {                                                      \
12682a9080eaff95d69b270cd863e9df63e3b4e59adEvgeniy Stepanov  } while (false)
127996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name)
1284f32c0beaa83ffbb84db23d2e6205bee57c39ce1Evgeniy Stepanov#include "sanitizer_common/sanitizer_common_interceptors.inc"
1298530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany
130881b677c189e65872fd315a75a0e56f077339189Evgeniy Stepanov#define COMMON_SYSCALL_PRE_READ_RANGE(p, s) ASAN_READ_RANGE(p, s)
131881b677c189e65872fd315a75a0e56f077339189Evgeniy Stepanov#define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) ASAN_WRITE_RANGE(p, s)
132ae4e6fd0300b13812a02a779619b1a451478cdd1Evgeniy Stepanov#define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
133ae4e6fd0300b13812a02a779619b1a451478cdd1Evgeniy Stepanov  do {                                       \
134ae4e6fd0300b13812a02a779619b1a451478cdd1Evgeniy Stepanov  } while (false)
135ae4e6fd0300b13812a02a779619b1a451478cdd1Evgeniy Stepanov#define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \
136ae4e6fd0300b13812a02a779619b1a451478cdd1Evgeniy Stepanov  do {                                        \
137ae4e6fd0300b13812a02a779619b1a451478cdd1Evgeniy Stepanov  } while (false)
138881b677c189e65872fd315a75a0e56f077339189Evgeniy Stepanov#include "sanitizer_common/sanitizer_common_syscalls.inc"
139881b677c189e65872fd315a75a0e56f077339189Evgeniy Stepanov
140600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanovstatic thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
1414803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  AsanThread *t = (AsanThread*)arg;
14289c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov  SetCurrentThread(t);
143def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  return t->ThreadStart(GetTid());
1444803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
1454803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
146fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_PTHREAD_CREATE
147def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonovextern "C" int pthread_attr_getdetachstate(void *attr, int *v);
148def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov
149b8ef925563f8dde5be837c4b0569082867c5f14cEvgeniy StepanovINTERCEPTOR(int, pthread_create, void *thread,
150b8ef925563f8dde5be837c4b0569082867c5f14cEvgeniy Stepanov    void *attr, void *(*start_routine)(void*), void *arg) {
151c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev  EnsureMainThreadIDIsCorrect();
152bdd0966deb04068ea94cf416c7fb46516013bd26Alexey Samsonov  // Strict init-order checking in thread-hostile.
1539465cbdbe73590746b57916f46ea1aa4bf3dd13dAlexey Samsonov  if (flags()->strict_init_order)
1549465cbdbe73590746b57916f46ea1aa4bf3dd13dAlexey Samsonov    StopInitOrderChecking();
155a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  GET_STACK_TRACE_THREAD;
156def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  int detached = 0;
157def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  if (attr != 0)
158def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov    pthread_attr_getdetachstate(attr, &detached);
159def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov
16089c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov  u32 current_tid = GetCurrentTidOrInvalid();
161def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  AsanThread *t = AsanThread::Create(start_routine, arg);
162def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  CreateThreadContextArgs args = { t, &stack };
163def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  asanThreadRegistry().CreateThread(*(uptr*)t, detached, current_tid, &args);
16409672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(pthread_create)(thread, attr, asan_thread_start, t);
1654803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
166fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif  // ASAN_INTERCEPT_PTHREAD_CREATE
1674803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
16834a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
169f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void*, signal, int signum, void *handler) {
170332bf3340435a85d39d6abefbf4d6a145e17da1cAlexey Samsonov  if (!AsanInterceptsSignal(signum) || flags()->allow_user_segv_handler) {
171034bda5eab7cda14fac0bed3a39de4a3dbce3cffAlexander Potapenko    return REAL(signal)(signum, handler);
1724803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  }
1733f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  return 0;
1744803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
1754803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
176da13ba833b046553f50b54538e4828287ddbf5c0Alexey SamsonovINTERCEPTOR(int, sigaction, int signum, const struct sigaction *act,
177da13ba833b046553f50b54538e4828287ddbf5c0Alexey Samsonov                            struct sigaction *oldact) {
178332bf3340435a85d39d6abefbf4d6a145e17da1cAlexey Samsonov  if (!AsanInterceptsSignal(signum) || flags()->allow_user_segv_handler) {
179034bda5eab7cda14fac0bed3a39de4a3dbce3cffAlexander Potapenko    return REAL(sigaction)(signum, act, oldact);
1804803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  }
181034bda5eab7cda14fac0bed3a39de4a3dbce3cffAlexander Potapenko  return 0;
1824803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
183e1ba0009d5be18d513ffd29c1b6fccea1a3bffa0Evgeniy Stepanov#elif SANITIZER_POSIX
18434a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov// We need to have defined REAL(sigaction) on posix systems.
18534a3202a2c22816a6da66959e266a2d078ded37bAlexey SamsonovDEFINE_REAL(int, sigaction, int signum, const struct sigaction *act,
186fdde5a97a71b142297d7b2270c2a7f564a37dbaeAlexey Samsonov    struct sigaction *oldact)
18734a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov#endif  // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
1884803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
1890870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov#if ASAN_INTERCEPT_SWAPCONTEXT
19057db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonovstatic void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) {
19157db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  // Align to page size.
19257db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  uptr PageSize = GetPageSizeCached();
19357db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  uptr bottom = stack & ~(PageSize - 1);
19457db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  ssize += stack - bottom;
19557db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  ssize = RoundUpTo(ssize, PageSize);
19657db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  static const uptr kMaxSaneContextStackSize = 1 << 22;  // 4 Mb
197541cfb10f5daa17e48eb42365a74233cd551c545Kostya Serebryany  if (ssize && ssize <= kMaxSaneContextStackSize) {
19857db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov    PoisonShadow(bottom, ssize, 0);
19957db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  }
20057db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov}
20157db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov
2020870028410087e67a0049c76cb7c64f02c260d24Alexey SamsonovINTERCEPTOR(int, swapcontext, struct ucontext_t *oucp,
2030870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov            struct ucontext_t *ucp) {
2040870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  static bool reported_warning = false;
2050870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  if (!reported_warning) {
2060870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov    Report("WARNING: ASan doesn't fully support makecontext/swapcontext "
2070870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov           "functions and may produce false positives in some cases!\n");
2080870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov    reported_warning = true;
2090870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  }
2100870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  // Clear shadow memory for new context (it may share stack
2110870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  // with current context).
21257db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  uptr stack, ssize;
21357db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  ReadContextStack(ucp, &stack, &ssize);
21457db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  ClearShadowMemoryForContextStack(stack, ssize);
2150870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  int res = REAL(swapcontext)(oucp, ucp);
2160870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  // swapcontext technically does not return, but program may swap context to
2170870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  // "oucp" later, that would look as if swapcontext() returned 0.
2180870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  // We need to clear shadow for ucp once again, as it may be in arbitrary
2190870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  // state.
22057db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  ClearShadowMemoryForContextStack(stack, ssize);
2210870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  return res;
2220870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov}
22357db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov#endif  // ASAN_INTERCEPT_SWAPCONTEXT
2240870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov
225f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, longjmp, void *env, int val) {
226f54b1f9b73a6855d77ee270c282bd61407fa73a0Kostya Serebryany  __asan_handle_no_return();
22709672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  REAL(longjmp)(env, val);
2284803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
2294803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
230fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT__LONGJMP
231f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, _longjmp, void *env, int val) {
232f54b1f9b73a6855d77ee270c282bd61407fa73a0Kostya Serebryany  __asan_handle_no_return();
23309672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  REAL(_longjmp)(env, val);
2344803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
235fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif
2364803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
237fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_SIGLONGJMP
238f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, siglongjmp, void *env, int val) {
239f54b1f9b73a6855d77ee270c282bd61407fa73a0Kostya Serebryany  __asan_handle_no_return();
24009672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  REAL(siglongjmp)(env, val);
2414803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
24207bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov#endif
2434803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
244fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT___CXA_THROW
245f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
24609672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  CHECK(REAL(__cxa_throw));
247f54b1f9b73a6855d77ee270c282bd61407fa73a0Kostya Serebryany  __asan_handle_no_return();
24809672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  REAL(__cxa_throw)(a, b, c);
2494803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
2504803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany#endif
2514803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
2524803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany// intercept mlock and friends.
2534803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany// Since asan maps 16T of RAM, mlock is completely unfriendly to asan.
2544803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany// All functions return 0 (success).
2554803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanystatic void MlockIsUnsupported() {
2568d2438a7ebb01201c652f91d1e8043a1f3d03bffTimur Iskhodzhanov  static bool printed = false;
2574803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  if (printed) return;
2584803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  printed = true;
259eaca82cf249021afa31dbc970278f2f28ea2a1aaTimur Iskhodzhanov  if (flags()->verbosity > 0) {
260eaca82cf249021afa31dbc970278f2f28ea2a1aaTimur Iskhodzhanov    Printf("INFO: AddressSanitizer ignores "
261eaca82cf249021afa31dbc970278f2f28ea2a1aaTimur Iskhodzhanov           "mlock/mlockall/munlock/munlockall\n");
262eaca82cf249021afa31dbc970278f2f28ea2a1aaTimur Iskhodzhanov  }
2634803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
2643389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov
26500f1c091441be5c2cacb99e21bd1965a5e418242Alexander PotapenkoINTERCEPTOR(int, mlock, const void *addr, uptr len) {
2664803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  MlockIsUnsupported();
2674803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  return 0;
2684803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
2693389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov
27000f1c091441be5c2cacb99e21bd1965a5e418242Alexander PotapenkoINTERCEPTOR(int, munlock, const void *addr, uptr len) {
2714803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  MlockIsUnsupported();
2724803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  return 0;
2734803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
2743389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov
27500f1c091441be5c2cacb99e21bd1965a5e418242Alexander PotapenkoINTERCEPTOR(int, mlockall, int flags) {
2764803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  MlockIsUnsupported();
2774803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  return 0;
2784803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
2793389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov
28000f1c091441be5c2cacb99e21bd1965a5e418242Alexander PotapenkoINTERCEPTOR(int, munlockall, void) {
2814803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  MlockIsUnsupported();
2824803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  return 0;
2834803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
2844803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
28552fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryanystatic inline int CharCmp(unsigned char c1, unsigned char c2) {
28652fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
28752fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany}
28852fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany
2893f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {
29050f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko  if (!asan_inited) return internal_memcmp(a1, a2, size);
29152fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  ENSURE_ASAN_INITED();
2921b057b20db71ec6cc2bac460c8b2848f0889d47dKostya Serebryany  if (flags()->replace_intrin) {
2938bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko    if (flags()->strict_memcmp) {
2948bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko      // Check the entire regions even if the first bytes of the buffers are
2958bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko      // different.
2968bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko      ASAN_READ_RANGE(a1, size);
2978bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko      ASAN_READ_RANGE(a2, size);
2988bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko      // Fallthrough to REAL(memcmp) below.
2998bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko    } else {
3008bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko      unsigned char c1 = 0, c2 = 0;
3018bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko      const unsigned char *s1 = (const unsigned char*)a1;
3028bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko      const unsigned char *s2 = (const unsigned char*)a2;
3038bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko      uptr i;
3048bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko      for (i = 0; i < size; i++) {
3058bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko        c1 = s1[i];
3068bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko        c2 = s2[i];
3078bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko        if (c1 != c2) break;
3088bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko      }
3098bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko      ASAN_READ_RANGE(s1, Min(i + 1, size));
3108bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko      ASAN_READ_RANGE(s2, Min(i + 1, size));
3118bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko      return CharCmp(c1, c2);
3128bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko    }
31352fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  }
3141b057b20db71ec6cc2bac460c8b2848f0889d47dKostya Serebryany  return REAL(memcmp(a1, a2, size));
31552fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany}
31652fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany
3173f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) {
31850f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko  if (!asan_inited) return internal_memcpy(to, from, size);
3191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // memcpy is called during __asan_init() from the internals
3201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // of printf(...).
3211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (asan_init_is_running) {
32209672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(memcpy)(to, from, size);
3231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
324e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
325cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_intrin) {
326c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany    if (to != from) {
327c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany      // We do not treat memcpy with to==from as a bug.
328c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany      // See http://llvm.org/bugs/show_bug.cgi?id=11763.
329c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany      CHECK_RANGES_OVERLAP("memcpy", to, size, from, size);
330c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany    }
331c75d8483e27528349620ccf4e997a72029a7ea17Alexander Potapenko    ASAN_READ_RANGE(from, size);
332c75d8483e27528349620ccf4e997a72029a7ea17Alexander Potapenko    ASAN_WRITE_RANGE(to, size);
3331e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
334f1673e61768cb08d488a75584b61bfdf24ffdac1Alexander Potapenko  // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8.
335f1673e61768cb08d488a75584b61bfdf24ffdac1Alexander Potapenko  // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116.
336f1673e61768cb08d488a75584b61bfdf24ffdac1Alexander Potapenko  return internal_memcpy(to, from, size);
3371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
3381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
3393f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) {
3403e8458ab54c7cbaec45e367b2da909c6f94b291cAlexander Potapenko  if (!asan_inited) return internal_memmove(to, from, size);
341a1a25c1afe38e59ffb342c24bb5bb10d05679df7Alexey Samsonov  if (asan_init_is_running) {
342a1a25c1afe38e59ffb342c24bb5bb10d05679df7Alexey Samsonov    return REAL(memmove)(to, from, size);
343a1a25c1afe38e59ffb342c24bb5bb10d05679df7Alexey Samsonov  }
344e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
345cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_intrin) {
346c75d8483e27528349620ccf4e997a72029a7ea17Alexander Potapenko    ASAN_READ_RANGE(from, size);
347c75d8483e27528349620ccf4e997a72029a7ea17Alexander Potapenko    ASAN_WRITE_RANGE(to, size);
3481e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
349f1673e61768cb08d488a75584b61bfdf24ffdac1Alexander Potapenko  // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8.
350f1673e61768cb08d488a75584b61bfdf24ffdac1Alexander Potapenko  // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116.
351f1673e61768cb08d488a75584b61bfdf24ffdac1Alexander Potapenko  return internal_memmove(to, from, size);
3521e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
3531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
3543f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(void*, memset, void *block, int c, uptr size) {
35550f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko  if (!asan_inited) return internal_memset(block, c, size);
356ebb9702cff96192c6a6ea963037929ca7ed60eaeAlexander Potapenko  // memset is called inside Printf.
357e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  if (asan_init_is_running) {
35809672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(memset)(block, c, size);
359e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  }
360e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
361cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_intrin) {
3621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_WRITE_RANGE(block, size);
3631e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
36409672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(memset)(block, c, size);
3651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
3661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
367f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strchr, const char *str, int c) {
36850f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko  if (!asan_inited) return internal_strchr(str, c);
3698d6e3f7d011970e35dadf831964260bcf6a4d8a9Alexander Potapenko  // strchr is called inside create_purgeable_zone() when MallocGuardEdges=1 is
3708d6e3f7d011970e35dadf831964260bcf6a4d8a9Alexander Potapenko  // used.
3718d6e3f7d011970e35dadf831964260bcf6a4d8a9Alexander Potapenko  if (asan_init_is_running) {
3728d6e3f7d011970e35dadf831964260bcf6a4d8a9Alexander Potapenko    return REAL(strchr)(str, c);
3738d6e3f7d011970e35dadf831964260bcf6a4d8a9Alexander Potapenko  }
374e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
37509672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  char *result = REAL(strchr)(str, c);
376cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_str) {
3773f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany    uptr bytes_read = (result ? result - str : REAL(strlen)(str)) + 1;
3781e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(str, bytes_read);
3791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
3801e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return result;
3811e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
3821e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
383fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_INDEX
384fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov# if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
3854b0c5f240e71be4f375627e57d0f1b89600918a7Evgeniy StepanovINTERCEPTOR(char*, index, const char *string, int c)
38672bbfd4f3a442afde281476bc6bd41b3b2152a4eAlexander Potapenko  ALIAS(WRAPPER_NAME(strchr));
387fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov# else
38824e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#  if SANITIZER_MAC
38950a002ecad3f0a10c136496e5b6289bd3c71590eAlexander PotapenkoDECLARE_REAL(char*, index, const char *string, int c)
39050a002ecad3f0a10c136496e5b6289bd3c71590eAlexander PotapenkoOVERRIDE_FUNCTION(index, strchr);
39150a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko#  else
392fdde5a97a71b142297d7b2270c2a7f564a37dbaeAlexey SamsonovDEFINE_REAL(char*, index, const char *string, int c)
39350a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko#  endif
394fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov# endif
395fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif  // ASAN_INTERCEPT_INDEX
396af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany
39737b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko// For both strcat() and strncat() we need to check the validity of |to|
39837b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko// argument irrespective of the |from| length.
399f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strcat, char *to, const char *from) {  // NOLINT
4000985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany  ENSURE_ASAN_INITED();
401cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_str) {
4023f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany    uptr from_length = REAL(strlen)(from);
4030985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany    ASAN_READ_RANGE(from, from_length + 1);
40437b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko    uptr to_length = REAL(strlen)(to);
40537b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko    ASAN_READ_RANGE(to, to_length);
40637b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko    ASAN_WRITE_RANGE(to + to_length, from_length + 1);
40737b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko    // If the copying actually happens, the |from| string should not overlap
40837b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko    // with the resulting string starting at |to|, which has a length of
40937b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko    // to_length + from_length + 1.
4100985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany    if (from_length > 0) {
41137b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko      CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1,
41237b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko                           from, from_length + 1);
4130985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany    }
4140985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany  }
41509672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(strcat)(to, from);  // NOLINT
4160985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany}
4170985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany
418c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey SamsonovINTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
419c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov  ENSURE_ASAN_INITED();
42037b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko  if (flags()->replace_str) {
421c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov    uptr from_length = MaybeRealStrnlen(from, size);
42237b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko    uptr copy_length = Min(size, from_length + 1);
42337b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko    ASAN_READ_RANGE(from, copy_length);
424c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov    uptr to_length = REAL(strlen)(to);
425c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov    ASAN_READ_RANGE(to, to_length);
426c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov    ASAN_WRITE_RANGE(to + to_length, from_length + 1);
427c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov    if (from_length > 0) {
42837b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko      CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1,
42937b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko                           from, copy_length);
430c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov    }
431c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov  }
432c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov  return REAL(strncat)(to, from, size);
433c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov}
434c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov
435f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(int, strcmp, const char *s1, const char *s2) {
43650f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko  if (!asan_inited) return internal_strcmp(s1, s2);
437fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  if (asan_init_is_running) {
438fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov    return REAL(strcmp)(s1, s2);
4391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
4408648e7734ff02a25706464e9e294bd217622bcaeKostya Serebryany  ENSURE_ASAN_INITED();
4411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  unsigned char c1, c2;
4423f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  uptr i;
4431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  for (i = 0; ; i++) {
4441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    c1 = (unsigned char)s1[i];
4451e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    c2 = (unsigned char)s2[i];
4461e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    if (c1 != c2 || c1 == '\0') break;
4471e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
4481e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  ASAN_READ_RANGE(s1, i + 1);
4491e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  ASAN_READ_RANGE(s2, i + 1);
4501e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return CharCmp(c1, c2);
4511e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
4521e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
453f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strcpy, char *to, const char *from) {  // NOLINT
45424e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#if SANITIZER_MAC
455beda44f87166f91dbeef3d174d77395653bead4dAlexander Potapenko  if (!asan_inited) return REAL(strcpy)(to, from);  // NOLINT
4560ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko#endif
4571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // strcpy is called from malloc_default_purgeable_zone()
4581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // in __asan::ReplaceSystemAlloc() on Mac.
4591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (asan_init_is_running) {
46009672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(strcpy)(to, from);  // NOLINT
4611e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
462e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
463cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_str) {
4643f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany    uptr from_size = REAL(strlen)(from) + 1;
465c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany    CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size);
4661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(from, from_size);
4671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_WRITE_RANGE(to, from_size);
4681e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
46909672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(strcpy)(to, from);  // NOLINT
4701e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
4711e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
472fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_STRDUP
473f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strdup, const char *s) {
47450f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko  if (!asan_inited) return internal_strdup(s);
475e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
476d530d892b4958a9ae54e57472d5d0a0bae1f6ad8Alexey Samsonov  uptr length = REAL(strlen)(s);
477cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_str) {
4781e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(s, length + 1);
4791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
480d530d892b4958a9ae54e57472d5d0a0bae1f6ad8Alexey Samsonov  GET_STACK_TRACE_MALLOC;
481d530d892b4958a9ae54e57472d5d0a0bae1f6ad8Alexey Samsonov  void *new_mem = asan_malloc(length + 1, &stack);
482d530d892b4958a9ae54e57472d5d0a0bae1f6ad8Alexey Samsonov  REAL(memcpy)(new_mem, s, length + 1);
483d530d892b4958a9ae54e57472d5d0a0bae1f6ad8Alexey Samsonov  return reinterpret_cast<char*>(new_mem);
4841e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
485fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif
4861e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
4873f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(uptr, strlen, const char *s) {
48850f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko  if (!asan_inited) return internal_strlen(s);
4891e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // strlen is called from malloc_default_purgeable_zone()
4901e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // in __asan::ReplaceSystemAlloc() on Mac.
4911e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (asan_init_is_running) {
49209672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(strlen)(s);
4931e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
494e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
4953f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  uptr length = REAL(strlen)(s);
496cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_str) {
4971e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(s, length + 1);
4981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
4991e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return length;
5001e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
5011e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
5023f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(int, strncmp, const char *s1, const char *s2, uptr size) {
50350f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko  if (!asan_inited) return internal_strncmp(s1, s2, size);
5041e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // strncmp is called from malloc_default_purgeable_zone()
5051e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // in __asan::ReplaceSystemAlloc() on Mac.
5061e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (asan_init_is_running) {
50709672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(strncmp)(s1, s2, size);
5081e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
5098648e7734ff02a25706464e9e294bd217622bcaeKostya Serebryany  ENSURE_ASAN_INITED();
5101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  unsigned char c1 = 0, c2 = 0;
5113f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  uptr i;
5121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  for (i = 0; i < size; i++) {
5131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    c1 = (unsigned char)s1[i];
5141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    c2 = (unsigned char)s2[i];
5151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    if (c1 != c2 || c1 == '\0') break;
5161e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
5172d8b3bdb112ebb8ed3f15ee41d4cebcd683b41b0Kostya Serebryany  ASAN_READ_RANGE(s1, Min(i + 1, size));
5182d8b3bdb112ebb8ed3f15ee41d4cebcd683b41b0Kostya Serebryany  ASAN_READ_RANGE(s2, Min(i + 1, size));
5191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return CharCmp(c1, c2);
5201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
5211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
5223f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) {
523e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
524cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_str) {
525c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov    uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1);
526c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany    CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size);
5271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(from, from_size);
5281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_WRITE_RANGE(to, size);
5291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
53009672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(strncpy)(to, from, size);
5311e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
5321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
53381a7a4ab53c94e76c3b131d6f0ed82894640900bAlexey Samsonov#if ASAN_INTERCEPT_STRNLEN
5343f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(uptr, strnlen, const char *s, uptr maxlen) {
535e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
5363f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  uptr length = REAL(strnlen)(s, maxlen);
537cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_str) {
5382d8b3bdb112ebb8ed3f15ee41d4cebcd683b41b0Kostya Serebryany    ASAN_READ_RANGE(s, Min(length + 1, maxlen));
5391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
5401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return length;
5411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
54281a7a4ab53c94e76c3b131d6f0ed82894640900bAlexey Samsonov#endif  // ASAN_INTERCEPT_STRNLEN
543547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany
5448f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonovstatic inline bool IsValidStrtolBase(int base) {
5458f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  return (base == 0) || (2 <= base && base <= 36);
5468f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov}
5478f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov
5488f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonovstatic inline void FixRealStrtolEndptr(const char *nptr, char **endptr) {
549a27bdf70ca24202dce21cf7c1a387aeaa400d889Kostya Serebryany  CHECK(endptr);
5508f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  if (nptr == *endptr) {
5518f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    // No digits were found at strtol call, we need to find out the last
5528f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    // symbol accessed by strtoll on our own.
5538f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    // We get this symbol by skipping leading blanks and optional +/- sign.
5548f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    while (IsSpace(*nptr)) nptr++;
5558f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    if (*nptr == '+' || *nptr == '-') nptr++;
5568f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    *endptr = (char*)nptr;
5578f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  }
5588f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  CHECK(*endptr >= nptr);
55984ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov}
56084ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov
561847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR(long, strtol, const char *nptr,  // NOLINT
56284ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov            char **endptr, int base) {
56384ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov  ENSURE_ASAN_INITED();
564cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (!flags()->replace_str) {
565847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov    return REAL(strtol)(nptr, endptr, base);
56684ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov  }
56784ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov  char *real_endptr;
568847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  long result = REAL(strtol)(nptr, &real_endptr, base);  // NOLINT
5693f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  if (endptr != 0) {
57084ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov    *endptr = real_endptr;
57184ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov  }
5728f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  if (IsValidStrtolBase(base)) {
5738f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    FixRealStrtolEndptr(nptr, &real_endptr);
57484ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov    ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
57584ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov  }
57684ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov  return result;
57784ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov}
57884ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov
579847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR(int, atoi, const char *nptr) {
58024e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#if SANITIZER_MAC
5810ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko  if (!asan_inited) return REAL(atoi)(nptr);
5820ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko#endif
583847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  ENSURE_ASAN_INITED();
584cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (!flags()->replace_str) {
585847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov    return REAL(atoi)(nptr);
586847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  }
587847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  char *real_endptr;
588847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  // "man atoi" tells that behavior of atoi(nptr) is the same as
5893f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
590847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  // parsed integer can't be stored in *long* type (even if it's
591847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  // different from int). So, we just imitate this behavior.
592847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  int result = REAL(strtol)(nptr, &real_endptr, 10);
593847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  FixRealStrtolEndptr(nptr, &real_endptr);
594847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
595847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  return result;
596847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov}
597847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov
598847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR(long, atol, const char *nptr) {  // NOLINT
59924e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#if SANITIZER_MAC
6000ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko  if (!asan_inited) return REAL(atol)(nptr);
6010ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko#endif
602847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  ENSURE_ASAN_INITED();
603cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (!flags()->replace_str) {
604847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov    return REAL(atol)(nptr);
605847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  }
606847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  char *real_endptr;
607847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  long result = REAL(strtol)(nptr, &real_endptr, 10);  // NOLINT
608847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  FixRealStrtolEndptr(nptr, &real_endptr);
609847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
610847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  return result;
611847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov}
612847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov
613847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
614847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR(long long, strtoll, const char *nptr,  // NOLINT
6158f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov            char **endptr, int base) {
6168f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  ENSURE_ASAN_INITED();
617cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (!flags()->replace_str) {
618847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov    return REAL(strtoll)(nptr, endptr, base);
6198f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  }
6208f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  char *real_endptr;
621847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  long long result = REAL(strtoll)(nptr, &real_endptr, base);  // NOLINT
6223f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  if (endptr != 0) {
6238f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    *endptr = real_endptr;
6248f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  }
625847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  // If base has unsupported value, strtoll can exit with EINVAL
626847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  // without reading any characters. So do additional checks only
627847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  // if base is valid.
6288f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  if (IsValidStrtolBase(base)) {
6298f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    FixRealStrtolEndptr(nptr, &real_endptr);
6308f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
6318f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  }
6328f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  return result;
6338f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov}
6348f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov
635847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR(long long, atoll, const char *nptr) {  // NOLINT
636847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  ENSURE_ASAN_INITED();
637cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (!flags()->replace_str) {
638847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov    return REAL(atoll)(nptr);
639847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  }
640847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  char *real_endptr;
641847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  long long result = REAL(strtoll)(nptr, &real_endptr, 10);  // NOLINT
642847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  FixRealStrtolEndptr(nptr, &real_endptr);
643847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
644847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  return result;
645847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov}
646847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov#endif  // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
647847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov
64846efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonovstatic void AtCxaAtexit(void *unused) {
64946efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov  (void)unused;
65046efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov  StopInitOrderChecking();
65146efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov}
65246efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov
65346efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov#if ASAN_INTERCEPT___CXA_ATEXIT
65446efcb09dc16b91cb805abea52f3ff6081a63751Alexey SamsonovINTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
65546efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov            void *dso_handle) {
65646efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov  ENSURE_ASAN_INITED();
65746efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov  int res = REAL(__cxa_atexit)(func, arg, dso_handle);
65846efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov  REAL(__cxa_atexit)(AtCxaAtexit, 0, 0);
65946efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov  return res;
66046efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov}
66146efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov#endif  // ASAN_INTERCEPT___CXA_ATEXIT
66246efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov
663fd55281122b4dedceb4e5a2fedc3946bfba9032bAlexander Potapenko#if !SANITIZER_MAC
664580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov#define ASAN_INTERCEPT_FUNC(name) do { \
665cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov      if (!INTERCEPT_FUNCTION(name) && flags()->verbosity > 0) \
666580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov        Report("AddressSanitizer: failed to intercept '" #name "'\n"); \
667580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov    } while (0)
668fd55281122b4dedceb4e5a2fedc3946bfba9032bAlexander Potapenko#else
669fd55281122b4dedceb4e5a2fedc3946bfba9032bAlexander Potapenko// OS X interceptors don't need to be initialized with INTERCEPT_FUNCTION.
670fd55281122b4dedceb4e5a2fedc3946bfba9032bAlexander Potapenko#define ASAN_INTERCEPT_FUNC(name)
671fd55281122b4dedceb4e5a2fedc3946bfba9032bAlexander Potapenko#endif  // SANITIZER_MAC
672580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov
67324e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#if SANITIZER_WINDOWS
674600972e3427173cc8904d741decd1af0ed5de9fdTimur IskhodzhanovINTERCEPTOR_WINAPI(DWORD, CreateThread,
6753f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany                   void* security, uptr stack_size,
676600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov                   DWORD (__stdcall *start_routine)(void*), void* arg,
677b9a928497168e177791f10f5042ff6f5e4e8a881Alexey Samsonov                   DWORD thr_flags, void* tid) {
678bdd0966deb04068ea94cf416c7fb46516013bd26Alexey Samsonov  // Strict init-order checking in thread-hostile.
6799465cbdbe73590746b57916f46ea1aa4bf3dd13dAlexey Samsonov  if (flags()->strict_init_order)
6809465cbdbe73590746b57916f46ea1aa4bf3dd13dAlexey Samsonov    StopInitOrderChecking();
681a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  GET_STACK_TRACE_THREAD;
68289c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov  u32 current_tid = GetCurrentTidOrInvalid();
683dfe3f9691d4700981566a4b57e1e482f72783950Alexey Samsonov  AsanThread *t = AsanThread::Create(start_routine, arg);
684dfe3f9691d4700981566a4b57e1e482f72783950Alexey Samsonov  CreateThreadContextArgs args = { t, &stack };
6858d2438a7ebb01201c652f91d1e8043a1f3d03bffTimur Iskhodzhanov  bool detached = false;  // FIXME: how can we determine it on Windows?
686dfe3f9691d4700981566a4b57e1e482f72783950Alexey Samsonov  asanThreadRegistry().CreateThread(*(uptr*)t, detached, current_tid, &args);
687600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  return REAL(CreateThread)(security, stack_size,
688b9a928497168e177791f10f5042ff6f5e4e8a881Alexey Samsonov                            asan_thread_start, t, thr_flags, tid);
689600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov}
690600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov
691600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanovnamespace __asan {
692600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanovvoid InitializeWindowsInterceptors() {
693580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(CreateThread);
694600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov}
695600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov
696600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov}  // namespace __asan
697600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov#endif
698600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov
699547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany// ---------------------- InitializeAsanInterceptors ---------------- {{{1
700547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryanynamespace __asan {
701547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryanyvoid InitializeAsanInterceptors() {
702fdbdab5ff8de4c23b58bb411ea2358a78e2d9b2fKostya Serebryany  static bool was_called_once;
703fdbdab5ff8de4c23b58bb411ea2358a78e2d9b2fKostya Serebryany  CHECK(was_called_once == false);
704fdbdab5ff8de4c23b58bb411ea2358a78e2d9b2fKostya Serebryany  was_called_once = true;
7058530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany  SANITIZER_COMMON_INTERCEPTORS_INIT;
7068530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany
70707bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  // Intercept mem* functions.
708580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(memcmp);
709580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(memmove);
710580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(memset);
71138dd4ed885e714c376466f6fe0d69f5f22d37014Alexey Samsonov  if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) {
712580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov    ASAN_INTERCEPT_FUNC(memcpy);
713573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko  }
71407bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov
71507bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  // Intercept str* functions.
716580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strcat);  // NOLINT
717580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strchr);
718580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strcmp);
719580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strcpy);  // NOLINT
720580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strlen);
721c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov  ASAN_INTERCEPT_FUNC(strncat);
722580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strncmp);
723580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strncpy);
724fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_STRDUP
725fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  ASAN_INTERCEPT_FUNC(strdup);
726fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif
727fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_STRNLEN
728fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  ASAN_INTERCEPT_FUNC(strnlen);
729fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif
73069563986ca570ce750111a82264d51ddbf4107baAlexander Potapenko#if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
731580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(index);
73207bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov#endif
7335b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov
734580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(atoi);
735580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(atol);
736580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strtol);
737847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
738580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(atoll);
739580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strtoll);
74084ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov#endif
74184ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov
742f0c6de3d91ba5cdfbb17a630e823523c7d433160Alexander Potapenko#if ASAN_INTERCEPT_MLOCKX
74300f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko  // Intercept mlock/munlock.
74400f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko  ASAN_INTERCEPT_FUNC(mlock);
74500f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko  ASAN_INTERCEPT_FUNC(munlock);
74600f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko  ASAN_INTERCEPT_FUNC(mlockall);
74700f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko  ASAN_INTERCEPT_FUNC(munlockall);
748f0c6de3d91ba5cdfbb17a630e823523c7d433160Alexander Potapenko#endif
74900f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko
75007bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  // Intecept signal- and jump-related functions.
751580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(longjmp);
75234a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
753580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(sigaction);
754580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(signal);
755919c24787a655597bdcf367e26c9dd1504e9f463Evgeniy Stepanov#endif
7560870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov#if ASAN_INTERCEPT_SWAPCONTEXT
7570870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  ASAN_INTERCEPT_FUNC(swapcontext);
7580870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov#endif
759fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT__LONGJMP
760580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(_longjmp);
761fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif
762fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_SIGLONGJMP
763580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(siglongjmp);
764fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif
765fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov
766fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  // Intercept exception handling functions.
767fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT___CXA_THROW
768fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  INTERCEPT_FUNCTION(__cxa_throw);
7693e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov#endif
7703e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov
77107bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  // Intercept threading-related functions
772fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_PTHREAD_CREATE
773580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(pthread_create);
77407bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov#endif
77507bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov
77646efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov  // Intercept atexit function.
77746efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov#if ASAN_INTERCEPT___CXA_ATEXIT
77846efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov  ASAN_INTERCEPT_FUNC(__cxa_atexit);
77946efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov#endif
78046efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov
781600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  // Some Windows-specific interceptors.
78224e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#if SANITIZER_WINDOWS
783600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  InitializeWindowsInterceptors();
784600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov#endif
785600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov
786cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->verbosity > 0) {
7872962f26071ebef1d5fec52b5569e5ae7aae45c9bAlexander Potapenko    Report("AddressSanitizer: libc interceptors initialized\n");
788547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  }
789547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany}
790547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany
791547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany}  // namespace __asan
792