asan_interceptors.cc revision e236dbb5e558b174609d2d13e80685d488c129d8
17a653cb24d4dda283d34c984e81514ac1547796eGordon Henriksen//===-- asan_interceptors.cc ----------------------------------------------===//
28ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen//
38ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen//                     The LLVM Compiler Infrastructure
48ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen//
58ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen// This file is distributed under the University of Illinois Open Source
68ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen// License. See LICENSE.TXT for details.
78ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen//
88ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen//===----------------------------------------------------------------------===//
98ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen//
108ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen// This file is a part of AddressSanitizer, an address sanity checker.
118ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen//
128ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen// Intercept various libc functions.
138ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen//===----------------------------------------------------------------------===//
14344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen#include "asan_interceptors.h"
158ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen
168ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen#include "asan_allocator.h"
178ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen#include "asan_intercepted_functions.h"
188ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen#include "asan_internal.h"
198ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen#include "asan_mapping.h"
20344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen#include "asan_poisoning.h"
218ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen#include "asan_report.h"
228ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen#include "asan_stack.h"
238ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen#include "asan_stats.h"
24404a1942e43ca967700cc2608eb97b863add2677Gordon Henriksen#include "interception/interception.h"
2580a75bfae980df96f969f1c05b0c4a80ce975240Gordon Henriksen#include "sanitizer_common/sanitizer_libc.h"
2680a75bfae980df96f969f1c05b0c4a80ce975240Gordon Henriksen
278ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksennamespace __asan {
288ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen
298ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen// Return true if we can quickly decide that the region is unpoisoned.
308ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksenstatic inline bool QuickCheckForUnpoisonedRegion(uptr beg, uptr size) {
318ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  if (size == 0) return true;
328ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  if (size <= 32)
338ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen    return !AddressIsPoisoned(beg) &&
348ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen           !AddressIsPoisoned(beg + size - 1) &&
358ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen           !AddressIsPoisoned(beg + size / 2);
368ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  return false;
378ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen}
388ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen
39a353ffa7e556bfd2864474911174da691117f691Gordon Henriksen// We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE,
40a353ffa7e556bfd2864474911174da691117f691Gordon Henriksen// and ASAN_WRITE_RANGE as macro instead of function so
41a353ffa7e556bfd2864474911174da691117f691Gordon Henriksen// that no extra frames are created, and stack trace contains
42a353ffa7e556bfd2864474911174da691117f691Gordon Henriksen// relevant information only.
43a353ffa7e556bfd2864474911174da691117f691Gordon Henriksen// We check all shadow bytes.
44a353ffa7e556bfd2864474911174da691117f691Gordon Henriksen#define ACCESS_MEMORY_RANGE(offset, size, isWrite) do {                 \
45a353ffa7e556bfd2864474911174da691117f691Gordon Henriksen    uptr __offset = (uptr)(offset);                                     \
46a353ffa7e556bfd2864474911174da691117f691Gordon Henriksen    uptr __size = (uptr)(size);                                         \
47a353ffa7e556bfd2864474911174da691117f691Gordon Henriksen    uptr __bad = 0;                                                     \
48a353ffa7e556bfd2864474911174da691117f691Gordon Henriksen    if (!QuickCheckForUnpoisonedRegion(__offset, __size) &&             \
49a353ffa7e556bfd2864474911174da691117f691Gordon Henriksen        (__bad = __asan_region_is_poisoned(__offset, __size))) {        \
50a353ffa7e556bfd2864474911174da691117f691Gordon Henriksen      GET_CURRENT_PC_BP_SP;                                             \
51a353ffa7e556bfd2864474911174da691117f691Gordon Henriksen      __asan_report_error(pc, bp, sp, __bad, isWrite, __size);          \
52a353ffa7e556bfd2864474911174da691117f691Gordon Henriksen    }                                                                   \
53a353ffa7e556bfd2864474911174da691117f691Gordon Henriksen  } while (0)
54a353ffa7e556bfd2864474911174da691117f691Gordon Henriksen
55a353ffa7e556bfd2864474911174da691117f691Gordon Henriksen#define ASAN_READ_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size, false)
56a353ffa7e556bfd2864474911174da691117f691Gordon Henriksen#define ASAN_WRITE_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size, true)
57a353ffa7e556bfd2864474911174da691117f691Gordon Henriksen
588ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen// Behavior of functions like "memcpy" or "strcpy" is undefined
598ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen// if memory intervals overlap. We report error in this case.
608ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen// Macro is used to avoid creation of new frames.
618ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksenstatic inline bool RangesOverlap(const char *offset1, uptr length1,
628ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen                                 const char *offset2, uptr length2) {
638ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  return !((offset1 + length1 <= offset2) || (offset2 + length2 <= offset1));
6446abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen}
65404a1942e43ca967700cc2608eb97b863add2677Gordon Henriksen#define CHECK_RANGES_OVERLAP(name, _offset1, length1, _offset2, length2) do { \
668ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  const char *offset1 = (const char*)_offset1; \
678ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  const char *offset2 = (const char*)_offset2; \
688ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  if (RangesOverlap(offset1, length1, offset2, length2)) { \
698ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen    GET_STACK_TRACE_FATAL_HERE; \
7046abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen    ReportStringFunctionMemoryRangesOverlap(name, offset1, length1, \
71404a1942e43ca967700cc2608eb97b863add2677Gordon Henriksen                                            offset2, length2, &stack); \
728ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  } \
738ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen} while (0)
748ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen
758ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen#define ENSURE_ASAN_INITED() do { \
7646abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  CHECK(!asan_init_is_running); \
778ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  if (!asan_inited) { \
788ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen    __asan_init(); \
798ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  } \
808ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen} while (0)
81957f9fe1cce0957bcde4a1093da83e17aaec6764Gordon Henriksen
8246abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksenstatic inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) {
838ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen#if ASAN_INTERCEPT_STRNLEN
848ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  if (REAL(strnlen) != 0) {
858ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen    return REAL(strnlen)(s, maxlen);
868ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  }
8746abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#endif
88404a1942e43ca967700cc2608eb97b863add2677Gordon Henriksen  return internal_strnlen(s, maxlen);
898ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen}
908ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen
918ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksenvoid SetThreadName(const char *name) {
928ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  AsanThread *t = GetCurrentThread();
9346abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  if (t)
94404a1942e43ca967700cc2608eb97b863add2677Gordon Henriksen    asanThreadRegistry().SetThreadName(t->tid(), name);
958ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen}
968ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen
978ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksenint OnExit() {
988ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  // FIXME: ask frontend whether we need to return failure.
99957f9fe1cce0957bcde4a1093da83e17aaec6764Gordon Henriksen  return 0;
10046abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen}
101404a1942e43ca967700cc2608eb97b863add2677Gordon Henriksen
1028ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen}  // namespace __asan
1038ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen
1048ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen// ---------------------- Wrappers ---------------- {{{1
1058ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksenusing namespace __asan;  // NOLINT
1068ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen
1078ef426baa36639458f6777309db25c1768dc9c8aGordon HenriksenDECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr)
108957f9fe1cce0957bcde4a1093da83e17aaec6764Gordon HenriksenDECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
109957f9fe1cce0957bcde4a1093da83e17aaec6764Gordon Henriksen
11046abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#define COMMON_INTERCEPTOR_UNPOISON_PARAM(ctx, count) \
1118ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  do {                                                \
1128ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  } while (false)
1138ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
1148ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  ASAN_WRITE_RANGE(ptr, size)
1158ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) ASAN_READ_RANGE(ptr, size)
116957f9fe1cce0957bcde4a1093da83e17aaec6764Gordon Henriksen#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...)              \
11746abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  do {                                                        \
1188ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen    if (asan_init_is_running) return REAL(func)(__VA_ARGS__); \
1198ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen    ctx = 0;                                                  \
120404a1942e43ca967700cc2608eb97b863add2677Gordon Henriksen    (void) ctx;                                               \
1218ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen    ENSURE_ASAN_INITED();                                     \
12257cebeec7ba08b55f29f5bf98ad0a3a17e9d0c71Gordon Henriksen  } while (false)
12357cebeec7ba08b55f29f5bf98ad0a3a17e9d0c71Gordon Henriksen#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
12457cebeec7ba08b55f29f5bf98ad0a3a17e9d0c71Gordon Henriksen  do {                                         \
12557cebeec7ba08b55f29f5bf98ad0a3a17e9d0c71Gordon Henriksen  } while (false)
12657cebeec7ba08b55f29f5bf98ad0a3a17e9d0c71Gordon Henriksen#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
12757cebeec7ba08b55f29f5bf98ad0a3a17e9d0c71Gordon Henriksen  do {                                         \
12857cebeec7ba08b55f29f5bf98ad0a3a17e9d0c71Gordon Henriksen  } while (false)
129404a1942e43ca967700cc2608eb97b863add2677Gordon Henriksen#define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
13057cebeec7ba08b55f29f5bf98ad0a3a17e9d0c71Gordon Henriksen  do {                                                      \
13157cebeec7ba08b55f29f5bf98ad0a3a17e9d0c71Gordon Henriksen  } while (false)
13257cebeec7ba08b55f29f5bf98ad0a3a17e9d0c71Gordon Henriksen#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name)
133ef989a275c1191f583178c6934f3594e7a9fd3a6Christopher Lamb#define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
13457cebeec7ba08b55f29f5bf98ad0a3a17e9d0c71Gordon Henriksen#define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
13557cebeec7ba08b55f29f5bf98ad0a3a17e9d0c71Gordon Henriksen#include "sanitizer_common/sanitizer_common_interceptors.inc"
13657cebeec7ba08b55f29f5bf98ad0a3a17e9d0c71Gordon Henriksen
13757cebeec7ba08b55f29f5bf98ad0a3a17e9d0c71Gordon Henriksen#define COMMON_SYSCALL_PRE_READ_RANGE(p, s) ASAN_READ_RANGE(p, s)
13857cebeec7ba08b55f29f5bf98ad0a3a17e9d0c71Gordon Henriksen#define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) ASAN_WRITE_RANGE(p, s)
13957cebeec7ba08b55f29f5bf98ad0a3a17e9d0c71Gordon Henriksen#define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
1408ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  do {                                       \
1418ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  } while (false)
1428ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen#define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \
1438ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  do {                                        \
144957f9fe1cce0957bcde4a1093da83e17aaec6764Gordon Henriksen  } while (false)
14546abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#include "sanitizer_common/sanitizer_common_syscalls.inc"
1468ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen
1478ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksenstatic thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
1488ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  AsanThread *t = (AsanThread*)arg;
1498ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  SetCurrentThread(t);
1508ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  return t->ThreadStart(GetTid());
1518ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen}
152957f9fe1cce0957bcde4a1093da83e17aaec6764Gordon Henriksen
15346abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#if ASAN_INTERCEPT_PTHREAD_CREATE
1548ef426baa36639458f6777309db25c1768dc9c8aGordon HenriksenINTERCEPTOR(int, pthread_create, void *thread,
155957f9fe1cce0957bcde4a1093da83e17aaec6764Gordon Henriksen    void *attr, void *(*start_routine)(void*), void *arg) {
15646abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  EnsureMainThreadIDIsCorrect();
15746abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  // Strict init-order checking in thread-hostile.
15846abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  if (flags()->strict_init_order)
15946abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen    StopInitOrderChecking();
160957f9fe1cce0957bcde4a1093da83e17aaec6764Gordon Henriksen  GET_STACK_TRACE_THREAD;
16146abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  int detached = 0;
1621cf08fddc7413076dedad58dbb8d8d67e69a490fGordon Henriksen  if (attr != 0)
1631cf08fddc7413076dedad58dbb8d8d67e69a490fGordon Henriksen    pthread_attr_getdetachstate(attr, &detached);
1641cf08fddc7413076dedad58dbb8d8d67e69a490fGordon Henriksen
1651cf08fddc7413076dedad58dbb8d8d67e69a490fGordon Henriksen  u32 current_tid = GetCurrentTidOrInvalid();
1661cf08fddc7413076dedad58dbb8d8d67e69a490fGordon Henriksen  AsanThread *t = AsanThread::Create(start_routine, arg);
1671cf08fddc7413076dedad58dbb8d8d67e69a490fGordon Henriksen  CreateThreadContextArgs args = { t, &stack };
1681cf08fddc7413076dedad58dbb8d8d67e69a490fGordon Henriksen  asanThreadRegistry().CreateThread(*(uptr*)t, detached, current_tid, &args);
1691cf08fddc7413076dedad58dbb8d8d67e69a490fGordon Henriksen  return REAL(pthread_create)(thread, attr, asan_thread_start, t);
1701cf08fddc7413076dedad58dbb8d8d67e69a490fGordon Henriksen}
1711cf08fddc7413076dedad58dbb8d8d67e69a490fGordon Henriksen#endif  // ASAN_INTERCEPT_PTHREAD_CREATE
1721cf08fddc7413076dedad58dbb8d8d67e69a490fGordon Henriksen
1738ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
1748ef426baa36639458f6777309db25c1768dc9c8aGordon HenriksenINTERCEPTOR(void*, signal, int signum, void *handler) {
175344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen  if (!AsanInterceptsSignal(signum) || flags()->allow_user_segv_handler) {
176344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen    return REAL(signal)(signum, handler);
177344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen  }
178344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen  return 0;
179344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen}
180344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen
181e3b989d4a4ba47f77d5d38c35ff17e9673d9f87bGordon HenriksenINTERCEPTOR(int, sigaction, int signum, const struct sigaction *act,
182344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen                            struct sigaction *oldact) {
183344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen  if (!AsanInterceptsSignal(signum) || flags()->allow_user_segv_handler) {
184344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen    return REAL(sigaction)(signum, act, oldact);
185344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen  }
186344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen  return 0;
187344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen}
188344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen#elif SANITIZER_POSIX
189e3b989d4a4ba47f77d5d38c35ff17e9673d9f87bGordon Henriksen// We need to have defined REAL(sigaction) on posix systems.
190344be5fbecec9908bab611eafeae0549ba3be6d7Gordon HenriksenDEFINE_REAL(int, sigaction, int signum, const struct sigaction *act,
191344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen    struct sigaction *oldact)
192344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen#endif  // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
193344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen
194344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen#if ASAN_INTERCEPT_SWAPCONTEXT
195344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksenstatic void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) {
196e3b989d4a4ba47f77d5d38c35ff17e9673d9f87bGordon Henriksen  // Align to page size.
197344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen  uptr PageSize = GetPageSizeCached();
198344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen  uptr bottom = stack & ~(PageSize - 1);
199344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen  ssize += stack - bottom;
200344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen  ssize = RoundUpTo(ssize, PageSize);
201344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen  static const uptr kMaxSaneContextStackSize = 1 << 22;  // 4 Mb
202344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen  if (ssize && ssize <= kMaxSaneContextStackSize) {
203e3b989d4a4ba47f77d5d38c35ff17e9673d9f87bGordon Henriksen    PoisonShadow(bottom, ssize, 0);
204344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen  }
205957f9fe1cce0957bcde4a1093da83e17aaec6764Gordon Henriksen}
206344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen
207344be5fbecec9908bab611eafeae0549ba3be6d7Gordon HenriksenINTERCEPTOR(int, swapcontext, struct ucontext_t *oucp,
208344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen            struct ucontext_t *ucp) {
209e3b989d4a4ba47f77d5d38c35ff17e9673d9f87bGordon Henriksen  static bool reported_warning = false;
210e3b989d4a4ba47f77d5d38c35ff17e9673d9f87bGordon Henriksen  if (!reported_warning) {
211344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen    Report("WARNING: ASan doesn't fully support makecontext/swapcontext "
212957f9fe1cce0957bcde4a1093da83e17aaec6764Gordon Henriksen           "functions and may produce false positives in some cases!\n");
213344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen    reported_warning = true;
214344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen  }
215344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen  // Clear shadow memory for new context (it may share stack
216344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen  // with current context).
217e3b989d4a4ba47f77d5d38c35ff17e9673d9f87bGordon Henriksen  uptr stack, ssize;
218344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen  ReadContextStack(ucp, &stack, &ssize);
219344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen  ClearShadowMemoryForContextStack(stack, ssize);
220344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen  int res = REAL(swapcontext)(oucp, ucp);
221e3b989d4a4ba47f77d5d38c35ff17e9673d9f87bGordon Henriksen  // swapcontext technically does not return, but program may swap context to
222e3b989d4a4ba47f77d5d38c35ff17e9673d9f87bGordon Henriksen  // "oucp" later, that would look as if swapcontext() returned 0.
223e3b989d4a4ba47f77d5d38c35ff17e9673d9f87bGordon Henriksen  // We need to clear shadow for ucp once again, as it may be in arbitrary
224e3b989d4a4ba47f77d5d38c35ff17e9673d9f87bGordon Henriksen  // state.
225344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen  ClearShadowMemoryForContextStack(stack, ssize);
226344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen  return res;
227344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen}
228344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen#endif  // ASAN_INTERCEPT_SWAPCONTEXT
229e3b989d4a4ba47f77d5d38c35ff17e9673d9f87bGordon Henriksen
230344be5fbecec9908bab611eafeae0549ba3be6d7Gordon HenriksenINTERCEPTOR(void, longjmp, void *env, int val) {
231957f9fe1cce0957bcde4a1093da83e17aaec6764Gordon Henriksen  __asan_handle_no_return();
232344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen  REAL(longjmp)(env, val);
233344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen}
234344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen
235344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen#if ASAN_INTERCEPT__LONGJMP
236e3b989d4a4ba47f77d5d38c35ff17e9673d9f87bGordon HenriksenINTERCEPTOR(void, _longjmp, void *env, int val) {
237e3b989d4a4ba47f77d5d38c35ff17e9673d9f87bGordon Henriksen  __asan_handle_no_return();
238344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen  REAL(_longjmp)(env, val);
239957f9fe1cce0957bcde4a1093da83e17aaec6764Gordon Henriksen}
240344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen#endif
241344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen
242344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen#if ASAN_INTERCEPT_SIGLONGJMP
243344be5fbecec9908bab611eafeae0549ba3be6d7Gordon HenriksenINTERCEPTOR(void, siglongjmp, void *env, int val) {
244e3b989d4a4ba47f77d5d38c35ff17e9673d9f87bGordon Henriksen  __asan_handle_no_return();
245344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen  REAL(siglongjmp)(env, val);
246957f9fe1cce0957bcde4a1093da83e17aaec6764Gordon Henriksen}
247344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen#endif
248344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen
249344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen#if ASAN_INTERCEPT___CXA_THROW
250344be5fbecec9908bab611eafeae0549ba3be6d7Gordon HenriksenINTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
251344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen  CHECK(REAL(__cxa_throw));
252957f9fe1cce0957bcde4a1093da83e17aaec6764Gordon Henriksen  __asan_handle_no_return();
253957f9fe1cce0957bcde4a1093da83e17aaec6764Gordon Henriksen  REAL(__cxa_throw)(a, b, c);
254344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen}
255344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen#endif
256344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen
257344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen// intercept mlock and friends.
258344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen// Since asan maps 16T of RAM, mlock is completely unfriendly to asan.
259e3b989d4a4ba47f77d5d38c35ff17e9673d9f87bGordon Henriksen// All functions return 0 (success).
260344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksenstatic void MlockIsUnsupported() {
261344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen  static bool printed = false;
262344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen  if (printed) return;
263344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen  printed = true;
264344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen  if (common_flags()->verbosity > 0) {
265e3b989d4a4ba47f77d5d38c35ff17e9673d9f87bGordon Henriksen    Printf("INFO: AddressSanitizer ignores "
266344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen           "mlock/mlockall/munlock/munlockall\n");
267344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen  }
2684647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen}
2694647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen
2704647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon HenriksenINTERCEPTOR(int, mlock, const void *addr, uptr len) {
2714647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen  MlockIsUnsupported();
2724647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen  return 0;
2734647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen}
2744647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen
2754647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon HenriksenINTERCEPTOR(int, munlock, const void *addr, uptr len) {
2764647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen  MlockIsUnsupported();
2774647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen  return 0;
2784647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen}
2794647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen
2804647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon HenriksenINTERCEPTOR(int, mlockall, int flags) {
2814647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen  MlockIsUnsupported();
2824647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen  return 0;
2834647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen}
2844647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen
2854647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon HenriksenINTERCEPTOR(int, munlockall, void) {
2864647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen  MlockIsUnsupported();
2874647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen  return 0;
288957f9fe1cce0957bcde4a1093da83e17aaec6764Gordon Henriksen}
289e3b989d4a4ba47f77d5d38c35ff17e9673d9f87bGordon Henriksen
2904647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksenstatic inline int CharCmp(unsigned char c1, unsigned char c2) {
291e3b989d4a4ba47f77d5d38c35ff17e9673d9f87bGordon Henriksen  return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
2924647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen}
2934647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen
2944647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon HenriksenINTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {
2954647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen  if (!asan_inited) return internal_memcmp(a1, a2, size);
2964647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen  ENSURE_ASAN_INITED();
2974647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen  if (flags()->replace_intrin) {
2984647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen    if (flags()->strict_memcmp) {
2994647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen      // Check the entire regions even if the first bytes of the buffers are
3004647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen      // different.
3014647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen      ASAN_READ_RANGE(a1, size);
3024647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen      ASAN_READ_RANGE(a2, size);
3034647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen      // Fallthrough to REAL(memcmp) below.
3044647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen    } else {
3054647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen      unsigned char c1 = 0, c2 = 0;
3064647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen      const unsigned char *s1 = (const unsigned char*)a1;
3074647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen      const unsigned char *s2 = (const unsigned char*)a2;
308404a1942e43ca967700cc2608eb97b863add2677Gordon Henriksen      uptr i;
309404a1942e43ca967700cc2608eb97b863add2677Gordon Henriksen      for (i = 0; i < size; i++) {
3104647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen        c1 = s1[i];
3114647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen        c2 = s2[i];
3124647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen        if (c1 != c2) break;
3134647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen      }
3144647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen      ASAN_READ_RANGE(s1, Min(i + 1, size));
3154647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen      ASAN_READ_RANGE(s2, Min(i + 1, size));
3164647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen      return CharCmp(c1, c2);
3174647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen    }
3184647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen  }
3194647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen  return REAL(memcmp(a1, a2, size));
3204647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen}
3214647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen
3224647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen#define MEMMOVE_BODY { \
3234647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen  if (!asan_inited) return internal_memmove(to, from, size); \
3244647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen  if (asan_init_is_running) { \
325957f9fe1cce0957bcde4a1093da83e17aaec6764Gordon Henriksen    return REAL(memmove)(to, from, size); \
3264647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen  } \
3274647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen  ENSURE_ASAN_INITED(); \
3284647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen  if (flags()->replace_intrin) { \
3294647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen    ASAN_READ_RANGE(from, size); \
3304647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen    ASAN_WRITE_RANGE(to, size); \
3314647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen  } \
3324647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen  return internal_memmove(to, from, size); \
3334647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen}
3344647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen
3354647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon HenriksenINTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) MEMMOVE_BODY
3364647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen
337957f9fe1cce0957bcde4a1093da83e17aaec6764Gordon HenriksenINTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) {
338e3b989d4a4ba47f77d5d38c35ff17e9673d9f87bGordon Henriksen#if !SANITIZER_MAC
3394647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen  if (!asan_inited) return internal_memcpy(to, from, size);
3404647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen  // memcpy is called during __asan_init() from the internals
3414647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen  // of printf(...).
3424647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen  if (asan_init_is_running) {
3434647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen    return REAL(memcpy)(to, from, size);
3444647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen  }
3454647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen  ENSURE_ASAN_INITED();
3464647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen  if (flags()->replace_intrin) {
3474647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen    if (to != from) {
3484647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen      // We do not treat memcpy with to==from as a bug.
3494647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen      // See http://llvm.org/bugs/show_bug.cgi?id=11763.
3504647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen      CHECK_RANGES_OVERLAP("memcpy", to, size, from, size);
3514647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen    }
352957f9fe1cce0957bcde4a1093da83e17aaec6764Gordon Henriksen    ASAN_READ_RANGE(from, size);
3534647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen    ASAN_WRITE_RANGE(to, size);
3544647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen  }
355404a1942e43ca967700cc2608eb97b863add2677Gordon Henriksen  // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8, so
356e3b989d4a4ba47f77d5d38c35ff17e9673d9f87bGordon Henriksen  // calling REAL(memcpy) here leads to infinite recursion.
357e3b989d4a4ba47f77d5d38c35ff17e9673d9f87bGordon Henriksen  // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116.
358e3b989d4a4ba47f77d5d38c35ff17e9673d9f87bGordon Henriksen  return internal_memcpy(to, from, size);
359e3b989d4a4ba47f77d5d38c35ff17e9673d9f87bGordon Henriksen#else
3604647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen  // At least on 10.7 and 10.8 both memcpy() and memmove() are being replaced
361e3b989d4a4ba47f77d5d38c35ff17e9673d9f87bGordon Henriksen  // with WRAP(memcpy). As a result, false positives are reported for memmove()
3624647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen  // calls. If we just disable error reporting with
3634647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen  // ASAN_OPTIONS=replace_intrin=0, memmove() is still replaced with
364e3b989d4a4ba47f77d5d38c35ff17e9673d9f87bGordon Henriksen  // internal_memcpy(), which may lead to crashes, see
3654647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen  // http://llvm.org/bugs/show_bug.cgi?id=16362.
3664647569fe7706e76135a08ca0e5f90a447ccc5b4Gordon Henriksen  MEMMOVE_BODY
367e3b989d4a4ba47f77d5d38c35ff17e9673d9f87bGordon Henriksen#endif  // !SANITIZER_MAC
368e3b989d4a4ba47f77d5d38c35ff17e9673d9f87bGordon Henriksen}
369957f9fe1cce0957bcde4a1093da83e17aaec6764Gordon Henriksen
370344be5fbecec9908bab611eafeae0549ba3be6d7Gordon HenriksenINTERCEPTOR(void*, memset, void *block, int c, uptr size) {
371344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen  if (!asan_inited) return internal_memset(block, c, size);
3728ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  // memset is called inside Printf.
3738ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  if (asan_init_is_running) {
3748ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen    return REAL(memset)(block, c, size);
3758ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  }
376e3b989d4a4ba47f77d5d38c35ff17e9673d9f87bGordon Henriksen  ENSURE_ASAN_INITED();
3778ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  if (flags()->replace_intrin) {
3788ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen    ASAN_WRITE_RANGE(block, size);
3798ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  }
3808ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  return REAL(memset)(block, c, size);
3818ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen}
3828ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen
3838ef426baa36639458f6777309db25c1768dc9c8aGordon HenriksenINTERCEPTOR(char*, strchr, const char *str, int c) {
3848ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  if (!asan_inited) return internal_strchr(str, c);
3858ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  // strchr is called inside create_purgeable_zone() when MallocGuardEdges=1 is
3868ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  // used.
3878ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  if (asan_init_is_running) {
3888ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen    return REAL(strchr)(str, c);
3898ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  }
390404a1942e43ca967700cc2608eb97b863add2677Gordon Henriksen  ENSURE_ASAN_INITED();
391404a1942e43ca967700cc2608eb97b863add2677Gordon Henriksen  char *result = REAL(strchr)(str, c);
3928ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  if (flags()->replace_str) {
3938ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen    uptr bytes_read = (result ? result - str : REAL(strlen)(str)) + 1;
3948ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen    ASAN_READ_RANGE(str, bytes_read);
3958ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  }
3968ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  return result;
3978ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen}
3988ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen
3998ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen#if ASAN_INTERCEPT_INDEX
4008ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen# if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
4018ef426baa36639458f6777309db25c1768dc9c8aGordon HenriksenINTERCEPTOR(char*, index, const char *string, int c)
4028ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  ALIAS(WRAPPER_NAME(strchr));
4038ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen# else
404404a1942e43ca967700cc2608eb97b863add2677Gordon Henriksen#  if SANITIZER_MAC
405404a1942e43ca967700cc2608eb97b863add2677Gordon HenriksenDECLARE_REAL(char*, index, const char *string, int c)
4068ef426baa36639458f6777309db25c1768dc9c8aGordon HenriksenOVERRIDE_FUNCTION(index, strchr);
4078ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen#  else
4088ef426baa36639458f6777309db25c1768dc9c8aGordon HenriksenDEFINE_REAL(char*, index, const char *string, int c)
4098ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen#  endif
4108ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen# endif
4118ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen#endif  // ASAN_INTERCEPT_INDEX
4128ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen
4138ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen// For both strcat() and strncat() we need to check the validity of |to|
4148ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen// argument irrespective of the |from| length.
4158ef426baa36639458f6777309db25c1768dc9c8aGordon HenriksenINTERCEPTOR(char*, strcat, char *to, const char *from) {  // NOLINT
4168ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  ENSURE_ASAN_INITED();
4178ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  if (flags()->replace_str) {
4188ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen    uptr from_length = REAL(strlen)(from);
419e3b989d4a4ba47f77d5d38c35ff17e9673d9f87bGordon Henriksen    ASAN_READ_RANGE(from, from_length + 1);
4208ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen    uptr to_length = REAL(strlen)(to);
4218ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen    ASAN_READ_RANGE(to, to_length);
4228ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen    ASAN_WRITE_RANGE(to + to_length, from_length + 1);
4238ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen    // If the copying actually happens, the |from| string should not overlap
4246d6203dff3560a2cc3ac8ec620ac3b105b0c7cc7Gordon Henriksen    // with the resulting string starting at |to|, which has a length of
4258ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen    // to_length + from_length + 1.
4268ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen    if (from_length > 0) {
4276d6203dff3560a2cc3ac8ec620ac3b105b0c7cc7Gordon Henriksen      CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1,
4286d6203dff3560a2cc3ac8ec620ac3b105b0c7cc7Gordon Henriksen                           from, from_length + 1);
4296d6203dff3560a2cc3ac8ec620ac3b105b0c7cc7Gordon Henriksen    }
4306d6203dff3560a2cc3ac8ec620ac3b105b0c7cc7Gordon Henriksen  }
4316d6203dff3560a2cc3ac8ec620ac3b105b0c7cc7Gordon Henriksen  return REAL(strcat)(to, from);  // NOLINT
4328ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen}
4338ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen
4348ef426baa36639458f6777309db25c1768dc9c8aGordon HenriksenINTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
4358ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  ENSURE_ASAN_INITED();
4368ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  if (flags()->replace_str) {
4378ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen    uptr from_length = MaybeRealStrnlen(from, size);
4388ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen    uptr copy_length = Min(size, from_length + 1);
4398ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen    ASAN_READ_RANGE(from, copy_length);
4408ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen    uptr to_length = REAL(strlen)(to);
4418ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen    ASAN_READ_RANGE(to, to_length);
4428ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen    ASAN_WRITE_RANGE(to + to_length, from_length + 1);
4438ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen    if (from_length > 0) {
4448ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen      CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1,
4458ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen                           from, copy_length);
4468ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen    }
4478ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  }
4488ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen  return REAL(strncat)(to, from, size);
4498ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen}
4508ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen
4518ef426baa36639458f6777309db25c1768dc9c8aGordon HenriksenINTERCEPTOR(char*, strcpy, char *to, const char *from) {  // NOLINT
4528ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen#if SANITIZER_MAC
453344be5fbecec9908bab611eafeae0549ba3be6d7Gordon Henriksen  if (!asan_inited) return REAL(strcpy)(to, from);  // NOLINT
4548ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen#endif
455c84c16be9b29b4f805b92bfc2d93e2dfaa952f8fGordon Henriksen  // strcpy is called from malloc_default_purgeable_zone()
456c84c16be9b29b4f805b92bfc2d93e2dfaa952f8fGordon Henriksen  // in __asan::ReplaceSystemAlloc() on Mac.
457c84c16be9b29b4f805b92bfc2d93e2dfaa952f8fGordon Henriksen  if (asan_init_is_running) {
458c84c16be9b29b4f805b92bfc2d93e2dfaa952f8fGordon Henriksen    return REAL(strcpy)(to, from);  // NOLINT
459c84c16be9b29b4f805b92bfc2d93e2dfaa952f8fGordon Henriksen  }
460c84c16be9b29b4f805b92bfc2d93e2dfaa952f8fGordon Henriksen  ENSURE_ASAN_INITED();
461c84c16be9b29b4f805b92bfc2d93e2dfaa952f8fGordon Henriksen  if (flags()->replace_str) {
462c84c16be9b29b4f805b92bfc2d93e2dfaa952f8fGordon Henriksen    uptr from_size = REAL(strlen)(from) + 1;
463c84c16be9b29b4f805b92bfc2d93e2dfaa952f8fGordon Henriksen    CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size);
4648ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen    ASAN_READ_RANGE(from, from_size);
4658ef426baa36639458f6777309db25c1768dc9c8aGordon Henriksen    ASAN_WRITE_RANGE(to, from_size);
46646abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  }
46746abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  return REAL(strcpy)(to, from);  // NOLINT
46846abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen}
469957f9fe1cce0957bcde4a1093da83e17aaec6764Gordon Henriksen
4706d6203dff3560a2cc3ac8ec620ac3b105b0c7cc7Gordon Henriksen#if ASAN_INTERCEPT_STRDUP
47146abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon HenriksenINTERCEPTOR(char*, strdup, const char *s) {
47246abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  if (!asan_inited) return internal_strdup(s);
47346abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  ENSURE_ASAN_INITED();
47446abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  uptr length = REAL(strlen)(s);
4756d6203dff3560a2cc3ac8ec620ac3b105b0c7cc7Gordon Henriksen  if (flags()->replace_str) {
47646abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen    ASAN_READ_RANGE(s, length + 1);
4776d6203dff3560a2cc3ac8ec620ac3b105b0c7cc7Gordon Henriksen  }
47846abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  GET_STACK_TRACE_MALLOC;
47946abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  void *new_mem = asan_malloc(length + 1, &stack);
4806d6203dff3560a2cc3ac8ec620ac3b105b0c7cc7Gordon Henriksen  REAL(memcpy)(new_mem, s, length + 1);
4816d6203dff3560a2cc3ac8ec620ac3b105b0c7cc7Gordon Henriksen  return reinterpret_cast<char*>(new_mem);
4826d6203dff3560a2cc3ac8ec620ac3b105b0c7cc7Gordon Henriksen}
4836d6203dff3560a2cc3ac8ec620ac3b105b0c7cc7Gordon Henriksen#endif
4846d6203dff3560a2cc3ac8ec620ac3b105b0c7cc7Gordon Henriksen
48546abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon HenriksenINTERCEPTOR(uptr, strlen, const char *s) {
48646abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  if (!asan_inited) return internal_strlen(s);
48746abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  // strlen is called from malloc_default_purgeable_zone()
48846abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  // in __asan::ReplaceSystemAlloc() on Mac.
48946abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  if (asan_init_is_running) {
49046abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen    return REAL(strlen)(s);
49146abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  }
49246abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  ENSURE_ASAN_INITED();
49346abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  uptr length = REAL(strlen)(s);
49446abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  if (flags()->replace_str) {
49546abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen    ASAN_READ_RANGE(s, length + 1);
49646abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  }
49746abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  return length;
4982618a6c1122d5d2007787fb56156be44b21ab32aGordon Henriksen}
49946abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen
50046abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon HenriksenINTERCEPTOR(uptr, wcslen, const wchar_t *s) {
50146abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  uptr length = REAL(wcslen)(s);
50246abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  if (!asan_init_is_running) {
50346abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen    ENSURE_ASAN_INITED();
50446abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen    ASAN_READ_RANGE(s, (length + 1) * sizeof(wchar_t));
50546abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  }
50646abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  return length;
50746abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen}
50846abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen
50946abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon HenriksenINTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) {
51046abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  ENSURE_ASAN_INITED();
51146abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  if (flags()->replace_str) {
5122618a6c1122d5d2007787fb56156be44b21ab32aGordon Henriksen    uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1);
51346abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen    CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size);
51446abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen    ASAN_READ_RANGE(from, from_size);
51546abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen    ASAN_WRITE_RANGE(to, size);
51646abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  }
51746abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  return REAL(strncpy)(to, from, size);
5181475142b93a618da72ec471e5ad7c1510c2feb37Gordon Henriksen}
5191475142b93a618da72ec471e5ad7c1510c2feb37Gordon Henriksen
5201475142b93a618da72ec471e5ad7c1510c2feb37Gordon Henriksen#if ASAN_INTERCEPT_STRNLEN
52180a75bfae980df96f969f1c05b0c4a80ce975240Gordon HenriksenINTERCEPTOR(uptr, strnlen, const char *s, uptr maxlen) {
52280a75bfae980df96f969f1c05b0c4a80ce975240Gordon Henriksen  ENSURE_ASAN_INITED();
52380a75bfae980df96f969f1c05b0c4a80ce975240Gordon Henriksen  uptr length = REAL(strnlen)(s, maxlen);
52480a75bfae980df96f969f1c05b0c4a80ce975240Gordon Henriksen  if (flags()->replace_str) {
52580a75bfae980df96f969f1c05b0c4a80ce975240Gordon Henriksen    ASAN_READ_RANGE(s, Min(length + 1, maxlen));
52680a75bfae980df96f969f1c05b0c4a80ce975240Gordon Henriksen  }
52780a75bfae980df96f969f1c05b0c4a80ce975240Gordon Henriksen  return length;
52880a75bfae980df96f969f1c05b0c4a80ce975240Gordon Henriksen}
52980a75bfae980df96f969f1c05b0c4a80ce975240Gordon Henriksen#endif  // ASAN_INTERCEPT_STRNLEN
53080a75bfae980df96f969f1c05b0c4a80ce975240Gordon Henriksen
53180a75bfae980df96f969f1c05b0c4a80ce975240Gordon Henriksenstatic inline bool IsValidStrtolBase(int base) {
53280a75bfae980df96f969f1c05b0c4a80ce975240Gordon Henriksen  return (base == 0) || (2 <= base && base <= 36);
53380a75bfae980df96f969f1c05b0c4a80ce975240Gordon Henriksen}
53480a75bfae980df96f969f1c05b0c4a80ce975240Gordon Henriksen
53546abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksenstatic inline void FixRealStrtolEndptr(const char *nptr, char **endptr) {
53646abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  CHECK(endptr);
53746abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  if (nptr == *endptr) {
53846abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen    // No digits were found at strtol call, we need to find out the last
53946abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen    // symbol accessed by strtoll on our own.
540957f9fe1cce0957bcde4a1093da83e17aaec6764Gordon Henriksen    // We get this symbol by skipping leading blanks and optional +/- sign.
54146abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen    while (IsSpace(*nptr)) nptr++;
54246abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen    if (*nptr == '+' || *nptr == '-') nptr++;
54346abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen    *endptr = (char*)nptr;
54446abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  }
54546abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  CHECK(*endptr >= nptr);
54646abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen}
54746abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen
5482618a6c1122d5d2007787fb56156be44b21ab32aGordon HenriksenINTERCEPTOR(long, strtol, const char *nptr,  // NOLINT
54946abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen            char **endptr, int base) {
55046abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  ENSURE_ASAN_INITED();
55146abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  if (!flags()->replace_str) {
55246abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen    return REAL(strtol)(nptr, endptr, base);
55346abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  }
55446abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  char *real_endptr;
55546abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  long result = REAL(strtol)(nptr, &real_endptr, base);  // NOLINT
55646abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  if (endptr != 0) {
55746abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen    *endptr = real_endptr;
55846abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  }
5592618a6c1122d5d2007787fb56156be44b21ab32aGordon Henriksen  if (IsValidStrtolBase(base)) {
5602618a6c1122d5d2007787fb56156be44b21ab32aGordon Henriksen    FixRealStrtolEndptr(nptr, &real_endptr);
56146abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen    ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
5622618a6c1122d5d2007787fb56156be44b21ab32aGordon Henriksen  }
5632618a6c1122d5d2007787fb56156be44b21ab32aGordon Henriksen  return result;
56446abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen}
56546abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen
56646abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon HenriksenINTERCEPTOR(int, atoi, const char *nptr) {
56746abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#if SANITIZER_MAC
56846abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  if (!asan_inited) return REAL(atoi)(nptr);
56946abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#endif
5702618a6c1122d5d2007787fb56156be44b21ab32aGordon Henriksen  ENSURE_ASAN_INITED();
57146abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  if (!flags()->replace_str) {
57246abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen    return REAL(atoi)(nptr);
57346abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  }
57446abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  char *real_endptr;
57546abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  // "man atoi" tells that behavior of atoi(nptr) is the same as
57646abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
57746abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  // parsed integer can't be stored in *long* type (even if it's
5782618a6c1122d5d2007787fb56156be44b21ab32aGordon Henriksen  // different from int). So, we just imitate this behavior.
57946abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  int result = REAL(strtol)(nptr, &real_endptr, 10);
58046abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  FixRealStrtolEndptr(nptr, &real_endptr);
581e3b989d4a4ba47f77d5d38c35ff17e9673d9f87bGordon Henriksen  ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
58246abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  return result;
58346abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen}
58446abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen
58546abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon HenriksenINTERCEPTOR(long, atol, const char *nptr) {  // NOLINT
58646abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#if SANITIZER_MAC
58746abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  if (!asan_inited) return REAL(atol)(nptr);
58846abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#endif
58946abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  ENSURE_ASAN_INITED();
59046abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  if (!flags()->replace_str) {
59146abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen    return REAL(atol)(nptr);
59246abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  }
593957f9fe1cce0957bcde4a1093da83e17aaec6764Gordon Henriksen  char *real_endptr;
59446abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  long result = REAL(strtol)(nptr, &real_endptr, 10);  // NOLINT
59546abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  FixRealStrtolEndptr(nptr, &real_endptr);
59646abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
59746abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  return result;
59846abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen}
59946abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen
600957f9fe1cce0957bcde4a1093da83e17aaec6764Gordon Henriksen#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
60146abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon HenriksenINTERCEPTOR(long long, strtoll, const char *nptr,  // NOLINT
60246abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen            char **endptr, int base) {
60346abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  ENSURE_ASAN_INITED();
60446abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  if (!flags()->replace_str) {
60546abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen    return REAL(strtoll)(nptr, endptr, base);
60646abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  }
60746abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  char *real_endptr;
60846abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  long long result = REAL(strtoll)(nptr, &real_endptr, base);  // NOLINT
60946abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  if (endptr != 0) {
61046abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen    *endptr = real_endptr;
61146abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  }
61246abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  // If base has unsupported value, strtoll can exit with EINVAL
61346abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  // without reading any characters. So do additional checks only
61446abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  // if base is valid.
61546abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  if (IsValidStrtolBase(base)) {
61646abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen    FixRealStrtolEndptr(nptr, &real_endptr);
61746abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen    ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
61846abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  }
61946abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  return result;
62046abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen}
62146abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen
62246abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon HenriksenINTERCEPTOR(long long, atoll, const char *nptr) {  // NOLINT
62346abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  ENSURE_ASAN_INITED();
62446abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  if (!flags()->replace_str) {
62546abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen    return REAL(atoll)(nptr);
62646abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  }
62746abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  char *real_endptr;
62846abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  long long result = REAL(strtoll)(nptr, &real_endptr, 10);  // NOLINT
62946abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  FixRealStrtolEndptr(nptr, &real_endptr);
63046abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
63146abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  return result;
63246abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen}
63346abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#endif  // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
63446abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen
63546abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksenstatic void AtCxaAtexit(void *unused) {
63646abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  (void)unused;
63746abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  StopInitOrderChecking();
63846abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen}
63946abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen
64046abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#if ASAN_INTERCEPT___CXA_ATEXIT
64146abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon HenriksenINTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
64246abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen            void *dso_handle) {
64346abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  ENSURE_ASAN_INITED();
64446abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  int res = REAL(__cxa_atexit)(func, arg, dso_handle);
64546abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  REAL(__cxa_atexit)(AtCxaAtexit, 0, 0);
64646abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  return res;
64746abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen}
64846abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#endif  // ASAN_INTERCEPT___CXA_ATEXIT
64946abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen
65046abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#if !SANITIZER_MAC
65146abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#define ASAN_INTERCEPT_FUNC(name) do { \
65246abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen      if (!INTERCEPT_FUNCTION(name) && common_flags()->verbosity > 0) \
65346abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen        Report("AddressSanitizer: failed to intercept '" #name "'\n"); \
65446abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen    } while (0)
65546abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#else
65646abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen// OS X interceptors don't need to be initialized with INTERCEPT_FUNCTION.
65746abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#define ASAN_INTERCEPT_FUNC(name)
65846abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#endif  // SANITIZER_MAC
65946abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen
66046abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#if SANITIZER_WINDOWS
66146abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon HenriksenINTERCEPTOR_WINAPI(DWORD, CreateThread,
66246abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen                   void* security, uptr stack_size,
66346abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen                   DWORD (__stdcall *start_routine)(void*), void* arg,
66446abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen                   DWORD thr_flags, void* tid) {
66546abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  // Strict init-order checking in thread-hostile.
66646abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  if (flags()->strict_init_order)
66746abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen    StopInitOrderChecking();
66846abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  GET_STACK_TRACE_THREAD;
66946abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  u32 current_tid = GetCurrentTidOrInvalid();
67046abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  AsanThread *t = AsanThread::Create(start_routine, arg);
67146abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  CreateThreadContextArgs args = { t, &stack };
67246abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  bool detached = false;  // FIXME: how can we determine it on Windows?
67346abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  asanThreadRegistry().CreateThread(*(uptr*)t, detached, current_tid, &args);
67446abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  return REAL(CreateThread)(security, stack_size,
67546abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen                            asan_thread_start, t, thr_flags, tid);
67646abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen}
67746abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen
67846abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksennamespace __asan {
67946abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksenvoid InitializeWindowsInterceptors() {
68046abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  ASAN_INTERCEPT_FUNC(CreateThread);
68146abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen}
68246abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen
68346abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen}  // namespace __asan
68446abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#endif
68546abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen
68646abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen// ---------------------- InitializeAsanInterceptors ---------------- {{{1
68746abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksennamespace __asan {
68846abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksenvoid InitializeAsanInterceptors() {
68946abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  static bool was_called_once;
69046abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  CHECK(was_called_once == false);
69146abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  was_called_once = true;
69246abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  SANITIZER_COMMON_INTERCEPTORS_INIT;
69346abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen
69446abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  // Intercept mem* functions.
69546abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  ASAN_INTERCEPT_FUNC(memcmp);
69646abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  ASAN_INTERCEPT_FUNC(memmove);
69746abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  ASAN_INTERCEPT_FUNC(memset);
69846abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) {
69946abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen    ASAN_INTERCEPT_FUNC(memcpy);
7002618a6c1122d5d2007787fb56156be44b21ab32aGordon Henriksen  }
7012618a6c1122d5d2007787fb56156be44b21ab32aGordon Henriksen
70246abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  // Intercept str* functions.
70346abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  ASAN_INTERCEPT_FUNC(strcat);  // NOLINT
70446abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  ASAN_INTERCEPT_FUNC(strchr);
70546abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  ASAN_INTERCEPT_FUNC(strcpy);  // NOLINT
70646abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  ASAN_INTERCEPT_FUNC(strlen);
70746abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  ASAN_INTERCEPT_FUNC(wcslen);
70846abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  ASAN_INTERCEPT_FUNC(strncat);
70946abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  ASAN_INTERCEPT_FUNC(strncpy);
71046abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#if ASAN_INTERCEPT_STRDUP
71146abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  ASAN_INTERCEPT_FUNC(strdup);
71246abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#endif
71346abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#if ASAN_INTERCEPT_STRNLEN
71446abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  ASAN_INTERCEPT_FUNC(strnlen);
71546abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#endif
71646abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
71746abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  ASAN_INTERCEPT_FUNC(index);
71846abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#endif
71946abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen
72046abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  ASAN_INTERCEPT_FUNC(atoi);
72146abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  ASAN_INTERCEPT_FUNC(atol);
72246abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  ASAN_INTERCEPT_FUNC(strtol);
72346abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
7242618a6c1122d5d2007787fb56156be44b21ab32aGordon Henriksen  ASAN_INTERCEPT_FUNC(atoll);
7252618a6c1122d5d2007787fb56156be44b21ab32aGordon Henriksen  ASAN_INTERCEPT_FUNC(strtoll);
72646abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#endif
72746abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen
72846abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#if ASAN_INTERCEPT_MLOCKX
729957f9fe1cce0957bcde4a1093da83e17aaec6764Gordon Henriksen  // Intercept mlock/munlock.
73046abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  ASAN_INTERCEPT_FUNC(mlock);
73146abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  ASAN_INTERCEPT_FUNC(munlock);
73246abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  ASAN_INTERCEPT_FUNC(mlockall);
73346abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  ASAN_INTERCEPT_FUNC(munlockall);
73446abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#endif
73546abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen
73646abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  // Intecept signal- and jump-related functions.
73746abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  ASAN_INTERCEPT_FUNC(longjmp);
73846abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
73946abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  ASAN_INTERCEPT_FUNC(sigaction);
74046abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  ASAN_INTERCEPT_FUNC(signal);
74146abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#endif
74246abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#if ASAN_INTERCEPT_SWAPCONTEXT
74346abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  ASAN_INTERCEPT_FUNC(swapcontext);
74446abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#endif
74546abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#if ASAN_INTERCEPT__LONGJMP
74646abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  ASAN_INTERCEPT_FUNC(_longjmp);
74746abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#endif
74846abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#if ASAN_INTERCEPT_SIGLONGJMP
74946abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  ASAN_INTERCEPT_FUNC(siglongjmp);
75046abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#endif
75146abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen
75246abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  // Intercept exception handling functions.
75346abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#if ASAN_INTERCEPT___CXA_THROW
75446abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  INTERCEPT_FUNCTION(__cxa_throw);
75546abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#endif
75646abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen
75746abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  // Intercept threading-related functions
75846abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#if ASAN_INTERCEPT_PTHREAD_CREATE
75946abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  ASAN_INTERCEPT_FUNC(pthread_create);
76046abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#endif
76146abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen
76246abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  // Intercept atexit function.
76346abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#if ASAN_INTERCEPT___CXA_ATEXIT
764404a1942e43ca967700cc2608eb97b863add2677Gordon Henriksen  ASAN_INTERCEPT_FUNC(__cxa_atexit);
765404a1942e43ca967700cc2608eb97b863add2677Gordon Henriksen#endif
766404a1942e43ca967700cc2608eb97b863add2677Gordon Henriksen
767404a1942e43ca967700cc2608eb97b863add2677Gordon Henriksen  // Some Windows-specific interceptors.
76846abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#if SANITIZER_WINDOWS
76946abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  InitializeWindowsInterceptors();
77046abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen#endif
77146abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen
77246abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  if (common_flags()->verbosity > 0) {
77346abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen    Report("AddressSanitizer: libc interceptors initialized\n");
77446abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen  }
77546abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen}
7762618a6c1122d5d2007787fb56156be44b21ab32aGordon Henriksen
77746abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen}  // namespace __asan
77846abf91f7378fb7bb118d66fe6d69b5d3af1e9d5Gordon Henriksen