asan_interceptors.cc revision a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808
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"
20487fee7f6f7497906a00d7d2fe2c75e6d5d4feb1Alexey Samsonov#include "asan_report.h"
211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_stack.h"
221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_stats.h"
234803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany#include "asan_thread_registry.h"
245b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov#include "interception/interception.h"
25c0d78c1de1f2607c874020d27b72cf989c5ce092Alexey Samsonov#include "sanitizer_common/sanitizer_libc.h"
26c0d78c1de1f2607c874020d27b72cf989c5ce092Alexey Samsonov
271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan {
281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
29a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany// Return true if we can quickly decide that the region is unpoisoned.
30a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryanystatic inline bool QuickCheckForUnpoisonedRegion(uptr beg, uptr size) {
31a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany  if (size == 0) return true;
32a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany  if (size <= 32)
33a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany    return !AddressIsPoisoned(beg) &&
34a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany           !AddressIsPoisoned(beg + size - 1) &&
35a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany           !AddressIsPoisoned(beg + size / 2);
36a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany  return false;
37a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany}
38a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany
391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE,
401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// and ASAN_WRITE_RANGE as macro instead of function so
411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// that no extra frames are created, and stack trace contains
421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// relevant information only.
43eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany// We check all shadow bytes.
44589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov#define ACCESS_MEMORY_RANGE(offset, size, isWrite) do {                 \
45589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov    uptr __offset = (uptr)(offset);                                     \
46589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov    uptr __size = (uptr)(size);                                         \
47a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany    if (!QuickCheckForUnpoisonedRegion(__offset, __size) &&             \
48a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany        __asan_region_is_poisoned(__offset, __size)) {                  \
49589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov      GET_CURRENT_PC_BP_SP;                                             \
50589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov      __asan_report_error(pc, bp, sp, __offset, isWrite, __size);       \
51589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov    }                                                                   \
52589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov  } while (0)
531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
54eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany#define ASAN_READ_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size, false)
55eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany#define ASAN_WRITE_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size, true);
561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Behavior of functions like "memcpy" or "strcpy" is undefined
581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// if memory intervals overlap. We report error in this case.
591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Macro is used to avoid creation of new frames.
603f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryanystatic inline bool RangesOverlap(const char *offset1, uptr length1,
613f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany                                 const char *offset2, uptr length2) {
620985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany  return !((offset1 + length1 <= offset2) || (offset2 + length2 <= offset1));
631e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
64c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany#define CHECK_RANGES_OVERLAP(name, _offset1, length1, _offset2, length2) do { \
651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  const char *offset1 = (const char*)_offset1; \
661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  const char *offset2 = (const char*)_offset2; \
670985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany  if (RangesOverlap(offset1, length1, offset2, length2)) { \
68a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany    GET_STACK_TRACE_FATAL_HERE; \
69487fee7f6f7497906a00d7d2fe2c75e6d5d4feb1Alexey Samsonov    ReportStringFunctionMemoryRangesOverlap(name, offset1, length1, \
70487fee7f6f7497906a00d7d2fe2c75e6d5d4feb1Alexey Samsonov                                            offset2, length2, &stack); \
711e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  } \
72e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany} while (0)
731e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
74e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany#define ENSURE_ASAN_INITED() do { \
75e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  CHECK(!asan_init_is_running); \
76e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  if (!asan_inited) { \
77e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany    __asan_init(); \
78e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  } \
79e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany} while (0)
801e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
81c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonovstatic inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) {
8281a7a4ab53c94e76c3b131d6f0ed82894640900bAlexey Samsonov#if ASAN_INTERCEPT_STRNLEN
833f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  if (REAL(strnlen) != 0) {
8409672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(strnlen)(s, maxlen);
851e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
86f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov#endif
87c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov  return internal_strnlen(s, maxlen);
88a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany}
891e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
90c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryanyvoid SetThreadName(const char *name) {
91c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany  AsanThread *t = asanThreadRegistry().GetCurrent();
92c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany  if (t)
93c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany    t->summary()->set_name(name);
94c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany}
95c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany
961e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}  // namespace __asan
971e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// ---------------------- Wrappers ---------------- {{{1
991e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyusing namespace __asan;  // NOLINT
1001e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
10182a9080eaff95d69b270cd863e9df63e3b4e59adEvgeniy Stepanov#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
10282a9080eaff95d69b270cd863e9df63e3b4e59adEvgeniy Stepanov  ASAN_WRITE_RANGE(ptr, size)
103996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) ASAN_READ_RANGE(ptr, size)
104bee7415a86d9437659d09f034c346794bf15c2abEvgeniy Stepanov#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
10582a9080eaff95d69b270cd863e9df63e3b4e59adEvgeniy Stepanov  do {                                           \
10682a9080eaff95d69b270cd863e9df63e3b4e59adEvgeniy Stepanov    ctx = 0;                                     \
10782a9080eaff95d69b270cd863e9df63e3b4e59adEvgeniy Stepanov    (void)ctx;                                   \
10882a9080eaff95d69b270cd863e9df63e3b4e59adEvgeniy Stepanov    ENSURE_ASAN_INITED();                        \
10982a9080eaff95d69b270cd863e9df63e3b4e59adEvgeniy Stepanov  } while (false)
110996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) do { } while (false)
111996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) do { } while (false)
112996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name)
1134f32c0beaa83ffbb84db23d2e6205bee57c39ce1Evgeniy Stepanov#include "sanitizer_common/sanitizer_common_interceptors.inc"
1148530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany
115600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanovstatic thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
1164803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  AsanThread *t = (AsanThread*)arg;
1174803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  asanThreadRegistry().SetCurrent(t);
1184803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  return t->ThreadStart();
1194803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
1204803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
121fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_PTHREAD_CREATE
122b8ef925563f8dde5be837c4b0569082867c5f14cEvgeniy StepanovINTERCEPTOR(int, pthread_create, void *thread,
123b8ef925563f8dde5be837c4b0569082867c5f14cEvgeniy Stepanov    void *attr, void *(*start_routine)(void*), void *arg) {
124a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  GET_STACK_TRACE_THREAD;
125e0cff0bc20ae51790c8edfbceb817e18ebf5355eKostya Serebryany  u32 current_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
12655cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov  AsanThread *t = AsanThread::Create(current_tid, start_routine, arg, &stack);
12755cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov  asanThreadRegistry().RegisterThread(t);
12809672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(pthread_create)(thread, attr, asan_thread_start, t);
1294803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
130fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif  // ASAN_INTERCEPT_PTHREAD_CREATE
1314803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
13234a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
133f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void*, signal, int signum, void *handler) {
134034bda5eab7cda14fac0bed3a39de4a3dbce3cffAlexander Potapenko  if (!AsanInterceptsSignal(signum)) {
135034bda5eab7cda14fac0bed3a39de4a3dbce3cffAlexander Potapenko    return REAL(signal)(signum, handler);
1364803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  }
1373f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  return 0;
1384803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
1394803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
140da13ba833b046553f50b54538e4828287ddbf5c0Alexey SamsonovINTERCEPTOR(int, sigaction, int signum, const struct sigaction *act,
141da13ba833b046553f50b54538e4828287ddbf5c0Alexey Samsonov                            struct sigaction *oldact) {
142034bda5eab7cda14fac0bed3a39de4a3dbce3cffAlexander Potapenko  if (!AsanInterceptsSignal(signum)) {
143034bda5eab7cda14fac0bed3a39de4a3dbce3cffAlexander Potapenko    return REAL(sigaction)(signum, act, oldact);
1444803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  }
145034bda5eab7cda14fac0bed3a39de4a3dbce3cffAlexander Potapenko  return 0;
1464803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
14734a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov#elif ASAN_POSIX
14834a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov// We need to have defined REAL(sigaction) on posix systems.
14934a3202a2c22816a6da66959e266a2d078ded37bAlexey SamsonovDEFINE_REAL(int, sigaction, int signum, const struct sigaction *act,
15034a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov    struct sigaction *oldact);
15134a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov#endif  // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
1524803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
1530870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov#if ASAN_INTERCEPT_SWAPCONTEXT
15457db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonovstatic void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) {
15557db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  // Align to page size.
15657db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  uptr PageSize = GetPageSizeCached();
15757db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  uptr bottom = stack & ~(PageSize - 1);
15857db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  ssize += stack - bottom;
15957db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  ssize = RoundUpTo(ssize, PageSize);
16057db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  static const uptr kMaxSaneContextStackSize = 1 << 22;  // 4 Mb
161541cfb10f5daa17e48eb42365a74233cd551c545Kostya Serebryany  if (ssize && ssize <= kMaxSaneContextStackSize) {
16257db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov    PoisonShadow(bottom, ssize, 0);
16357db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  }
16457db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov}
16557db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov
1660870028410087e67a0049c76cb7c64f02c260d24Alexey SamsonovINTERCEPTOR(int, swapcontext, struct ucontext_t *oucp,
1670870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov            struct ucontext_t *ucp) {
1680870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  static bool reported_warning = false;
1690870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  if (!reported_warning) {
1700870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov    Report("WARNING: ASan doesn't fully support makecontext/swapcontext "
1710870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov           "functions and may produce false positives in some cases!\n");
1720870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov    reported_warning = true;
1730870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  }
1740870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  // Clear shadow memory for new context (it may share stack
1750870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  // with current context).
17657db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  uptr stack, ssize;
17757db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  ReadContextStack(ucp, &stack, &ssize);
17857db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  ClearShadowMemoryForContextStack(stack, ssize);
1790870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  int res = REAL(swapcontext)(oucp, ucp);
1800870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  // swapcontext technically does not return, but program may swap context to
1810870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  // "oucp" later, that would look as if swapcontext() returned 0.
1820870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  // We need to clear shadow for ucp once again, as it may be in arbitrary
1830870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  // state.
18457db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  ClearShadowMemoryForContextStack(stack, ssize);
1850870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  return res;
1860870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov}
18757db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov#endif  // ASAN_INTERCEPT_SWAPCONTEXT
1880870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov
189f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, longjmp, void *env, int val) {
190f54b1f9b73a6855d77ee270c282bd61407fa73a0Kostya Serebryany  __asan_handle_no_return();
19109672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  REAL(longjmp)(env, val);
1924803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
1934803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
194fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT__LONGJMP
195f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, _longjmp, void *env, int val) {
196f54b1f9b73a6855d77ee270c282bd61407fa73a0Kostya Serebryany  __asan_handle_no_return();
19709672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  REAL(_longjmp)(env, val);
1984803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
199fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif
2004803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
201fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_SIGLONGJMP
202f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, siglongjmp, void *env, int val) {
203f54b1f9b73a6855d77ee270c282bd61407fa73a0Kostya Serebryany  __asan_handle_no_return();
20409672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  REAL(siglongjmp)(env, val);
2054803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
20607bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov#endif
2074803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
208fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT___CXA_THROW
209f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
21009672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  CHECK(REAL(__cxa_throw));
211f54b1f9b73a6855d77ee270c282bd61407fa73a0Kostya Serebryany  __asan_handle_no_return();
21209672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  REAL(__cxa_throw)(a, b, c);
2134803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
2144803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany#endif
2154803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
2164803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany// intercept mlock and friends.
2174803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany// Since asan maps 16T of RAM, mlock is completely unfriendly to asan.
2184803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany// All functions return 0 (success).
2194803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanystatic void MlockIsUnsupported() {
2204803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  static bool printed = 0;
2214803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  if (printed) return;
2224803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  printed = true;
2234803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  Printf("INFO: AddressSanitizer ignores mlock/mlockall/munlock/munlockall\n");
2244803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
2253389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov
226f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonovextern "C" {
22700f1c091441be5c2cacb99e21bd1965a5e418242Alexander PotapenkoINTERCEPTOR(int, mlock, const void *addr, uptr len) {
2284803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  MlockIsUnsupported();
2294803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  return 0;
2304803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
2313389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov
23200f1c091441be5c2cacb99e21bd1965a5e418242Alexander PotapenkoINTERCEPTOR(int, munlock, const void *addr, uptr len) {
2334803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  MlockIsUnsupported();
2344803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  return 0;
2354803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
2363389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov
23700f1c091441be5c2cacb99e21bd1965a5e418242Alexander PotapenkoINTERCEPTOR(int, mlockall, int flags) {
2384803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  MlockIsUnsupported();
2394803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  return 0;
2404803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
2413389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov
24200f1c091441be5c2cacb99e21bd1965a5e418242Alexander PotapenkoINTERCEPTOR(int, munlockall, void) {
2434803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  MlockIsUnsupported();
2444803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  return 0;
2454803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
2464803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}  // extern "C"
2474803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
24852fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryanystatic inline int CharCmp(unsigned char c1, unsigned char c2) {
24952fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
25052fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany}
25152fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany
25252fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryanystatic inline int CharCaseCmp(unsigned char c1, unsigned char c2) {
2538898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov  int c1_low = ToLower(c1);
2548898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov  int c2_low = ToLower(c2);
25552fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  return c1_low - c2_low;
25652fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany}
25752fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany
2583f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {
25950f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko  if (!asan_inited) return internal_memcmp(a1, a2, size);
26052fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  ENSURE_ASAN_INITED();
26152fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  unsigned char c1 = 0, c2 = 0;
26252fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  const unsigned char *s1 = (const unsigned char*)a1;
26352fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  const unsigned char *s2 = (const unsigned char*)a2;
2643f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  uptr i;
26552fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  for (i = 0; i < size; i++) {
26652fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany    c1 = s1[i];
26752fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany    c2 = s2[i];
26852fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany    if (c1 != c2) break;
26952fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  }
27052fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  ASAN_READ_RANGE(s1, Min(i + 1, size));
27152fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  ASAN_READ_RANGE(s2, Min(i + 1, size));
27252fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  return CharCmp(c1, c2);
27352fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany}
27452fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany
2753f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) {
27650f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko  if (!asan_inited) return internal_memcpy(to, from, size);
2771e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // memcpy is called during __asan_init() from the internals
2781e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // of printf(...).
2791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (asan_init_is_running) {
28009672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(memcpy)(to, from, size);
2811e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
282e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
283cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_intrin) {
284c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany    if (to != from) {
285c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany      // We do not treat memcpy with to==from as a bug.
286c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany      // See http://llvm.org/bugs/show_bug.cgi?id=11763.
287c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany      CHECK_RANGES_OVERLAP("memcpy", to, size, from, size);
288c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany    }
289c75d8483e27528349620ccf4e997a72029a7ea17Alexander Potapenko    ASAN_READ_RANGE(from, size);
290c75d8483e27528349620ccf4e997a72029a7ea17Alexander Potapenko    ASAN_WRITE_RANGE(to, size);
2911e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
292f1673e61768cb08d488a75584b61bfdf24ffdac1Alexander Potapenko  // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8.
293f1673e61768cb08d488a75584b61bfdf24ffdac1Alexander Potapenko  // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116.
294f1673e61768cb08d488a75584b61bfdf24ffdac1Alexander Potapenko  return internal_memcpy(to, from, size);
2951e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
2961e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
2973f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) {
2983e8458ab54c7cbaec45e367b2da909c6f94b291cAlexander Potapenko  if (!asan_inited) return internal_memmove(to, from, size);
299a1a25c1afe38e59ffb342c24bb5bb10d05679df7Alexey Samsonov  if (asan_init_is_running) {
300a1a25c1afe38e59ffb342c24bb5bb10d05679df7Alexey Samsonov    return REAL(memmove)(to, from, size);
301a1a25c1afe38e59ffb342c24bb5bb10d05679df7Alexey Samsonov  }
302e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
303cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_intrin) {
304c75d8483e27528349620ccf4e997a72029a7ea17Alexander Potapenko    ASAN_READ_RANGE(from, size);
305c75d8483e27528349620ccf4e997a72029a7ea17Alexander Potapenko    ASAN_WRITE_RANGE(to, size);
3061e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
307f1673e61768cb08d488a75584b61bfdf24ffdac1Alexander Potapenko  // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8.
308f1673e61768cb08d488a75584b61bfdf24ffdac1Alexander Potapenko  // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116.
309f1673e61768cb08d488a75584b61bfdf24ffdac1Alexander Potapenko  return internal_memmove(to, from, size);
3101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
3111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
3123f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(void*, memset, void *block, int c, uptr size) {
31350f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko  if (!asan_inited) return internal_memset(block, c, size);
314ebb9702cff96192c6a6ea963037929ca7ed60eaeAlexander Potapenko  // memset is called inside Printf.
315e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  if (asan_init_is_running) {
31609672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(memset)(block, c, size);
317e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  }
318e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
319cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_intrin) {
3201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_WRITE_RANGE(block, size);
3211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
32209672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(memset)(block, c, size);
3231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
3241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
325f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strchr, const char *str, int c) {
32650f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko  if (!asan_inited) return internal_strchr(str, c);
3278d6e3f7d011970e35dadf831964260bcf6a4d8a9Alexander Potapenko  // strchr is called inside create_purgeable_zone() when MallocGuardEdges=1 is
3288d6e3f7d011970e35dadf831964260bcf6a4d8a9Alexander Potapenko  // used.
3298d6e3f7d011970e35dadf831964260bcf6a4d8a9Alexander Potapenko  if (asan_init_is_running) {
3308d6e3f7d011970e35dadf831964260bcf6a4d8a9Alexander Potapenko    return REAL(strchr)(str, c);
3318d6e3f7d011970e35dadf831964260bcf6a4d8a9Alexander Potapenko  }
332e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
33309672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  char *result = REAL(strchr)(str, c);
334cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_str) {
3353f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany    uptr bytes_read = (result ? result - str : REAL(strlen)(str)) + 1;
3361e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(str, bytes_read);
3371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
3381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return result;
3391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
3401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
341fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_INDEX
342fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov# if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
3434b0c5f240e71be4f375627e57d0f1b89600918a7Evgeniy StepanovINTERCEPTOR(char*, index, const char *string, int c)
344adf2b036127d7e887392d9be5b02069b777ee280Alexey Samsonov  ALIAS(WRAPPER_NAME(strchr));
345fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov# else
346b4fefa713da3dabda1cd83ae4182c71f1683f02cAlexey SamsonovDEFINE_REAL(char*, index, const char *string, int c)
347fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov# endif
348fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif  // ASAN_INTERCEPT_INDEX
349af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany
35037b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko// For both strcat() and strncat() we need to check the validity of |to|
35137b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko// argument irrespective of the |from| length.
352f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strcat, char *to, const char *from) {  // NOLINT
3530985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany  ENSURE_ASAN_INITED();
354cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_str) {
3553f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany    uptr from_length = REAL(strlen)(from);
3560985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany    ASAN_READ_RANGE(from, from_length + 1);
35737b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko    uptr to_length = REAL(strlen)(to);
35837b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko    ASAN_READ_RANGE(to, to_length);
35937b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko    ASAN_WRITE_RANGE(to + to_length, from_length + 1);
36037b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko    // If the copying actually happens, the |from| string should not overlap
36137b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko    // with the resulting string starting at |to|, which has a length of
36237b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko    // to_length + from_length + 1.
3630985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany    if (from_length > 0) {
36437b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko      CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1,
36537b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko                           from, from_length + 1);
3660985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany    }
3670985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany  }
36809672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(strcat)(to, from);  // NOLINT
3690985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany}
3700985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany
371c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey SamsonovINTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
372c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov  ENSURE_ASAN_INITED();
37337b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko  if (flags()->replace_str) {
374c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov    uptr from_length = MaybeRealStrnlen(from, size);
37537b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko    uptr copy_length = Min(size, from_length + 1);
37637b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko    ASAN_READ_RANGE(from, copy_length);
377c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov    uptr to_length = REAL(strlen)(to);
378c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov    ASAN_READ_RANGE(to, to_length);
379c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov    ASAN_WRITE_RANGE(to + to_length, from_length + 1);
380c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov    if (from_length > 0) {
38137b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko      CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1,
38237b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko                           from, copy_length);
383c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov    }
384c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov  }
385c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov  return REAL(strncat)(to, from, size);
386c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov}
387c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov
388f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(int, strcmp, const char *s1, const char *s2) {
38950f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko  if (!asan_inited) return internal_strcmp(s1, s2);
390fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  if (asan_init_is_running) {
391fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov    return REAL(strcmp)(s1, s2);
3921e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
3938648e7734ff02a25706464e9e294bd217622bcaeKostya Serebryany  ENSURE_ASAN_INITED();
3941e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  unsigned char c1, c2;
3953f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  uptr i;
3961e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  for (i = 0; ; i++) {
3971e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    c1 = (unsigned char)s1[i];
3981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    c2 = (unsigned char)s2[i];
3991e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    if (c1 != c2 || c1 == '\0') break;
4001e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
4011e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  ASAN_READ_RANGE(s1, i + 1);
4021e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  ASAN_READ_RANGE(s2, i + 1);
4031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return CharCmp(c1, c2);
4041e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
4051e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
406f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strcpy, char *to, const char *from) {  // NOLINT
40769563986ca570ce750111a82264d51ddbf4107baAlexander Potapenko#if defined(__APPLE__)
408beda44f87166f91dbeef3d174d77395653bead4dAlexander Potapenko  if (!asan_inited) return REAL(strcpy)(to, from);  // NOLINT
4090ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko#endif
4101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // strcpy is called from malloc_default_purgeable_zone()
4111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // in __asan::ReplaceSystemAlloc() on Mac.
4121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (asan_init_is_running) {
41309672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(strcpy)(to, from);  // NOLINT
4141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
415e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
416cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_str) {
4173f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany    uptr from_size = REAL(strlen)(from) + 1;
418c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany    CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size);
4191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(from, from_size);
4201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_WRITE_RANGE(to, from_size);
4211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
42209672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(strcpy)(to, from);  // NOLINT
4231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
4241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
425fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_STRDUP
426f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strdup, const char *s) {
42769563986ca570ce750111a82264d51ddbf4107baAlexander Potapenko#if defined(__APPLE__)
42871578faf4eb8e61aefb3121e1945cc47f07cea0dAlexander Potapenko  // FIXME: because internal_strdup() uses InternalAlloc(), which currently
42971578faf4eb8e61aefb3121e1945cc47f07cea0dAlexander Potapenko  // just calls malloc() on Mac, we can't use internal_strdup() with the
43071578faf4eb8e61aefb3121e1945cc47f07cea0dAlexander Potapenko  // dynamic runtime. We can remove the call to REAL(strdup) once InternalAlloc
43171578faf4eb8e61aefb3121e1945cc47f07cea0dAlexander Potapenko  // starts using mmap() instead.
43271578faf4eb8e61aefb3121e1945cc47f07cea0dAlexander Potapenko  // See also http://code.google.com/p/address-sanitizer/issues/detail?id=123.
43371578faf4eb8e61aefb3121e1945cc47f07cea0dAlexander Potapenko  if (!asan_inited) return REAL(strdup)(s);
43471578faf4eb8e61aefb3121e1945cc47f07cea0dAlexander Potapenko#endif
43550f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko  if (!asan_inited) return internal_strdup(s);
436e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
437cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_str) {
4383f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany    uptr length = REAL(strlen)(s);
4391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(s, length + 1);
4401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
44109672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(strdup)(s);
4421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
443fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif
4441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
4453f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(uptr, strlen, const char *s) {
44650f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko  if (!asan_inited) return internal_strlen(s);
4471e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // strlen is called from malloc_default_purgeable_zone()
4481e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // in __asan::ReplaceSystemAlloc() on Mac.
4491e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (asan_init_is_running) {
45009672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(strlen)(s);
4511e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
452e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
4533f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  uptr length = REAL(strlen)(s);
454cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_str) {
4551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(s, length + 1);
4561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
4571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return length;
4581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
4591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
460fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP
461fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey SamsonovINTERCEPTOR(int, strcasecmp, const char *s1, const char *s2) {
462fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  ENSURE_ASAN_INITED();
463fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  unsigned char c1, c2;
464fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  uptr i;
465fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  for (i = 0; ; i++) {
466fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov    c1 = (unsigned char)s1[i];
467fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov    c2 = (unsigned char)s2[i];
468fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov    if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
469fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  }
470fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  ASAN_READ_RANGE(s1, i + 1);
471fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  ASAN_READ_RANGE(s2, i + 1);
472fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  return CharCaseCmp(c1, c2);
473fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov}
474fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov
4753f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, uptr n) {
476af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany  ENSURE_ASAN_INITED();
477af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany  unsigned char c1 = 0, c2 = 0;
4783f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  uptr i;
479f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov  for (i = 0; i < n; i++) {
480af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany    c1 = (unsigned char)s1[i];
481af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany    c2 = (unsigned char)s2[i];
482af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany    if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
483af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany  }
484f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov  ASAN_READ_RANGE(s1, Min(i + 1, n));
485f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov  ASAN_READ_RANGE(s2, Min(i + 1, n));
486af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany  return CharCaseCmp(c1, c2);
487af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany}
488fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif  // ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP
489af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany
4903f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(int, strncmp, const char *s1, const char *s2, uptr size) {
49150f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko  if (!asan_inited) return internal_strncmp(s1, s2, size);
4921e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // strncmp is called from malloc_default_purgeable_zone()
4931e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // in __asan::ReplaceSystemAlloc() on Mac.
4941e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (asan_init_is_running) {
49509672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(strncmp)(s1, s2, size);
4961e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
4978648e7734ff02a25706464e9e294bd217622bcaeKostya Serebryany  ENSURE_ASAN_INITED();
4981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  unsigned char c1 = 0, c2 = 0;
4993f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  uptr i;
5001e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  for (i = 0; i < size; i++) {
5011e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    c1 = (unsigned char)s1[i];
5021e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    c2 = (unsigned char)s2[i];
5031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    if (c1 != c2 || c1 == '\0') break;
5041e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
5052d8b3bdb112ebb8ed3f15ee41d4cebcd683b41b0Kostya Serebryany  ASAN_READ_RANGE(s1, Min(i + 1, size));
5062d8b3bdb112ebb8ed3f15ee41d4cebcd683b41b0Kostya Serebryany  ASAN_READ_RANGE(s2, Min(i + 1, size));
5071e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return CharCmp(c1, c2);
5081e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
5091e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
5103f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) {
511e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
512cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_str) {
513c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov    uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1);
514c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany    CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size);
5151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(from, from_size);
5161e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_WRITE_RANGE(to, size);
5171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
51809672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(strncpy)(to, from, size);
5191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
5201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
52181a7a4ab53c94e76c3b131d6f0ed82894640900bAlexey Samsonov#if ASAN_INTERCEPT_STRNLEN
5223f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(uptr, strnlen, const char *s, uptr maxlen) {
523e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
5243f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  uptr length = REAL(strnlen)(s, maxlen);
525cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_str) {
5262d8b3bdb112ebb8ed3f15ee41d4cebcd683b41b0Kostya Serebryany    ASAN_READ_RANGE(s, Min(length + 1, maxlen));
5271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
5281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return length;
5291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
53081a7a4ab53c94e76c3b131d6f0ed82894640900bAlexey Samsonov#endif  // ASAN_INTERCEPT_STRNLEN
531547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany
5328f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonovstatic inline bool IsValidStrtolBase(int base) {
5338f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  return (base == 0) || (2 <= base && base <= 36);
5348f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov}
5358f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov
5368f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonovstatic inline void FixRealStrtolEndptr(const char *nptr, char **endptr) {
5373f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  CHECK(endptr != 0);
5388f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  if (nptr == *endptr) {
5398f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    // No digits were found at strtol call, we need to find out the last
5408f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    // symbol accessed by strtoll on our own.
5418f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    // We get this symbol by skipping leading blanks and optional +/- sign.
5428f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    while (IsSpace(*nptr)) nptr++;
5438f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    if (*nptr == '+' || *nptr == '-') nptr++;
5448f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    *endptr = (char*)nptr;
5458f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  }
5468f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  CHECK(*endptr >= nptr);
54784ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov}
54884ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov
549847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR(long, strtol, const char *nptr,  // NOLINT
55084ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov            char **endptr, int base) {
55184ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov  ENSURE_ASAN_INITED();
552cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (!flags()->replace_str) {
553847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov    return REAL(strtol)(nptr, endptr, base);
55484ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov  }
55584ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov  char *real_endptr;
556847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  long result = REAL(strtol)(nptr, &real_endptr, base);  // NOLINT
5573f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  if (endptr != 0) {
55884ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov    *endptr = real_endptr;
55984ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov  }
5608f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  if (IsValidStrtolBase(base)) {
5618f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    FixRealStrtolEndptr(nptr, &real_endptr);
56284ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov    ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
56384ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov  }
56484ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov  return result;
56584ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov}
56684ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov
567847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR(int, atoi, const char *nptr) {
56869563986ca570ce750111a82264d51ddbf4107baAlexander Potapenko#if defined(__APPLE__)
5690ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko  if (!asan_inited) return REAL(atoi)(nptr);
5700ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko#endif
571847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  ENSURE_ASAN_INITED();
572cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (!flags()->replace_str) {
573847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov    return REAL(atoi)(nptr);
574847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  }
575847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  char *real_endptr;
576847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  // "man atoi" tells that behavior of atoi(nptr) is the same as
5773f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
578847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  // parsed integer can't be stored in *long* type (even if it's
579847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  // different from int). So, we just imitate this behavior.
580847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  int result = REAL(strtol)(nptr, &real_endptr, 10);
581847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  FixRealStrtolEndptr(nptr, &real_endptr);
582847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
583847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  return result;
584847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov}
585847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov
586847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR(long, atol, const char *nptr) {  // NOLINT
58769563986ca570ce750111a82264d51ddbf4107baAlexander Potapenko#if defined(__APPLE__)
5880ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko  if (!asan_inited) return REAL(atol)(nptr);
5890ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko#endif
590847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  ENSURE_ASAN_INITED();
591cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (!flags()->replace_str) {
592847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov    return REAL(atol)(nptr);
593847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  }
594847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  char *real_endptr;
595847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  long result = REAL(strtol)(nptr, &real_endptr, 10);  // NOLINT
596847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  FixRealStrtolEndptr(nptr, &real_endptr);
597847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
598847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  return result;
599847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov}
600847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov
601847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
602847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR(long long, strtoll, const char *nptr,  // NOLINT
6038f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov            char **endptr, int base) {
6048f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  ENSURE_ASAN_INITED();
605cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (!flags()->replace_str) {
606847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov    return REAL(strtoll)(nptr, endptr, base);
6078f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  }
6088f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  char *real_endptr;
609847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  long long result = REAL(strtoll)(nptr, &real_endptr, base);  // NOLINT
6103f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  if (endptr != 0) {
6118f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    *endptr = real_endptr;
6128f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  }
613847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  // If base has unsupported value, strtoll can exit with EINVAL
614847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  // without reading any characters. So do additional checks only
615847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  // if base is valid.
6168f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  if (IsValidStrtolBase(base)) {
6178f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    FixRealStrtolEndptr(nptr, &real_endptr);
6188f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
6198f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  }
6208f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  return result;
6218f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov}
6228f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov
623847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR(long long, atoll, const char *nptr) {  // NOLINT
624847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  ENSURE_ASAN_INITED();
625cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (!flags()->replace_str) {
626847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov    return REAL(atoll)(nptr);
627847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  }
628847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  char *real_endptr;
629847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  long long result = REAL(strtoll)(nptr, &real_endptr, 10);  // NOLINT
630847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  FixRealStrtolEndptr(nptr, &real_endptr);
631847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
632847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  return result;
633847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov}
634847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov#endif  // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
635847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov
636580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov#define ASAN_INTERCEPT_FUNC(name) do { \
637cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov      if (!INTERCEPT_FUNCTION(name) && flags()->verbosity > 0) \
638580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov        Report("AddressSanitizer: failed to intercept '" #name "'\n"); \
639580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov    } while (0)
640580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov
641600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov#if defined(_WIN32)
642600972e3427173cc8904d741decd1af0ed5de9fdTimur IskhodzhanovINTERCEPTOR_WINAPI(DWORD, CreateThread,
6433f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany                   void* security, uptr stack_size,
644600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov                   DWORD (__stdcall *start_routine)(void*), void* arg,
645600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov                   DWORD flags, void* tid) {
646a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  GET_STACK_TRACE_THREAD;
647e0cff0bc20ae51790c8edfbceb817e18ebf5355eKostya Serebryany  u32 current_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
648600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  AsanThread *t = AsanThread::Create(current_tid, start_routine, arg, &stack);
649600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  asanThreadRegistry().RegisterThread(t);
650600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  return REAL(CreateThread)(security, stack_size,
651600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov                            asan_thread_start, t, flags, tid);
652600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov}
653600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov
654600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanovnamespace __asan {
655600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanovvoid InitializeWindowsInterceptors() {
656580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(CreateThread);
657600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov}
658600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov
659600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov}  // namespace __asan
660600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov#endif
661600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov
662547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany// ---------------------- InitializeAsanInterceptors ---------------- {{{1
663547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryanynamespace __asan {
664547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryanyvoid InitializeAsanInterceptors() {
665fdbdab5ff8de4c23b58bb411ea2358a78e2d9b2fKostya Serebryany  static bool was_called_once;
666fdbdab5ff8de4c23b58bb411ea2358a78e2d9b2fKostya Serebryany  CHECK(was_called_once == false);
667fdbdab5ff8de4c23b58bb411ea2358a78e2d9b2fKostya Serebryany  was_called_once = true;
66869563986ca570ce750111a82264d51ddbf4107baAlexander Potapenko#if defined(__APPLE__)
6690ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko  return;
67069563986ca570ce750111a82264d51ddbf4107baAlexander Potapenko#else
6718530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany  SANITIZER_COMMON_INTERCEPTORS_INIT;
6728530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany
67307bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  // Intercept mem* functions.
674580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(memcmp);
675580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(memmove);
676580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(memset);
67738dd4ed885e714c376466f6fe0d69f5f22d37014Alexey Samsonov  if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) {
678580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov    ASAN_INTERCEPT_FUNC(memcpy);
679573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko  }
68007bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov
68107bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  // Intercept str* functions.
682580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strcat);  // NOLINT
683580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strchr);
684580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strcmp);
685580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strcpy);  // NOLINT
686580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strlen);
687c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov  ASAN_INTERCEPT_FUNC(strncat);
688580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strncmp);
689580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strncpy);
690fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP
691580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strcasecmp);
692580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strncasecmp);
693fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif
694fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_STRDUP
695fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  ASAN_INTERCEPT_FUNC(strdup);
696fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif
697fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_STRNLEN
698fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  ASAN_INTERCEPT_FUNC(strnlen);
699fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif
70069563986ca570ce750111a82264d51ddbf4107baAlexander Potapenko#if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
701580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(index);
70207bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov#endif
7035b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov
704580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(atoi);
705580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(atol);
706580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strtol);
707847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
708580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(atoll);
709580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strtoll);
71084ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov#endif
71184ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov
712f0c6de3d91ba5cdfbb17a630e823523c7d433160Alexander Potapenko#if ASAN_INTERCEPT_MLOCKX
71300f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko  // Intercept mlock/munlock.
71400f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko  ASAN_INTERCEPT_FUNC(mlock);
71500f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko  ASAN_INTERCEPT_FUNC(munlock);
71600f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko  ASAN_INTERCEPT_FUNC(mlockall);
71700f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko  ASAN_INTERCEPT_FUNC(munlockall);
718f0c6de3d91ba5cdfbb17a630e823523c7d433160Alexander Potapenko#endif
71900f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko
72007bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  // Intecept signal- and jump-related functions.
721580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(longjmp);
72234a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
723580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(sigaction);
724580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(signal);
725919c24787a655597bdcf367e26c9dd1504e9f463Evgeniy Stepanov#endif
7260870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov#if ASAN_INTERCEPT_SWAPCONTEXT
7270870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  ASAN_INTERCEPT_FUNC(swapcontext);
7280870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov#endif
729fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT__LONGJMP
730580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(_longjmp);
731fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif
732fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_SIGLONGJMP
733580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(siglongjmp);
734fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif
735fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov
736fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  // Intercept exception handling functions.
737fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT___CXA_THROW
738fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  INTERCEPT_FUNCTION(__cxa_throw);
7393e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov#endif
7403e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov
74107bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  // Intercept threading-related functions
742fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_PTHREAD_CREATE
743580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(pthread_create);
74407bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov#endif
74507bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov
746600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  // Some Windows-specific interceptors.
747600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov#if defined(_WIN32)
748600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  InitializeWindowsInterceptors();
749600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov#endif
750600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov
751cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->verbosity > 0) {
7522962f26071ebef1d5fec52b5569e5ae7aae45c9bAlexander Potapenko    Report("AddressSanitizer: libc interceptors initialized\n");
753547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  }
7542673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany#endif  // __APPLE__
755547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany}
756547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany
757547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany}  // namespace __asan
758