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"
171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_internal.h"
181e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_mapping.h"
197e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov#include "asan_poisoning.h"
20487fee7f6f7497906a00d7d2fe2c75e6d5d4feb1Alexey Samsonov#include "asan_report.h"
211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_stack.h"
221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_stats.h"
2386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "asan_suppressions.h"
24c0d78c1de1f2607c874020d27b72cf989c5ce092Alexey Samsonov#include "sanitizer_common/sanitizer_libc.h"
25c0d78c1de1f2607c874020d27b72cf989c5ce092Alexey Samsonov
26909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar#if SANITIZER_POSIX
27909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar#include "sanitizer_common/sanitizer_posix.h"
28909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar#endif
29909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar
301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan {
311e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
32a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany// Return true if we can quickly decide that the region is unpoisoned.
33a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryanystatic inline bool QuickCheckForUnpoisonedRegion(uptr beg, uptr size) {
34a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany  if (size == 0) return true;
35a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany  if (size <= 32)
36a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany    return !AddressIsPoisoned(beg) &&
37a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany           !AddressIsPoisoned(beg + size - 1) &&
38a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany           !AddressIsPoisoned(beg + size / 2);
39a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany  return false;
40a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany}
41a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany
4286277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstruct AsanInterceptorContext {
4386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  const char *interceptor_name;
4486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines};
4586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
461e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE,
471e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// and ASAN_WRITE_RANGE as macro instead of function so
481e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// that no extra frames are created, and stack trace contains
491e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// relevant information only.
50eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany// We check all shadow bytes.
5186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#define ACCESS_MEMORY_RANGE(ctx, offset, size, isWrite) do {            \
52589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov    uptr __offset = (uptr)(offset);                                     \
53589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov    uptr __size = (uptr)(size);                                         \
541b057b20db71ec6cc2bac460c8b2848f0889d47dKostya Serebryany    uptr __bad = 0;                                                     \
552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    if (__offset > __offset + __size) {                                 \
562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      GET_STACK_TRACE_FATAL_HERE;                                       \
572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      ReportStringFunctionSizeOverflow(__offset, __size, &stack);       \
582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    }                                                                   \
59a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany    if (!QuickCheckForUnpoisonedRegion(__offset, __size) &&             \
601b057b20db71ec6cc2bac460c8b2848f0889d47dKostya Serebryany        (__bad = __asan_region_is_poisoned(__offset, __size))) {        \
6186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      AsanInterceptorContext *_ctx = (AsanInterceptorContext *)ctx;     \
6286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      bool suppressed = false;                                          \
6386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      if (_ctx) {                                                       \
6486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines        suppressed = IsInterceptorSuppressed(_ctx->interceptor_name);   \
6586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines        if (!suppressed && HaveStackTraceBasedSuppressions()) {         \
6686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines          GET_STACK_TRACE_FATAL_HERE;                                   \
6786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines          suppressed = IsStackTraceSuppressed(&stack);                  \
6886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines        }                                                               \
6986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      }                                                                 \
7086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      if (!suppressed) {                                                \
7186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines        GET_CURRENT_PC_BP_SP;                                           \
727c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar        __asan_report_error(pc, bp, sp, __bad, isWrite, __size, 0);     \
7386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      }                                                                 \
74589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov    }                                                                   \
75589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov  } while (0)
761e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
7786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#define ASAN_READ_RANGE(ctx, offset, size) \
7886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ACCESS_MEMORY_RANGE(ctx, offset, size, false)
7986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#define ASAN_WRITE_RANGE(ctx, offset, size) \
8086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ACCESS_MEMORY_RANGE(ctx, offset, size, true)
811e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
82909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar#define ASAN_READ_STRING_OF_LEN(ctx, s, len, n)                 \
83909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  ASAN_READ_RANGE((ctx), (s),                                   \
84909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar    common_flags()->strict_string_checks ? (len) + 1 : (n))
85909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar
86909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar#define ASAN_READ_STRING(ctx, s, n)                             \
87909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  ASAN_READ_STRING_OF_LEN((ctx), (s), REAL(strlen)(s), (n))
88909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar
891e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Behavior of functions like "memcpy" or "strcpy" is undefined
901e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// if memory intervals overlap. We report error in this case.
911e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Macro is used to avoid creation of new frames.
923f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryanystatic inline bool RangesOverlap(const char *offset1, uptr length1,
933f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany                                 const char *offset2, uptr length2) {
940985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany  return !((offset1 + length1 <= offset2) || (offset2 + length2 <= offset1));
951e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
96c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany#define CHECK_RANGES_OVERLAP(name, _offset1, length1, _offset2, length2) do { \
971e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  const char *offset1 = (const char*)_offset1; \
981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  const char *offset2 = (const char*)_offset2; \
990985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany  if (RangesOverlap(offset1, length1, offset2, length2)) { \
100a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany    GET_STACK_TRACE_FATAL_HERE; \
101487fee7f6f7497906a00d7d2fe2c75e6d5d4feb1Alexey Samsonov    ReportStringFunctionMemoryRangesOverlap(name, offset1, length1, \
102487fee7f6f7497906a00d7d2fe2c75e6d5d4feb1Alexey Samsonov                                            offset2, length2, &stack); \
1031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  } \
104e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany} while (0)
1051e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
106c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonovstatic inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) {
10781a7a4ab53c94e76c3b131d6f0ed82894640900bAlexey Samsonov#if ASAN_INTERCEPT_STRNLEN
1083f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  if (REAL(strnlen) != 0) {
10909672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(strnlen)(s, maxlen);
1101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
111f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov#endif
112c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov  return internal_strnlen(s, maxlen);
113a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany}
1141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
115c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryanyvoid SetThreadName(const char *name) {
11689c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov  AsanThread *t = GetCurrentThread();
117c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany  if (t)
118def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov    asanThreadRegistry().SetThreadName(t->tid(), name);
119c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany}
120c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany
1218cde99fb9df913aaf7c1715cd134110dd5a15834Dmitry Vyukovint OnExit() {
12214dd980b384ad859099b499e12f320c4791fb674Dmitry Vyukov  // FIXME: ask frontend whether we need to return failure.
12314dd980b384ad859099b499e12f320c4791fb674Dmitry Vyukov  return 0;
12414dd980b384ad859099b499e12f320c4791fb674Dmitry Vyukov}
12514dd980b384ad859099b499e12f320c4791fb674Dmitry Vyukov
1261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}  // namespace __asan
1271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
1281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// ---------------------- Wrappers ---------------- {{{1
1291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyusing namespace __asan;  // NOLINT
1301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
13112eb79dd701d9d40551759330a9257316601373bEvgeniy StepanovDECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr)
13212eb79dd701d9d40551759330a9257316601373bEvgeniy StepanovDECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
13312eb79dd701d9d40551759330a9257316601373bEvgeniy Stepanov
13486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#define ASAN_INTERCEPTOR_ENTER(ctx, func)                                      \
13586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  AsanInterceptorContext _ctx = {#func};                                       \
13686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ctx = (void *)&_ctx;                                                         \
13786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  (void) ctx;                                                                  \
13886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
139a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov#define COMMON_INTERCEPT_FUNCTION(name) ASAN_INTERCEPT_FUNC(name)
14082a9080eaff95d69b270cd863e9df63e3b4e59adEvgeniy Stepanov#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
14186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ASAN_WRITE_RANGE(ctx, ptr, size)
14286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
14386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ASAN_READ_RANGE(ctx, ptr, size)
1442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...)                               \
14586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ASAN_INTERCEPTOR_ENTER(ctx, func);                                           \
1462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  do {                                                                         \
1472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    if (asan_init_is_running)                                                  \
1482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      return REAL(func)(__VA_ARGS__);                                          \
1492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    if (SANITIZER_MAC && UNLIKELY(!asan_inited))                               \
1502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      return REAL(func)(__VA_ARGS__);                                          \
1512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    ENSURE_ASAN_INITED();                                                      \
1529d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov  } while (false)
15386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \
15486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  do {                                            \
15586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  } while (false)
1569d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
1579d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov  do {                                         \
1589d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov  } while (false)
1599d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
1609d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov  do {                                         \
1619d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov  } while (false)
1629d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov#define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
1639d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov  do {                                                      \
16482a9080eaff95d69b270cd863e9df63e3b4e59adEvgeniy Stepanov  } while (false)
165996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name)
166e767e350b1a6461bc29cfea28af75f908d7da56eDmitry Vyukov// Should be asanThreadRegistry().SetThreadNameByUserId(thread, name)
167e767e350b1a6461bc29cfea28af75f908d7da56eDmitry Vyukov// But asan does not remember UserId's for threads (pthread_t);
168e767e350b1a6461bc29cfea28af75f908d7da56eDmitry Vyukov// and remembers all ever existed threads, so the linear search by UserId
169e767e350b1a6461bc29cfea28af75f908d7da56eDmitry Vyukov// can be slow.
1705cf2c460e96e593b1c772f1b02d3a217f4837fdcDmitry Vyukov#define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
171e767e350b1a6461bc29cfea28af75f908d7da56eDmitry Vyukov  do {                                                         \
172e767e350b1a6461bc29cfea28af75f908d7da56eDmitry Vyukov  } while (false)
173e18e3f07802c420eb4b2da407e148084b75cecc9Evgeniy Stepanov#define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
17486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// Strict init-order checking is dlopen-hostile:
17586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// https://code.google.com/p/address-sanitizer/issues/detail?id=178
17686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag)                           \
17786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  if (flags()->strict_init_order) {                                            \
17886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    StopInitOrderChecking();                                                   \
17986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
18014dd980b384ad859099b499e12f320c4791fb674Dmitry Vyukov#define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
18186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) \
18286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CoverageUpdateMapping()
18386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() CoverageUpdateMapping()
1846d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!asan_inited)
1854f32c0beaa83ffbb84db23d2e6205bee57c39ce1Evgeniy Stepanov#include "sanitizer_common/sanitizer_common_interceptors.inc"
1868530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany
18786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// Syscall interceptors don't have contexts, we don't support suppressions
18886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// for them.
18986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#define COMMON_SYSCALL_PRE_READ_RANGE(p, s) ASAN_READ_RANGE(nullptr, p, s)
19086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) ASAN_WRITE_RANGE(nullptr, p, s)
191ae4e6fd0300b13812a02a779619b1a451478cdd1Evgeniy Stepanov#define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
192ae4e6fd0300b13812a02a779619b1a451478cdd1Evgeniy Stepanov  do {                                       \
193dfab31b93e954ee42622a13dd79e9e1092346035Evgeniy Stepanov    (void)(p);                               \
194dfab31b93e954ee42622a13dd79e9e1092346035Evgeniy Stepanov    (void)(s);                               \
195ae4e6fd0300b13812a02a779619b1a451478cdd1Evgeniy Stepanov  } while (false)
196ae4e6fd0300b13812a02a779619b1a451478cdd1Evgeniy Stepanov#define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \
197ae4e6fd0300b13812a02a779619b1a451478cdd1Evgeniy Stepanov  do {                                        \
198dfab31b93e954ee42622a13dd79e9e1092346035Evgeniy Stepanov    (void)(p);                                \
199dfab31b93e954ee42622a13dd79e9e1092346035Evgeniy Stepanov    (void)(s);                                \
200ae4e6fd0300b13812a02a779619b1a451478cdd1Evgeniy Stepanov  } while (false)
201881b677c189e65872fd315a75a0e56f077339189Evgeniy Stepanov#include "sanitizer_common/sanitizer_common_syscalls.inc"
202881b677c189e65872fd315a75a0e56f077339189Evgeniy Stepanov
20386277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstruct ThreadStartParam {
20486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  atomic_uintptr_t t;
20586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  atomic_uintptr_t is_registered;
20686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines};
20786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
208600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanovstatic thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
20986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ThreadStartParam *param = reinterpret_cast<ThreadStartParam *>(arg);
21086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  AsanThread *t = nullptr;
21186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  while ((t = reinterpret_cast<AsanThread *>(
21286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines              atomic_load(&param->t, memory_order_acquire))) == 0)
21386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    internal_sched_yield();
21486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  SetCurrentThread(t);
21586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return t->ThreadStart(GetTid(), &param->is_registered);
2164803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
2174803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
218fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_PTHREAD_CREATE
219b8ef925563f8dde5be837c4b0569082867c5f14cEvgeniy StepanovINTERCEPTOR(int, pthread_create, void *thread,
220b8ef925563f8dde5be837c4b0569082867c5f14cEvgeniy Stepanov    void *attr, void *(*start_routine)(void*), void *arg) {
221c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev  EnsureMainThreadIDIsCorrect();
22286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // Strict init-order checking is thread-hostile.
2239465cbdbe73590746b57916f46ea1aa4bf3dd13dAlexey Samsonov  if (flags()->strict_init_order)
2249465cbdbe73590746b57916f46ea1aa4bf3dd13dAlexey Samsonov    StopInitOrderChecking();
225a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  GET_STACK_TRACE_THREAD;
226def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  int detached = 0;
227def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  if (attr != 0)
228bb6bc9a0ae534ada3c0c2c226462c351c078d761Evgeniy Stepanov    REAL(pthread_attr_getdetachstate)(attr, &detached);
22986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ThreadStartParam param;
23086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  atomic_store(&param.t, 0, memory_order_relaxed);
23186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  atomic_store(&param.is_registered, 0, memory_order_relaxed);
23286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  int result = REAL(pthread_create)(thread, attr, asan_thread_start, &param);
23386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  if (result == 0) {
23486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    u32 current_tid = GetCurrentTidOrInvalid();
23586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    AsanThread *t =
23686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines        AsanThread::Create(start_routine, arg, current_tid, &stack, detached);
23786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    atomic_store(&param.t, reinterpret_cast<uptr>(t), memory_order_release);
23886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    // Wait until the AsanThread object is initialized and the ThreadRegistry
23986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    // entry is in "started" state. One reason for this is that after this
24086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    // interceptor exits, the child thread's stack may be the only thing holding
24186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    // the |arg| pointer. This may cause LSan to report a leak if leak checking
24286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    // happens at a point when the interceptor has already exited, but the stack
24386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    // range for the child thread is not yet known.
24486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    while (atomic_load(&param.is_registered, memory_order_acquire) == 0)
24586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      internal_sched_yield();
24686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
24786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return result;
24886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
249def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov
25086277eb844c4983c81de62d7c050e92fe7155788Stephen HinesINTERCEPTOR(int, pthread_join, void *t, void **arg) {
25186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return real_pthread_join(t, arg);
2524803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
25386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
25486277eb844c4983c81de62d7c050e92fe7155788Stephen HinesDEFINE_REAL_PTHREAD_FUNCTIONS
255fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif  // ASAN_INTERCEPT_PTHREAD_CREATE
2564803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
25734a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
2582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
2592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_ANDROID
2602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERCEPTOR(void*, bsd_signal, int signum, void *handler) {
26186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  if (!IsDeadlySignal(signum) || common_flags()->allow_user_segv_handler) {
2622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    return REAL(bsd_signal)(signum, handler);
2632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
2642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return 0;
2652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
2662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
267f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void*, signal, int signum, void *handler) {
26886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  if (!IsDeadlySignal(signum) || common_flags()->allow_user_segv_handler) {
269034bda5eab7cda14fac0bed3a39de4a3dbce3cffAlexander Potapenko    return REAL(signal)(signum, handler);
2704803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  }
2713f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  return 0;
2724803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
2732d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
2744803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
275da13ba833b046553f50b54538e4828287ddbf5c0Alexey SamsonovINTERCEPTOR(int, sigaction, int signum, const struct sigaction *act,
276da13ba833b046553f50b54538e4828287ddbf5c0Alexey Samsonov                            struct sigaction *oldact) {
27786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  if (!IsDeadlySignal(signum) || common_flags()->allow_user_segv_handler) {
278034bda5eab7cda14fac0bed3a39de4a3dbce3cffAlexander Potapenko    return REAL(sigaction)(signum, act, oldact);
2794803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  }
280034bda5eab7cda14fac0bed3a39de4a3dbce3cffAlexander Potapenko  return 0;
2814803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
2822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
2832d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesnamespace __sanitizer {
2842d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesint real_sigaction(int signum, const void *act, void *oldact) {
2856d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  return REAL(sigaction)(signum, (const struct sigaction *)act,
2866d1862363c88c183b0ed7740fca876342cf0474bStephen Hines                         (struct sigaction *)oldact);
2872d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
2882d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}  // namespace __sanitizer
2892d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
290e1ba0009d5be18d513ffd29c1b6fccea1a3bffa0Evgeniy Stepanov#elif SANITIZER_POSIX
29134a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov// We need to have defined REAL(sigaction) on posix systems.
29234a3202a2c22816a6da66959e266a2d078ded37bAlexey SamsonovDEFINE_REAL(int, sigaction, int signum, const struct sigaction *act,
293fdde5a97a71b142297d7b2270c2a7f564a37dbaeAlexey Samsonov    struct sigaction *oldact)
29434a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov#endif  // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
2954803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
2960870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov#if ASAN_INTERCEPT_SWAPCONTEXT
29757db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonovstatic void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) {
29857db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  // Align to page size.
29957db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  uptr PageSize = GetPageSizeCached();
30057db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  uptr bottom = stack & ~(PageSize - 1);
30157db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  ssize += stack - bottom;
30257db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  ssize = RoundUpTo(ssize, PageSize);
30357db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  static const uptr kMaxSaneContextStackSize = 1 << 22;  // 4 Mb
304909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  if (AddrIsInMem(bottom) && ssize && ssize <= kMaxSaneContextStackSize) {
30557db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov    PoisonShadow(bottom, ssize, 0);
30657db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  }
30757db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov}
30857db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov
3090870028410087e67a0049c76cb7c64f02c260d24Alexey SamsonovINTERCEPTOR(int, swapcontext, struct ucontext_t *oucp,
3100870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov            struct ucontext_t *ucp) {
3110870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  static bool reported_warning = false;
3120870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  if (!reported_warning) {
3130870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov    Report("WARNING: ASan doesn't fully support makecontext/swapcontext "
3140870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov           "functions and may produce false positives in some cases!\n");
3150870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov    reported_warning = true;
3160870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  }
3170870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  // Clear shadow memory for new context (it may share stack
3180870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  // with current context).
31957db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  uptr stack, ssize;
32057db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  ReadContextStack(ucp, &stack, &ssize);
32157db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  ClearShadowMemoryForContextStack(stack, ssize);
3220870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  int res = REAL(swapcontext)(oucp, ucp);
3230870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  // swapcontext technically does not return, but program may swap context to
3240870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  // "oucp" later, that would look as if swapcontext() returned 0.
3250870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  // We need to clear shadow for ucp once again, as it may be in arbitrary
3260870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  // state.
32757db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov  ClearShadowMemoryForContextStack(stack, ssize);
3280870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  return res;
3290870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov}
33057db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov#endif  // ASAN_INTERCEPT_SWAPCONTEXT
3310870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov
332f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, longjmp, void *env, int val) {
333f54b1f9b73a6855d77ee270c282bd61407fa73a0Kostya Serebryany  __asan_handle_no_return();
33409672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  REAL(longjmp)(env, val);
3354803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
3364803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
337fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT__LONGJMP
338f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, _longjmp, void *env, int val) {
339f54b1f9b73a6855d77ee270c282bd61407fa73a0Kostya Serebryany  __asan_handle_no_return();
34009672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  REAL(_longjmp)(env, val);
3414803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
342fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif
3434803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
344fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_SIGLONGJMP
345f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, siglongjmp, void *env, int val) {
346f54b1f9b73a6855d77ee270c282bd61407fa73a0Kostya Serebryany  __asan_handle_no_return();
34709672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  REAL(siglongjmp)(env, val);
3484803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
34907bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov#endif
3504803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
351fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT___CXA_THROW
352f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
35309672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  CHECK(REAL(__cxa_throw));
354f54b1f9b73a6855d77ee270c282bd61407fa73a0Kostya Serebryany  __asan_handle_no_return();
35509672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  REAL(__cxa_throw)(a, b, c);
3564803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
3574803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany#endif
3584803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
35952fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryanystatic inline int CharCmp(unsigned char c1, unsigned char c2) {
36052fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
36152fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany}
36252fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany
3633f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {
36486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void *ctx;
36586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ASAN_INTERCEPTOR_ENTER(ctx, memcmp);
3662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (UNLIKELY(!asan_inited)) return internal_memcmp(a1, a2, size);
36752fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  ENSURE_ASAN_INITED();
3681b057b20db71ec6cc2bac460c8b2848f0889d47dKostya Serebryany  if (flags()->replace_intrin) {
3698bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko    if (flags()->strict_memcmp) {
3708bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko      // Check the entire regions even if the first bytes of the buffers are
3718bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko      // different.
37286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      ASAN_READ_RANGE(ctx, a1, size);
37386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      ASAN_READ_RANGE(ctx, a2, size);
3748bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko      // Fallthrough to REAL(memcmp) below.
3758bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko    } else {
3768bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko      unsigned char c1 = 0, c2 = 0;
3778bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko      const unsigned char *s1 = (const unsigned char*)a1;
3788bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko      const unsigned char *s2 = (const unsigned char*)a2;
3798bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko      uptr i;
3808bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko      for (i = 0; i < size; i++) {
3818bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko        c1 = s1[i];
3828bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko        c2 = s2[i];
3838bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko        if (c1 != c2) break;
3848bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko      }
38586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      ASAN_READ_RANGE(ctx, s1, Min(i + 1, size));
38686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      ASAN_READ_RANGE(ctx, s2, Min(i + 1, size));
3878bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko      return CharCmp(c1, c2);
3888bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko    }
38952fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  }
3901b057b20db71ec6cc2bac460c8b2848f0889d47dKostya Serebryany  return REAL(memcmp(a1, a2, size));
39152fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany}
39252fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany
39386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// memcpy is called during __asan_init() from the internals of printf(...).
39486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// We do not treat memcpy with to==from as a bug.
39586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// See http://llvm.org/bugs/show_bug.cgi?id=11763.
39686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#define ASAN_MEMCPY_IMPL(ctx, to, from, size) do {                             \
39786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (UNLIKELY(!asan_inited)) return internal_memcpy(to, from, size);        \
39886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (asan_init_is_running) {                                                \
39986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      return REAL(memcpy)(to, from, size);                                     \
40086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    }                                                                          \
40186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    ENSURE_ASAN_INITED();                                                      \
40286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (flags()->replace_intrin) {                                             \
40386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      if (to != from) {                                                        \
40486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines        CHECK_RANGES_OVERLAP("memcpy", to, size, from, size);                  \
40586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      }                                                                        \
40686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      ASAN_READ_RANGE(ctx, from, size);                                        \
40786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      ASAN_WRITE_RANGE(ctx, to, size);                                         \
40886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    }                                                                          \
40986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return REAL(memcpy)(to, from, size);                                       \
41086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  } while (0)
41186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
41286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
4132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid *__asan_memcpy(void *to, const void *from, uptr size) {
41486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ASAN_MEMCPY_IMPL(nullptr, to, from, size);
4151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
4161e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
41786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// memset is called inside Printf.
41886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#define ASAN_MEMSET_IMPL(ctx, block, c, size) do {                             \
41986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (UNLIKELY(!asan_inited)) return internal_memset(block, c, size);        \
42086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (asan_init_is_running) {                                                \
42186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      return REAL(memset)(block, c, size);                                     \
42286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    }                                                                          \
42386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    ENSURE_ASAN_INITED();                                                      \
42486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (flags()->replace_intrin) {                                             \
42586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      ASAN_WRITE_RANGE(ctx, block, size);                                      \
42686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    }                                                                          \
42786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return REAL(memset)(block, c, size);                                       \
42886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  } while (0)
42986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
4302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid *__asan_memset(void *block, int c, uptr size) {
43186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ASAN_MEMSET_IMPL(nullptr, block, c, size);
4321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
4331e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
43486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#define ASAN_MEMMOVE_IMPL(ctx, to, from, size) do {                            \
43586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (UNLIKELY(!asan_inited))                                                \
43686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      return internal_memmove(to, from, size);                                 \
43786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    ENSURE_ASAN_INITED();                                                      \
43886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (flags()->replace_intrin) {                                             \
43986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      ASAN_READ_RANGE(ctx, from, size);                                        \
44086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      ASAN_WRITE_RANGE(ctx, to, size);                                         \
44186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    }                                                                          \
44286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return internal_memmove(to, from, size);                                   \
44386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  } while (0)
44486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
4452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid *__asan_memmove(void *to, const void *from, uptr size) {
44686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ASAN_MEMMOVE_IMPL(nullptr, to, from, size);
4472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
4482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
4492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) {
45086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void *ctx;
45186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ASAN_INTERCEPTOR_ENTER(ctx, memmove);
45286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ASAN_MEMMOVE_IMPL(ctx, to, from, size);
4532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
4542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
4552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) {
45686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void *ctx;
45786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ASAN_INTERCEPTOR_ENTER(ctx, memcpy);
4582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if !SANITIZER_MAC
45986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ASAN_MEMCPY_IMPL(ctx, to, from, size);
4602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
4612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // At least on 10.7 and 10.8 both memcpy() and memmove() are being replaced
4622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // with WRAP(memcpy). As a result, false positives are reported for memmove()
4632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // calls. If we just disable error reporting with
4642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // ASAN_OPTIONS=replace_intrin=0, memmove() is still replaced with
4652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // internal_memcpy(), which may lead to crashes, see
4662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // http://llvm.org/bugs/show_bug.cgi?id=16362.
46786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ASAN_MEMMOVE_IMPL(ctx, to, from, size);
4682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif  // !SANITIZER_MAC
4692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
4702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
4712d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERCEPTOR(void*, memset, void *block, int c, uptr size) {
47286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void *ctx;
47386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ASAN_INTERCEPTOR_ENTER(ctx, memset);
47486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ASAN_MEMSET_IMPL(ctx, block, c, size);
4752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
4762d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
477f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strchr, const char *str, int c) {
47886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void *ctx;
47986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ASAN_INTERCEPTOR_ENTER(ctx, strchr);
4802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (UNLIKELY(!asan_inited)) return internal_strchr(str, c);
4818d6e3f7d011970e35dadf831964260bcf6a4d8a9Alexander Potapenko  // strchr is called inside create_purgeable_zone() when MallocGuardEdges=1 is
4828d6e3f7d011970e35dadf831964260bcf6a4d8a9Alexander Potapenko  // used.
4838d6e3f7d011970e35dadf831964260bcf6a4d8a9Alexander Potapenko  if (asan_init_is_running) {
4848d6e3f7d011970e35dadf831964260bcf6a4d8a9Alexander Potapenko    return REAL(strchr)(str, c);
4858d6e3f7d011970e35dadf831964260bcf6a4d8a9Alexander Potapenko  }
486e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
48709672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  char *result = REAL(strchr)(str, c);
488cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_str) {
489909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar    uptr len = REAL(strlen)(str);
490909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar    uptr bytes_read = (result ? result - str : len) + 1;
491909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar    ASAN_READ_STRING_OF_LEN(ctx, str, len, bytes_read);
4921e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
4931e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return result;
4941e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
4951e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
496fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_INDEX
497fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov# if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
4984b0c5f240e71be4f375627e57d0f1b89600918a7Evgeniy StepanovINTERCEPTOR(char*, index, const char *string, int c)
49972bbfd4f3a442afde281476bc6bd41b3b2152a4eAlexander Potapenko  ALIAS(WRAPPER_NAME(strchr));
500fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov# else
50124e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#  if SANITIZER_MAC
50250a002ecad3f0a10c136496e5b6289bd3c71590eAlexander PotapenkoDECLARE_REAL(char*, index, const char *string, int c)
50350a002ecad3f0a10c136496e5b6289bd3c71590eAlexander PotapenkoOVERRIDE_FUNCTION(index, strchr);
50450a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko#  else
505fdde5a97a71b142297d7b2270c2a7f564a37dbaeAlexey SamsonovDEFINE_REAL(char*, index, const char *string, int c)
50650a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko#  endif
507fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov# endif
508fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif  // ASAN_INTERCEPT_INDEX
509af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany
51037b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko// For both strcat() and strncat() we need to check the validity of |to|
51137b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko// argument irrespective of the |from| length.
512f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strcat, char *to, const char *from) {  // NOLINT
51386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void *ctx;
51486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ASAN_INTERCEPTOR_ENTER(ctx, strcat);  // NOLINT
5150985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany  ENSURE_ASAN_INITED();
516cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_str) {
5173f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany    uptr from_length = REAL(strlen)(from);
51886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    ASAN_READ_RANGE(ctx, from, from_length + 1);
51937b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko    uptr to_length = REAL(strlen)(to);
520909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar    ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
52186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
52237b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko    // If the copying actually happens, the |from| string should not overlap
52337b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko    // with the resulting string starting at |to|, which has a length of
52437b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko    // to_length + from_length + 1.
5250985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany    if (from_length > 0) {
52637b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko      CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1,
52737b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko                           from, from_length + 1);
5280985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany    }
5290985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany  }
53009672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(strcat)(to, from);  // NOLINT
5310985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany}
5320985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany
533c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey SamsonovINTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
53486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void *ctx;
53586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ASAN_INTERCEPTOR_ENTER(ctx, strncat);
536c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov  ENSURE_ASAN_INITED();
53737b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko  if (flags()->replace_str) {
538c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov    uptr from_length = MaybeRealStrnlen(from, size);
53937b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko    uptr copy_length = Min(size, from_length + 1);
54086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    ASAN_READ_RANGE(ctx, from, copy_length);
541c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov    uptr to_length = REAL(strlen)(to);
542909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar    ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
54386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
544c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov    if (from_length > 0) {
54537b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko      CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1,
54637b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko                           from, copy_length);
547c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov    }
548c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov  }
549c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov  return REAL(strncat)(to, from, size);
550c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov}
551c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov
552f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strcpy, char *to, const char *from) {  // NOLINT
55386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void *ctx;
55486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ASAN_INTERCEPTOR_ENTER(ctx, strcpy);  // NOLINT
55524e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#if SANITIZER_MAC
5562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (UNLIKELY(!asan_inited)) return REAL(strcpy)(to, from);  // NOLINT
5570ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko#endif
5581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // strcpy is called from malloc_default_purgeable_zone()
5591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // in __asan::ReplaceSystemAlloc() on Mac.
5601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (asan_init_is_running) {
56109672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(strcpy)(to, from);  // NOLINT
5621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
563e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
564cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_str) {
5653f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany    uptr from_size = REAL(strlen)(from) + 1;
566c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany    CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size);
56786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    ASAN_READ_RANGE(ctx, from, from_size);
56886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    ASAN_WRITE_RANGE(ctx, to, from_size);
5691e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
57009672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(strcpy)(to, from);  // NOLINT
5711e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
5721e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
573fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_STRDUP
574f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strdup, const char *s) {
57586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void *ctx;
57686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ASAN_INTERCEPTOR_ENTER(ctx, strdup);
5772d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (UNLIKELY(!asan_inited)) return internal_strdup(s);
578e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
579d530d892b4958a9ae54e57472d5d0a0bae1f6ad8Alexey Samsonov  uptr length = REAL(strlen)(s);
580cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_str) {
58186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    ASAN_READ_RANGE(ctx, s, length + 1);
5821e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
583d530d892b4958a9ae54e57472d5d0a0bae1f6ad8Alexey Samsonov  GET_STACK_TRACE_MALLOC;
584d530d892b4958a9ae54e57472d5d0a0bae1f6ad8Alexey Samsonov  void *new_mem = asan_malloc(length + 1, &stack);
585d530d892b4958a9ae54e57472d5d0a0bae1f6ad8Alexey Samsonov  REAL(memcpy)(new_mem, s, length + 1);
586d530d892b4958a9ae54e57472d5d0a0bae1f6ad8Alexey Samsonov  return reinterpret_cast<char*>(new_mem);
5871e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
588fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif
5891e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
5906d1862363c88c183b0ed7740fca876342cf0474bStephen HinesINTERCEPTOR(SIZE_T, strlen, const char *s) {
59186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void *ctx;
59286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ASAN_INTERCEPTOR_ENTER(ctx, strlen);
5932d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (UNLIKELY(!asan_inited)) return internal_strlen(s);
5941e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // strlen is called from malloc_default_purgeable_zone()
5951e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // in __asan::ReplaceSystemAlloc() on Mac.
5961e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (asan_init_is_running) {
59709672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(strlen)(s);
5981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
599e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
6006d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  SIZE_T length = REAL(strlen)(s);
601cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_str) {
60286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    ASAN_READ_RANGE(ctx, s, length + 1);
6031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
6041e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return length;
6051e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
6061e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
6076d1862363c88c183b0ed7740fca876342cf0474bStephen HinesINTERCEPTOR(SIZE_T, wcslen, const wchar_t *s) {
60886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void *ctx;
60986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ASAN_INTERCEPTOR_ENTER(ctx, wcslen);
6106d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  SIZE_T length = REAL(wcslen)(s);
611b99228de65b408b0acd9618b92774fb8add7e482Reid Kleckner  if (!asan_init_is_running) {
612b99228de65b408b0acd9618b92774fb8add7e482Reid Kleckner    ENSURE_ASAN_INITED();
61386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    ASAN_READ_RANGE(ctx, s, (length + 1) * sizeof(wchar_t));
614b99228de65b408b0acd9618b92774fb8add7e482Reid Kleckner  }
615b99228de65b408b0acd9618b92774fb8add7e482Reid Kleckner  return length;
616b99228de65b408b0acd9618b92774fb8add7e482Reid Kleckner}
617b99228de65b408b0acd9618b92774fb8add7e482Reid Kleckner
6183f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) {
61986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void *ctx;
62086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ASAN_INTERCEPTOR_ENTER(ctx, strncpy);
621e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
622cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_str) {
623c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov    uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1);
624c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany    CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size);
62586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    ASAN_READ_RANGE(ctx, from, from_size);
62686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    ASAN_WRITE_RANGE(ctx, to, size);
6271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
62809672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(strncpy)(to, from, size);
6291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
6301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
63181a7a4ab53c94e76c3b131d6f0ed82894640900bAlexey Samsonov#if ASAN_INTERCEPT_STRNLEN
6323f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(uptr, strnlen, const char *s, uptr maxlen) {
63386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void *ctx;
63486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ASAN_INTERCEPTOR_ENTER(ctx, strnlen);
635e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
6363f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  uptr length = REAL(strnlen)(s, maxlen);
637cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_str) {
63886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    ASAN_READ_RANGE(ctx, s, Min(length + 1, maxlen));
6391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
6401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return length;
6411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
64281a7a4ab53c94e76c3b131d6f0ed82894640900bAlexey Samsonov#endif  // ASAN_INTERCEPT_STRNLEN
643547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany
644847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR(long, strtol, const char *nptr,  // NOLINT
64584ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov            char **endptr, int base) {
64686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void *ctx;
64786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ASAN_INTERCEPTOR_ENTER(ctx, strtol);
64884ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov  ENSURE_ASAN_INITED();
649cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (!flags()->replace_str) {
650847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov    return REAL(strtol)(nptr, endptr, base);
65184ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov  }
65284ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov  char *real_endptr;
653847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  long result = REAL(strtol)(nptr, &real_endptr, base);  // NOLINT
654909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
65584ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov  return result;
65684ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov}
65784ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov
658847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR(int, atoi, const char *nptr) {
65986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void *ctx;
66086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ASAN_INTERCEPTOR_ENTER(ctx, atoi);
66124e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#if SANITIZER_MAC
6622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (UNLIKELY(!asan_inited)) return REAL(atoi)(nptr);
6630ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko#endif
664847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  ENSURE_ASAN_INITED();
665cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (!flags()->replace_str) {
666847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov    return REAL(atoi)(nptr);
667847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  }
668847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  char *real_endptr;
669847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  // "man atoi" tells that behavior of atoi(nptr) is the same as
6703f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
671847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  // parsed integer can't be stored in *long* type (even if it's
672847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  // different from int). So, we just imitate this behavior.
673847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  int result = REAL(strtol)(nptr, &real_endptr, 10);
674847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  FixRealStrtolEndptr(nptr, &real_endptr);
675909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
676847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  return result;
677847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov}
678847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov
679847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR(long, atol, const char *nptr) {  // NOLINT
68086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void *ctx;
68186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ASAN_INTERCEPTOR_ENTER(ctx, atol);
68224e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#if SANITIZER_MAC
6832d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (UNLIKELY(!asan_inited)) return REAL(atol)(nptr);
6840ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko#endif
685847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  ENSURE_ASAN_INITED();
686cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (!flags()->replace_str) {
687847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov    return REAL(atol)(nptr);
688847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  }
689847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  char *real_endptr;
690847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  long result = REAL(strtol)(nptr, &real_endptr, 10);  // NOLINT
691847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  FixRealStrtolEndptr(nptr, &real_endptr);
692909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
693847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  return result;
694847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov}
695847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov
696847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
697847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR(long long, strtoll, const char *nptr,  // NOLINT
6988f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov            char **endptr, int base) {
69986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void *ctx;
70086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ASAN_INTERCEPTOR_ENTER(ctx, strtoll);
7018f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  ENSURE_ASAN_INITED();
702cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (!flags()->replace_str) {
703847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov    return REAL(strtoll)(nptr, endptr, base);
7048f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  }
7058f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  char *real_endptr;
706847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  long long result = REAL(strtoll)(nptr, &real_endptr, base);  // NOLINT
707909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
7088f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  return result;
7098f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov}
7108f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov
711847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR(long long, atoll, const char *nptr) {  // NOLINT
71286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void *ctx;
71386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ASAN_INTERCEPTOR_ENTER(ctx, atoll);
714847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  ENSURE_ASAN_INITED();
715cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (!flags()->replace_str) {
716847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov    return REAL(atoll)(nptr);
717847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  }
718847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  char *real_endptr;
719847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  long long result = REAL(strtoll)(nptr, &real_endptr, 10);  // NOLINT
720847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  FixRealStrtolEndptr(nptr, &real_endptr);
721909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
722847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  return result;
723847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov}
724847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov#endif  // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
725847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov
72646efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonovstatic void AtCxaAtexit(void *unused) {
72746efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov  (void)unused;
72846efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov  StopInitOrderChecking();
72946efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov}
73046efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov
73146efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov#if ASAN_INTERCEPT___CXA_ATEXIT
73246efcb09dc16b91cb805abea52f3ff6081a63751Alexey SamsonovINTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
73346efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov            void *dso_handle) {
734b527f7de80001569542e3f0ef4c7f4b0cb15cb67Alexander Potapenko#if SANITIZER_MAC
7352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (UNLIKELY(!asan_inited)) return REAL(__cxa_atexit)(func, arg, dso_handle);
736b527f7de80001569542e3f0ef4c7f4b0cb15cb67Alexander Potapenko#endif
73746efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov  ENSURE_ASAN_INITED();
73846efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov  int res = REAL(__cxa_atexit)(func, arg, dso_handle);
73946efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov  REAL(__cxa_atexit)(AtCxaAtexit, 0, 0);
74046efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov  return res;
74146efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov}
74246efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov#endif  // ASAN_INTERCEPT___CXA_ATEXIT
74346efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov
7446a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#if ASAN_INTERCEPT_FORK
7456a211c5814e25d6745a5058cc0e499e5235d3821Stephen HinesINTERCEPTOR(int, fork, void) {
7466a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  ENSURE_ASAN_INITED();
7476a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  if (common_flags()->coverage) CovBeforeFork();
7486a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  int pid = REAL(fork)();
7496a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  if (common_flags()->coverage) CovAfterFork(pid);
7506a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  return pid;
7516a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines}
7526a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#endif  // ASAN_INTERCEPT_FORK
7536a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines
754547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany// ---------------------- InitializeAsanInterceptors ---------------- {{{1
755547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryanynamespace __asan {
756547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryanyvoid InitializeAsanInterceptors() {
757fdbdab5ff8de4c23b58bb411ea2358a78e2d9b2fKostya Serebryany  static bool was_called_once;
758fdbdab5ff8de4c23b58bb411ea2358a78e2d9b2fKostya Serebryany  CHECK(was_called_once == false);
759fdbdab5ff8de4c23b58bb411ea2358a78e2d9b2fKostya Serebryany  was_called_once = true;
7602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  InitializeCommonInterceptors();
7618530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany
76207bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  // Intercept mem* functions.
763580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(memcmp);
764580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(memmove);
765580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(memset);
76638dd4ed885e714c376466f6fe0d69f5f22d37014Alexey Samsonov  if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) {
767580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov    ASAN_INTERCEPT_FUNC(memcpy);
768573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko  }
76907bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov
77007bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  // Intercept str* functions.
771580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strcat);  // NOLINT
772580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strchr);
773580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strcpy);  // NOLINT
774580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strlen);
775b99228de65b408b0acd9618b92774fb8add7e482Reid Kleckner  ASAN_INTERCEPT_FUNC(wcslen);
776c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov  ASAN_INTERCEPT_FUNC(strncat);
777580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strncpy);
778fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_STRDUP
779fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  ASAN_INTERCEPT_FUNC(strdup);
780fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif
781fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_STRNLEN
782fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  ASAN_INTERCEPT_FUNC(strnlen);
783fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif
78469563986ca570ce750111a82264d51ddbf4107baAlexander Potapenko#if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
785580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(index);
78607bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov#endif
7875b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov
788580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(atoi);
789580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(atol);
790580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strtol);
791847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
792580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(atoll);
793580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strtoll);
79484ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov#endif
79584ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov
79607bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  // Intecept signal- and jump-related functions.
797580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(longjmp);
79834a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
799580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(sigaction);
8002d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_ANDROID
8012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  ASAN_INTERCEPT_FUNC(bsd_signal);
8022d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
803580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(signal);
804919c24787a655597bdcf367e26c9dd1504e9f463Evgeniy Stepanov#endif
8052d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
8060870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov#if ASAN_INTERCEPT_SWAPCONTEXT
8070870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov  ASAN_INTERCEPT_FUNC(swapcontext);
8080870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov#endif
809fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT__LONGJMP
810580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(_longjmp);
811fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif
812fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_SIGLONGJMP
813580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(siglongjmp);
814fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif
815fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov
816fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  // Intercept exception handling functions.
817fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT___CXA_THROW
8186d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  ASAN_INTERCEPT_FUNC(__cxa_throw);
8193e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov#endif
8203e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov
82107bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  // Intercept threading-related functions
822fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_PTHREAD_CREATE
823580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(pthread_create);
82486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ASAN_INTERCEPT_FUNC(pthread_join);
82507bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov#endif
82607bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov
82746efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov  // Intercept atexit function.
82846efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov#if ASAN_INTERCEPT___CXA_ATEXIT
82946efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov  ASAN_INTERCEPT_FUNC(__cxa_atexit);
83046efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov#endif
83146efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov
8326a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#if ASAN_INTERCEPT_FORK
8336a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  ASAN_INTERCEPT_FUNC(fork);
8346a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#endif
8356a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines
8367c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  InitializePlatformInterceptors();
837600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov
8382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  VReport(1, "AddressSanitizer: libc interceptors initialized\n");
839547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany}
840547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany
841547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany}  // namespace __asan
842