asan_interceptors.cc revision beda44f87166f91dbeef3d174d77395653bead4d
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_interface.h"
191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_internal.h"
201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_mapping.h"
21487fee7f6f7497906a00d7d2fe2c75e6d5d4feb1Alexey Samsonov#include "asan_report.h"
221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_stack.h"
231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_stats.h"
244803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany#include "asan_thread_registry.h"
255b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov#include "interception/interception.h"
26c0d78c1de1f2607c874020d27b72cf989c5ce092Alexey Samsonov#include "sanitizer_common/sanitizer_libc.h"
27c0d78c1de1f2607c874020d27b72cf989c5ce092Alexey Samsonov
281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan {
291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Instruments read/write access to a single byte in memory.
311e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// On error calls __asan_report_error, which aborts the program.
329f311bb0919d86ab3df2810dc0b81b70a87677e3Kostya Serebryany#define ACCESS_ADDRESS(address, isWrite)   do {         \
3379d12e87fbcc1b2342d76367b99b83adf9cbf499Alexander Potapenko  if (!AddrIsInMem(address) || AddressIsPoisoned(address)) {                \
349f311bb0919d86ab3df2810dc0b81b70a87677e3Kostya Serebryany    GET_CURRENT_PC_BP_SP;                               \
359f311bb0919d86ab3df2810dc0b81b70a87677e3Kostya Serebryany    __asan_report_error(pc, bp, sp, address, isWrite, /* access_size */ 1); \
369f311bb0919d86ab3df2810dc0b81b70a87677e3Kostya Serebryany  } \
379f311bb0919d86ab3df2810dc0b81b70a87677e3Kostya Serebryany} while (0)
381e172b4bdec57329bf904f063a29f99cddf2d85fKostya 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.
431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Instruments read/write access to a memory range.
451e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// More complex implementation is possible, for now just
461e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// checking the first and the last byte of a range.
471e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#define ACCESS_MEMORY_RANGE(offset, size, isWrite) do { \
481e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (size > 0) { \
493f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany    uptr ptr = (uptr)(offset); \
509f311bb0919d86ab3df2810dc0b81b70a87677e3Kostya Serebryany    ACCESS_ADDRESS(ptr, isWrite); \
519f311bb0919d86ab3df2810dc0b81b70a87677e3Kostya Serebryany    ACCESS_ADDRESS(ptr + (size) - 1, isWrite); \
521e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  } \
53e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany} while (0)
541e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#define ASAN_READ_RANGE(offset, size) do { \
561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  ACCESS_MEMORY_RANGE(offset, size, false); \
57e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany} while (0)
581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#define ASAN_WRITE_RANGE(offset, size) do { \
601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  ACCESS_MEMORY_RANGE(offset, size, true); \
61e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany} while (0)
621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
631e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Behavior of functions like "memcpy" or "strcpy" is undefined
641e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// if memory intervals overlap. We report error in this case.
651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Macro is used to avoid creation of new frames.
663f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryanystatic inline bool RangesOverlap(const char *offset1, uptr length1,
673f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany                                 const char *offset2, uptr length2) {
680985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany  return !((offset1 + length1 <= offset2) || (offset2 + length2 <= offset1));
691e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
70c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany#define CHECK_RANGES_OVERLAP(name, _offset1, length1, _offset2, length2) do { \
711e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  const char *offset1 = (const char*)_offset1; \
721e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  const char *offset2 = (const char*)_offset2; \
730985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany  if (RangesOverlap(offset1, length1, offset2, length2)) { \
74487fee7f6f7497906a00d7d2fe2c75e6d5d4feb1Alexey Samsonov    GET_STACK_TRACE_HERE(kStackTraceMax); \
75487fee7f6f7497906a00d7d2fe2c75e6d5d4feb1Alexey Samsonov    ReportStringFunctionMemoryRangesOverlap(name, offset1, length1, \
76487fee7f6f7497906a00d7d2fe2c75e6d5d4feb1Alexey Samsonov                                            offset2, length2, &stack); \
771e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  } \
78e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany} while (0)
791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
80e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany#define ENSURE_ASAN_INITED() do { \
81e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  CHECK(!asan_init_is_running); \
82e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  if (!asan_inited) { \
83e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany    __asan_init(); \
84e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  } \
85e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany} while (0)
861e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
87c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonovstatic inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) {
8881a7a4ab53c94e76c3b131d6f0ed82894640900bAlexey Samsonov#if ASAN_INTERCEPT_STRNLEN
893f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  if (REAL(strnlen) != 0) {
9009672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(strnlen)(s, maxlen);
911e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
92f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov#endif
93c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov  return internal_strnlen(s, maxlen);
94a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany}
951e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
961e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}  // namespace __asan
971e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// ---------------------- Wrappers ---------------- {{{1
991e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyusing namespace __asan;  // NOLINT
1001e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
101600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanovstatic thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
1024803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  AsanThread *t = (AsanThread*)arg;
1034803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  asanThreadRegistry().SetCurrent(t);
1044803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  return t->ThreadStart();
1054803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
1064803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
107fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_PTHREAD_CREATE
108b8ef925563f8dde5be837c4b0569082867c5f14cEvgeniy StepanovINTERCEPTOR(int, pthread_create, void *thread,
109b8ef925563f8dde5be837c4b0569082867c5f14cEvgeniy Stepanov    void *attr, void *(*start_routine)(void*), void *arg) {
1109cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov  GET_STACK_TRACE_HERE(kStackTraceMax);
111e0cff0bc20ae51790c8edfbceb817e18ebf5355eKostya Serebryany  u32 current_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
11255cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov  AsanThread *t = AsanThread::Create(current_tid, start_routine, arg, &stack);
11355cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov  asanThreadRegistry().RegisterThread(t);
11409672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(pthread_create)(thread, attr, asan_thread_start, t);
1154803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
116fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif  // ASAN_INTERCEPT_PTHREAD_CREATE
1174803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
11834a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
119f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void*, signal, int signum, void *handler) {
120034bda5eab7cda14fac0bed3a39de4a3dbce3cffAlexander Potapenko  if (!AsanInterceptsSignal(signum)) {
121034bda5eab7cda14fac0bed3a39de4a3dbce3cffAlexander Potapenko    return REAL(signal)(signum, handler);
1224803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  }
1233f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  return 0;
1244803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
1254803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
126da13ba833b046553f50b54538e4828287ddbf5c0Alexey SamsonovINTERCEPTOR(int, sigaction, int signum, const struct sigaction *act,
127da13ba833b046553f50b54538e4828287ddbf5c0Alexey Samsonov                            struct sigaction *oldact) {
128034bda5eab7cda14fac0bed3a39de4a3dbce3cffAlexander Potapenko  if (!AsanInterceptsSignal(signum)) {
129034bda5eab7cda14fac0bed3a39de4a3dbce3cffAlexander Potapenko    return REAL(sigaction)(signum, act, oldact);
1304803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  }
131034bda5eab7cda14fac0bed3a39de4a3dbce3cffAlexander Potapenko  return 0;
1324803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
13334a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov#elif ASAN_POSIX
13434a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov// We need to have defined REAL(sigaction) on posix systems.
13534a3202a2c22816a6da66959e266a2d078ded37bAlexey SamsonovDEFINE_REAL(int, sigaction, int signum, const struct sigaction *act,
13634a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov    struct sigaction *oldact);
13734a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov#endif  // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
1384803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
139f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, longjmp, void *env, int val) {
140f54b1f9b73a6855d77ee270c282bd61407fa73a0Kostya Serebryany  __asan_handle_no_return();
14109672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  REAL(longjmp)(env, val);
1424803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
1434803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
144fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT__LONGJMP
145f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, _longjmp, void *env, int val) {
146f54b1f9b73a6855d77ee270c282bd61407fa73a0Kostya Serebryany  __asan_handle_no_return();
14709672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  REAL(_longjmp)(env, val);
1484803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
149fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif
1504803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
151fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_SIGLONGJMP
152f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, siglongjmp, void *env, int val) {
153f54b1f9b73a6855d77ee270c282bd61407fa73a0Kostya Serebryany  __asan_handle_no_return();
15409672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  REAL(siglongjmp)(env, val);
1554803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
15607bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov#endif
1574803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
158fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT___CXA_THROW
159f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
16009672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  CHECK(REAL(__cxa_throw));
161f54b1f9b73a6855d77ee270c282bd61407fa73a0Kostya Serebryany  __asan_handle_no_return();
16209672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  REAL(__cxa_throw)(a, b, c);
1634803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
1644803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany#endif
1654803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
1664803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany// intercept mlock and friends.
1674803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany// Since asan maps 16T of RAM, mlock is completely unfriendly to asan.
1684803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany// All functions return 0 (success).
1694803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanystatic void MlockIsUnsupported() {
1704803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  static bool printed = 0;
1714803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  if (printed) return;
1724803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  printed = true;
1734803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  Printf("INFO: AddressSanitizer ignores mlock/mlockall/munlock/munlockall\n");
1744803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
1753389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov
176f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonovextern "C" {
17700f1c091441be5c2cacb99e21bd1965a5e418242Alexander PotapenkoINTERCEPTOR(int, mlock, const void *addr, uptr len) {
1784803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  MlockIsUnsupported();
1794803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  return 0;
1804803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
1813389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov
18200f1c091441be5c2cacb99e21bd1965a5e418242Alexander PotapenkoINTERCEPTOR(int, munlock, const void *addr, uptr len) {
1834803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  MlockIsUnsupported();
1844803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  return 0;
1854803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
1863389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov
18700f1c091441be5c2cacb99e21bd1965a5e418242Alexander PotapenkoINTERCEPTOR(int, mlockall, int flags) {
1884803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  MlockIsUnsupported();
1894803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  return 0;
1904803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
1913389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov
19200f1c091441be5c2cacb99e21bd1965a5e418242Alexander PotapenkoINTERCEPTOR(int, munlockall, void) {
1934803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  MlockIsUnsupported();
1944803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  return 0;
1954803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
1964803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}  // extern "C"
1974803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
19852fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryanystatic inline int CharCmp(unsigned char c1, unsigned char c2) {
19952fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
20052fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany}
20152fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany
20252fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryanystatic inline int CharCaseCmp(unsigned char c1, unsigned char c2) {
2038898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov  int c1_low = ToLower(c1);
2048898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov  int c2_low = ToLower(c2);
20552fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  return c1_low - c2_low;
20652fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany}
20752fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany
2083f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {
2090ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko#if MAC_INTERPOSE_FUNCTIONS
2100ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko  if (!asan_inited) return REAL(memcmp)(a1, a2, size);
2110ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko#endif
21252fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  ENSURE_ASAN_INITED();
21352fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  unsigned char c1 = 0, c2 = 0;
21452fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  const unsigned char *s1 = (const unsigned char*)a1;
21552fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  const unsigned char *s2 = (const unsigned char*)a2;
2163f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  uptr i;
21752fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  for (i = 0; i < size; i++) {
21852fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany    c1 = s1[i];
21952fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany    c2 = s2[i];
22052fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany    if (c1 != c2) break;
22152fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  }
22252fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  ASAN_READ_RANGE(s1, Min(i + 1, size));
22352fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  ASAN_READ_RANGE(s2, Min(i + 1, size));
22452fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  return CharCmp(c1, c2);
22552fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany}
22652fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany
2273f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) {
2281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // memcpy is called during __asan_init() from the internals
2291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // of printf(...).
2301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (asan_init_is_running) {
23109672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(memcpy)(to, from, size);
2321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
233e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
234cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_intrin) {
235c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany    if (to != from) {
236c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany      // We do not treat memcpy with to==from as a bug.
237c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany      // See http://llvm.org/bugs/show_bug.cgi?id=11763.
238c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany      CHECK_RANGES_OVERLAP("memcpy", to, size, from, size);
239c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany    }
2401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_WRITE_RANGE(from, size);
2411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(to, size);
2421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
24309672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(memcpy)(to, from, size);
2441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
2451e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
2463f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) {
247a1a25c1afe38e59ffb342c24bb5bb10d05679df7Alexey Samsonov  if (asan_init_is_running) {
248a1a25c1afe38e59ffb342c24bb5bb10d05679df7Alexey Samsonov    return REAL(memmove)(to, from, size);
249a1a25c1afe38e59ffb342c24bb5bb10d05679df7Alexey Samsonov  }
250e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
251cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_intrin) {
2521e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_WRITE_RANGE(from, size);
2531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(to, size);
2541e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
25509672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(memmove)(to, from, size);
2561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
2571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
2583f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(void*, memset, void *block, int c, uptr size) {
259ebb9702cff96192c6a6ea963037929ca7ed60eaeAlexander Potapenko  // memset is called inside Printf.
260e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  if (asan_init_is_running) {
26109672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(memset)(block, c, size);
262e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  }
263e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
264cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_intrin) {
2651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_WRITE_RANGE(block, size);
2661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
26709672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(memset)(block, c, size);
2681e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
2691e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
270f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strchr, const char *str, int c) {
2710ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko#if MAC_INTERPOSE_FUNCTIONS
2720ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko  if (!asan_inited) return REAL(strchr)(str, c);
2730ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko#endif
274e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
27509672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  char *result = REAL(strchr)(str, c);
276cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_str) {
2773f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany    uptr bytes_read = (result ? result - str : REAL(strlen)(str)) + 1;
2781e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(str, bytes_read);
2791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
2801e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return result;
2811e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
2821e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
283fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_INDEX
284fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov# if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
2854b0c5f240e71be4f375627e57d0f1b89600918a7Evgeniy StepanovINTERCEPTOR(char*, index, const char *string, int c)
286adf2b036127d7e887392d9be5b02069b777ee280Alexey Samsonov  ALIAS(WRAPPER_NAME(strchr));
287fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov# else
288b4fefa713da3dabda1cd83ae4182c71f1683f02cAlexey SamsonovDEFINE_REAL(char*, index, const char *string, int c)
289fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov# endif
290fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif  // ASAN_INTERCEPT_INDEX
291af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany
29237b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko// For both strcat() and strncat() we need to check the validity of |to|
29337b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko// argument irrespective of the |from| length.
294f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strcat, char *to, const char *from) {  // NOLINT
2950985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany  ENSURE_ASAN_INITED();
296cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_str) {
2973f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany    uptr from_length = REAL(strlen)(from);
2980985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany    ASAN_READ_RANGE(from, from_length + 1);
29937b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko    uptr to_length = REAL(strlen)(to);
30037b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko    ASAN_READ_RANGE(to, to_length);
30137b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko    ASAN_WRITE_RANGE(to + to_length, from_length + 1);
30237b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko    // If the copying actually happens, the |from| string should not overlap
30337b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko    // with the resulting string starting at |to|, which has a length of
30437b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko    // to_length + from_length + 1.
3050985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany    if (from_length > 0) {
30637b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko      CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1,
30737b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko                           from, from_length + 1);
3080985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany    }
3090985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany  }
31009672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(strcat)(to, from);  // NOLINT
3110985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany}
3120985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany
313c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey SamsonovINTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
314c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov  ENSURE_ASAN_INITED();
31537b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko  if (flags()->replace_str) {
316c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov    uptr from_length = MaybeRealStrnlen(from, size);
31737b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko    uptr copy_length = Min(size, from_length + 1);
31837b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko    ASAN_READ_RANGE(from, copy_length);
319c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov    uptr to_length = REAL(strlen)(to);
320c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov    ASAN_READ_RANGE(to, to_length);
321c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov    ASAN_WRITE_RANGE(to + to_length, from_length + 1);
322c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov    if (from_length > 0) {
32337b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko      CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1,
32437b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko                           from, copy_length);
325c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov    }
326c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov  }
327c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov  return REAL(strncat)(to, from, size);
328c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov}
329c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov
330f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(int, strcmp, const char *s1, const char *s2) {
3310ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko#if MAC_INTERPOSE_FUNCTIONS
3320ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko  if (!asan_inited) return REAL(strcmp)(s1, s2);
3330ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko#endif
334fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  if (asan_init_is_running) {
335fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov    return REAL(strcmp)(s1, s2);
3361e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
3378648e7734ff02a25706464e9e294bd217622bcaeKostya Serebryany  ENSURE_ASAN_INITED();
3381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  unsigned char c1, c2;
3393f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  uptr i;
3401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  for (i = 0; ; i++) {
3411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    c1 = (unsigned char)s1[i];
3421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    c2 = (unsigned char)s2[i];
3431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    if (c1 != c2 || c1 == '\0') break;
3441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
3451e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  ASAN_READ_RANGE(s1, i + 1);
3461e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  ASAN_READ_RANGE(s2, i + 1);
3471e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return CharCmp(c1, c2);
3481e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
3491e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
350f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strcpy, char *to, const char *from) {  // NOLINT
3510ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko#if MAC_INTERPOSE_FUNCTIONS
352beda44f87166f91dbeef3d174d77395653bead4dAlexander Potapenko  if (!asan_inited) return REAL(strcpy)(to, from);  // NOLINT
3530ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko#endif
3541e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // strcpy is called from malloc_default_purgeable_zone()
3551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // in __asan::ReplaceSystemAlloc() on Mac.
3561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (asan_init_is_running) {
35709672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(strcpy)(to, from);  // NOLINT
3581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
359e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
360cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_str) {
3613f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany    uptr from_size = REAL(strlen)(from) + 1;
362c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany    CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size);
3631e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(from, from_size);
3641e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_WRITE_RANGE(to, from_size);
3651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
36609672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(strcpy)(to, from);  // NOLINT
3671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
3681e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
369fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_STRDUP
370f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strdup, const char *s) {
3710ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko#if MAC_INTERPOSE_FUNCTIONS
3720ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko  if (!asan_inited) return REAL(strdup)(s);
3730ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko#endif
374e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
375cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_str) {
3763f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany    uptr length = REAL(strlen)(s);
3771e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(s, length + 1);
3781e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
37909672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(strdup)(s);
3801e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
381fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif
3821e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
3833f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(uptr, strlen, const char *s) {
3840ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko#if MAC_INTERPOSE_FUNCTIONS
3850ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko  if (!asan_inited) return REAL(strlen)(s);
3860ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko#endif
3871e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // strlen is called from malloc_default_purgeable_zone()
3881e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // in __asan::ReplaceSystemAlloc() on Mac.
3891e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (asan_init_is_running) {
39009672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(strlen)(s);
3911e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
392e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
3933f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  uptr length = REAL(strlen)(s);
394cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_str) {
3951e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(s, length + 1);
3961e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
3971e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return length;
3981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
3991e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
400fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP
401fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey SamsonovINTERCEPTOR(int, strcasecmp, const char *s1, const char *s2) {
402fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  ENSURE_ASAN_INITED();
403fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  unsigned char c1, c2;
404fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  uptr i;
405fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  for (i = 0; ; i++) {
406fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov    c1 = (unsigned char)s1[i];
407fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov    c2 = (unsigned char)s2[i];
408fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov    if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
409fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  }
410fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  ASAN_READ_RANGE(s1, i + 1);
411fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  ASAN_READ_RANGE(s2, i + 1);
412fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  return CharCaseCmp(c1, c2);
413fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov}
414fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov
4153f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, uptr n) {
416af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany  ENSURE_ASAN_INITED();
417af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany  unsigned char c1 = 0, c2 = 0;
4183f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  uptr i;
419f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov  for (i = 0; i < n; i++) {
420af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany    c1 = (unsigned char)s1[i];
421af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany    c2 = (unsigned char)s2[i];
422af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany    if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
423af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany  }
424f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov  ASAN_READ_RANGE(s1, Min(i + 1, n));
425f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov  ASAN_READ_RANGE(s2, Min(i + 1, n));
426af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany  return CharCaseCmp(c1, c2);
427af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany}
428fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif  // ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP
429af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany
4303f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(int, strncmp, const char *s1, const char *s2, uptr size) {
4310ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko#if MAC_INTERPOSE_FUNCTIONS
4320ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko  if (!asan_inited) return REAL(strncmp)(s1, s2, size);
4330ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko#endif
4341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // strncmp is called from malloc_default_purgeable_zone()
4351e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // in __asan::ReplaceSystemAlloc() on Mac.
4361e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (asan_init_is_running) {
43709672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(strncmp)(s1, s2, size);
4381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
4398648e7734ff02a25706464e9e294bd217622bcaeKostya Serebryany  ENSURE_ASAN_INITED();
4401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  unsigned char c1 = 0, c2 = 0;
4413f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  uptr i;
4421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  for (i = 0; i < size; i++) {
4431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    c1 = (unsigned char)s1[i];
4441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    c2 = (unsigned char)s2[i];
4451e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    if (c1 != c2 || c1 == '\0') break;
4461e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
4472d8b3bdb112ebb8ed3f15ee41d4cebcd683b41b0Kostya Serebryany  ASAN_READ_RANGE(s1, Min(i + 1, size));
4482d8b3bdb112ebb8ed3f15ee41d4cebcd683b41b0Kostya Serebryany  ASAN_READ_RANGE(s2, Min(i + 1, size));
4491e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return CharCmp(c1, c2);
4501e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
4511e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
4523f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) {
453e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
454cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_str) {
455c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov    uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1);
456c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany    CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size);
4571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(from, from_size);
4581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_WRITE_RANGE(to, size);
4591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
46009672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(strncpy)(to, from, size);
4611e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
4621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
46381a7a4ab53c94e76c3b131d6f0ed82894640900bAlexey Samsonov#if ASAN_INTERCEPT_STRNLEN
4643f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(uptr, strnlen, const char *s, uptr maxlen) {
465e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
4663f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  uptr length = REAL(strnlen)(s, maxlen);
467cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_str) {
4682d8b3bdb112ebb8ed3f15ee41d4cebcd683b41b0Kostya Serebryany    ASAN_READ_RANGE(s, Min(length + 1, maxlen));
4691e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
4701e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return length;
4711e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
47281a7a4ab53c94e76c3b131d6f0ed82894640900bAlexey Samsonov#endif  // ASAN_INTERCEPT_STRNLEN
473547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany
4748f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonovstatic inline bool IsValidStrtolBase(int base) {
4758f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  return (base == 0) || (2 <= base && base <= 36);
4768f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov}
4778f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov
4788f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonovstatic inline void FixRealStrtolEndptr(const char *nptr, char **endptr) {
4793f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  CHECK(endptr != 0);
4808f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  if (nptr == *endptr) {
4818f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    // No digits were found at strtol call, we need to find out the last
4828f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    // symbol accessed by strtoll on our own.
4838f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    // We get this symbol by skipping leading blanks and optional +/- sign.
4848f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    while (IsSpace(*nptr)) nptr++;
4858f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    if (*nptr == '+' || *nptr == '-') nptr++;
4868f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    *endptr = (char*)nptr;
4878f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  }
4888f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  CHECK(*endptr >= nptr);
48984ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov}
49084ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov
491847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR(long, strtol, const char *nptr,  // NOLINT
49284ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov            char **endptr, int base) {
49384ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov  ENSURE_ASAN_INITED();
494cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (!flags()->replace_str) {
495847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov    return REAL(strtol)(nptr, endptr, base);
49684ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov  }
49784ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov  char *real_endptr;
498847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  long result = REAL(strtol)(nptr, &real_endptr, base);  // NOLINT
4993f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  if (endptr != 0) {
50084ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov    *endptr = real_endptr;
50184ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov  }
5028f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  if (IsValidStrtolBase(base)) {
5038f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    FixRealStrtolEndptr(nptr, &real_endptr);
50484ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov    ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
50584ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov  }
50684ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov  return result;
50784ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov}
50884ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov
509847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR(int, atoi, const char *nptr) {
5100ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko#if MAC_INTERPOSE_FUNCTIONS
5110ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko  if (!asan_inited) return REAL(atoi)(nptr);
5120ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko#endif
513847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  ENSURE_ASAN_INITED();
514cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (!flags()->replace_str) {
515847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov    return REAL(atoi)(nptr);
516847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  }
517847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  char *real_endptr;
518847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  // "man atoi" tells that behavior of atoi(nptr) is the same as
5193f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
520847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  // parsed integer can't be stored in *long* type (even if it's
521847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  // different from int). So, we just imitate this behavior.
522847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  int result = REAL(strtol)(nptr, &real_endptr, 10);
523847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  FixRealStrtolEndptr(nptr, &real_endptr);
524847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
525847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  return result;
526847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov}
527847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov
528847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR(long, atol, const char *nptr) {  // NOLINT
5290ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko#if MAC_INTERPOSE_FUNCTIONS
5300ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko  if (!asan_inited) return REAL(atol)(nptr);
5310ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko#endif
532847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  ENSURE_ASAN_INITED();
533cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (!flags()->replace_str) {
534847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov    return REAL(atol)(nptr);
535847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  }
536847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  char *real_endptr;
537847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  long result = REAL(strtol)(nptr, &real_endptr, 10);  // NOLINT
538847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  FixRealStrtolEndptr(nptr, &real_endptr);
539847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
540847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  return result;
541847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov}
542847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov
543847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
544847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR(long long, strtoll, const char *nptr,  // NOLINT
5458f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov            char **endptr, int base) {
5468f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  ENSURE_ASAN_INITED();
547cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (!flags()->replace_str) {
548847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov    return REAL(strtoll)(nptr, endptr, base);
5498f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  }
5508f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  char *real_endptr;
551847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  long long result = REAL(strtoll)(nptr, &real_endptr, base);  // NOLINT
5523f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  if (endptr != 0) {
5538f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    *endptr = real_endptr;
5548f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  }
555847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  // If base has unsupported value, strtoll can exit with EINVAL
556847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  // without reading any characters. So do additional checks only
557847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  // if base is valid.
5588f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  if (IsValidStrtolBase(base)) {
5598f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    FixRealStrtolEndptr(nptr, &real_endptr);
5608f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
5618f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  }
5628f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  return result;
5638f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov}
5648f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov
565847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR(long long, atoll, const char *nptr) {  // NOLINT
566847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  ENSURE_ASAN_INITED();
567cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (!flags()->replace_str) {
568847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov    return REAL(atoll)(nptr);
569847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  }
570847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  char *real_endptr;
571847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  long long result = REAL(strtoll)(nptr, &real_endptr, 10);  // NOLINT
572847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  FixRealStrtolEndptr(nptr, &real_endptr);
573847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
574847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  return result;
575847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov}
576847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov#endif  // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
577847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov
578580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov#define ASAN_INTERCEPT_FUNC(name) do { \
579cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov      if (!INTERCEPT_FUNCTION(name) && flags()->verbosity > 0) \
580580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov        Report("AddressSanitizer: failed to intercept '" #name "'\n"); \
581580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov    } while (0)
582580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov
583600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov#if defined(_WIN32)
584600972e3427173cc8904d741decd1af0ed5de9fdTimur IskhodzhanovINTERCEPTOR_WINAPI(DWORD, CreateThread,
5853f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany                   void* security, uptr stack_size,
586600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov                   DWORD (__stdcall *start_routine)(void*), void* arg,
587600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov                   DWORD flags, void* tid) {
588600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  GET_STACK_TRACE_HERE(kStackTraceMax);
589e0cff0bc20ae51790c8edfbceb817e18ebf5355eKostya Serebryany  u32 current_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
590600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  AsanThread *t = AsanThread::Create(current_tid, start_routine, arg, &stack);
591600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  asanThreadRegistry().RegisterThread(t);
592600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  return REAL(CreateThread)(security, stack_size,
593600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov                            asan_thread_start, t, flags, tid);
594600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov}
595600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov
596600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanovnamespace __asan {
597600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanovvoid InitializeWindowsInterceptors() {
598580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(CreateThread);
599600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov}
600600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov
601600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov}  // namespace __asan
602600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov#endif
603600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov
604547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany// ---------------------- InitializeAsanInterceptors ---------------- {{{1
605547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryanynamespace __asan {
606547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryanyvoid InitializeAsanInterceptors() {
607fdbdab5ff8de4c23b58bb411ea2358a78e2d9b2fKostya Serebryany  static bool was_called_once;
608fdbdab5ff8de4c23b58bb411ea2358a78e2d9b2fKostya Serebryany  CHECK(was_called_once == false);
609fdbdab5ff8de4c23b58bb411ea2358a78e2d9b2fKostya Serebryany  was_called_once = true;
6100ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko#if MAC_INTERPOSE_FUNCTIONS
6110ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko  return;
6120ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko#endif
61307bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  // Intercept mem* functions.
614580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(memcmp);
615580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(memmove);
616580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(memset);
61738dd4ed885e714c376466f6fe0d69f5f22d37014Alexey Samsonov  if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) {
618580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov    ASAN_INTERCEPT_FUNC(memcpy);
619573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko  } else {
6200ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko#if !MAC_INTERPOSE_FUNCTIONS
621beda44f87166f91dbeef3d174d77395653bead4dAlexander Potapenko    // If we're using dynamic interceptors on Mac, these two are just plain
6220ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko    // functions.
6230ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko    *(uptr*)&REAL(memcpy) = (uptr)REAL(memmove);
6240ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko#endif
625573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko  }
62607bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov
62707bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  // Intercept str* functions.
628580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strcat);  // NOLINT
629580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strchr);
630580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strcmp);
631580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strcpy);  // NOLINT
632580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strlen);
633c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov  ASAN_INTERCEPT_FUNC(strncat);
634580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strncmp);
635580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strncpy);
636fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP
637580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strcasecmp);
638580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strncasecmp);
639fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif
640fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_STRDUP
641fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  ASAN_INTERCEPT_FUNC(strdup);
642fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif
643fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_STRNLEN
644fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  ASAN_INTERCEPT_FUNC(strnlen);
645fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif
646fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_INDEX
647fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov# if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
648580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(index);
64907bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov# else
650619e8bf99d2714c4411fefba22d54c233d93a177Meador Inge  CHECK(OVERRIDE_FUNCTION(index, WRAP(strchr)));
65107bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov# endif
65207bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov#endif
6535b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov
654580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(atoi);
655580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(atol);
656580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strtol);
657847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
658580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(atoll);
659580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strtoll);
66084ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov#endif
66184ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov
662f0c6de3d91ba5cdfbb17a630e823523c7d433160Alexander Potapenko#if ASAN_INTERCEPT_MLOCKX
66300f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko  // Intercept mlock/munlock.
66400f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko  ASAN_INTERCEPT_FUNC(mlock);
66500f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko  ASAN_INTERCEPT_FUNC(munlock);
66600f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko  ASAN_INTERCEPT_FUNC(mlockall);
66700f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko  ASAN_INTERCEPT_FUNC(munlockall);
668f0c6de3d91ba5cdfbb17a630e823523c7d433160Alexander Potapenko#endif
66900f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko
67007bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  // Intecept signal- and jump-related functions.
671580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(longjmp);
67234a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
673580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(sigaction);
674580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(signal);
675919c24787a655597bdcf367e26c9dd1504e9f463Evgeniy Stepanov#endif
676fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT__LONGJMP
677580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(_longjmp);
678fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif
679fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_SIGLONGJMP
680580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(siglongjmp);
681fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif
682fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov
683fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  // Intercept exception handling functions.
684fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT___CXA_THROW
685fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  INTERCEPT_FUNCTION(__cxa_throw);
6863e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov#endif
6873e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov
68807bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  // Intercept threading-related functions
689fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_PTHREAD_CREATE
690580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(pthread_create);
69107bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov#endif
69207bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov
693600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  // Some Windows-specific interceptors.
694600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov#if defined(_WIN32)
695600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  InitializeWindowsInterceptors();
696600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov#endif
697600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov
69807bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  // Some Mac-specific interceptors.
69907bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov#if defined(__APPLE__)
700beba6448539095b67cab266d09cd7b7d313b8c3dAlexey Samsonov  InitializeMacInterceptors();
701547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany#endif
702547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany
703cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->verbosity > 0) {
7042962f26071ebef1d5fec52b5569e5ae7aae45c9bAlexander Potapenko    Report("AddressSanitizer: libc interceptors initialized\n");
705547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  }
706547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany}
707547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany
708547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany}  // namespace __asan
709