asan_interceptors.cc revision 05bf9a51dfeac0f84f6dbc2dacf987249c0fc612
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) {
20952fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  ENSURE_ASAN_INITED();
21052fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  unsigned char c1 = 0, c2 = 0;
21152fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  const unsigned char *s1 = (const unsigned char*)a1;
21252fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  const unsigned char *s2 = (const unsigned char*)a2;
2133f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  uptr i;
21452fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  for (i = 0; i < size; i++) {
21552fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany    c1 = s1[i];
21652fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany    c2 = s2[i];
21752fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany    if (c1 != c2) break;
21852fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  }
21952fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  ASAN_READ_RANGE(s1, Min(i + 1, size));
22052fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  ASAN_READ_RANGE(s2, Min(i + 1, size));
22152fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  return CharCmp(c1, c2);
22252fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany}
22352fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany
2243f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) {
2251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // memcpy is called during __asan_init() from the internals
2261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // of printf(...).
2271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (asan_init_is_running) {
22809672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(memcpy)(to, from, size);
2291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
230e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
231cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_intrin) {
232c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany    if (to != from) {
233c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany      // We do not treat memcpy with to==from as a bug.
234c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany      // See http://llvm.org/bugs/show_bug.cgi?id=11763.
235c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany      CHECK_RANGES_OVERLAP("memcpy", to, size, from, size);
236c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany    }
2371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_WRITE_RANGE(from, size);
2381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(to, size);
2391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
24009672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(memcpy)(to, from, size);
2411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
2421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
2433f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) {
244a1a25c1afe38e59ffb342c24bb5bb10d05679df7Alexey Samsonov  if (asan_init_is_running) {
245a1a25c1afe38e59ffb342c24bb5bb10d05679df7Alexey Samsonov    return REAL(memmove)(to, from, size);
246a1a25c1afe38e59ffb342c24bb5bb10d05679df7Alexey Samsonov  }
247e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
248cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_intrin) {
2491e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_WRITE_RANGE(from, size);
2501e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(to, size);
2511e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
25209672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(memmove)(to, from, size);
2531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
2541e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
2553f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(void*, memset, void *block, int c, uptr size) {
256ebb9702cff96192c6a6ea963037929ca7ed60eaeAlexander Potapenko  // memset is called inside Printf.
257e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  if (asan_init_is_running) {
25809672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(memset)(block, c, size);
259e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  }
260e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
261cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_intrin) {
2621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_WRITE_RANGE(block, size);
2631e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
26409672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(memset)(block, c, size);
2651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
2661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
267f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strchr, const char *str, int c) {
268e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
26909672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  char *result = REAL(strchr)(str, c);
270cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_str) {
2713f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany    uptr bytes_read = (result ? result - str : REAL(strlen)(str)) + 1;
2721e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(str, bytes_read);
2731e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
2741e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return result;
2751e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
2761e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
277fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_INDEX
278fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov# if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
2794b0c5f240e71be4f375627e57d0f1b89600918a7Evgeniy StepanovINTERCEPTOR(char*, index, const char *string, int c)
280adf2b036127d7e887392d9be5b02069b777ee280Alexey Samsonov  ALIAS(WRAPPER_NAME(strchr));
281fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov# else
282b4fefa713da3dabda1cd83ae4182c71f1683f02cAlexey SamsonovDEFINE_REAL(char*, index, const char *string, int c)
283fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov# endif
284fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif  // ASAN_INTERCEPT_INDEX
285af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany
28637b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko// For both strcat() and strncat() we need to check the validity of |to|
28737b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko// argument irrespective of the |from| length.
288f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strcat, char *to, const char *from) {  // NOLINT
2890985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany  ENSURE_ASAN_INITED();
290cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_str) {
2913f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany    uptr from_length = REAL(strlen)(from);
2920985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany    ASAN_READ_RANGE(from, from_length + 1);
29337b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko    uptr to_length = REAL(strlen)(to);
29437b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko    ASAN_READ_RANGE(to, to_length);
29537b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko    ASAN_WRITE_RANGE(to + to_length, from_length + 1);
29637b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko    // If the copying actually happens, the |from| string should not overlap
29737b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko    // with the resulting string starting at |to|, which has a length of
29837b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko    // to_length + from_length + 1.
2990985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany    if (from_length > 0) {
30037b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko      CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1,
30137b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko                           from, from_length + 1);
3020985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany    }
3030985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany  }
30409672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(strcat)(to, from);  // NOLINT
3050985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany}
3060985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany
307c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey SamsonovINTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
308c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov  ENSURE_ASAN_INITED();
30937b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko  if (flags()->replace_str) {
310c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov    uptr from_length = MaybeRealStrnlen(from, size);
31137b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko    uptr copy_length = Min(size, from_length + 1);
31237b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko    ASAN_READ_RANGE(from, copy_length);
313c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov    uptr to_length = REAL(strlen)(to);
314c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov    ASAN_READ_RANGE(to, to_length);
315c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov    ASAN_WRITE_RANGE(to + to_length, from_length + 1);
316c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov    if (from_length > 0) {
31737b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko      CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1,
31837b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko                           from, copy_length);
319c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov    }
320c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov  }
321c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov  return REAL(strncat)(to, from, size);
322c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov}
323c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov
324f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(int, strcmp, const char *s1, const char *s2) {
325fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  if (asan_init_is_running) {
326fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov    return REAL(strcmp)(s1, s2);
3271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
3288648e7734ff02a25706464e9e294bd217622bcaeKostya Serebryany  ENSURE_ASAN_INITED();
3291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  unsigned char c1, c2;
3303f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  uptr i;
3311e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  for (i = 0; ; i++) {
3321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    c1 = (unsigned char)s1[i];
3331e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    c2 = (unsigned char)s2[i];
3341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    if (c1 != c2 || c1 == '\0') break;
3351e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
3361e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  ASAN_READ_RANGE(s1, i + 1);
3371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  ASAN_READ_RANGE(s2, i + 1);
3381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return CharCmp(c1, c2);
3391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
3401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
341f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strcpy, char *to, const char *from) {  // NOLINT
3421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // strcpy is called from malloc_default_purgeable_zone()
3431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // in __asan::ReplaceSystemAlloc() on Mac.
3441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (asan_init_is_running) {
34509672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(strcpy)(to, from);  // NOLINT
3461e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
347e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
348cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_str) {
3493f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany    uptr from_size = REAL(strlen)(from) + 1;
350c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany    CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size);
3511e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(from, from_size);
3521e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_WRITE_RANGE(to, from_size);
3531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
35409672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(strcpy)(to, from);  // NOLINT
3551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
3561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
357fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_STRDUP
358f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strdup, const char *s) {
359e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
360cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_str) {
3613f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany    uptr length = REAL(strlen)(s);
3621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(s, length + 1);
3631e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
36409672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(strdup)(s);
3651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
366fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif
3671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
3683f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(uptr, strlen, const char *s) {
3691e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // strlen is called from malloc_default_purgeable_zone()
3701e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // in __asan::ReplaceSystemAlloc() on Mac.
3711e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (asan_init_is_running) {
37209672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(strlen)(s);
3731e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
374e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
3753f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  uptr length = REAL(strlen)(s);
376cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_str) {
3771e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(s, length + 1);
3781e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
3791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return length;
3801e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
3811e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
382fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP
383fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey SamsonovINTERCEPTOR(int, strcasecmp, const char *s1, const char *s2) {
384fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  ENSURE_ASAN_INITED();
385fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  unsigned char c1, c2;
386fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  uptr i;
387fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  for (i = 0; ; i++) {
388fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov    c1 = (unsigned char)s1[i];
389fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov    c2 = (unsigned char)s2[i];
390fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov    if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
391fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  }
392fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  ASAN_READ_RANGE(s1, i + 1);
393fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  ASAN_READ_RANGE(s2, i + 1);
394fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  return CharCaseCmp(c1, c2);
395fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov}
396fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov
3973f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, uptr n) {
398af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany  ENSURE_ASAN_INITED();
399af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany  unsigned char c1 = 0, c2 = 0;
4003f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  uptr i;
401f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov  for (i = 0; i < n; i++) {
402af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany    c1 = (unsigned char)s1[i];
403af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany    c2 = (unsigned char)s2[i];
404af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany    if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
405af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany  }
406f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov  ASAN_READ_RANGE(s1, Min(i + 1, n));
407f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov  ASAN_READ_RANGE(s2, Min(i + 1, n));
408af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany  return CharCaseCmp(c1, c2);
409af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany}
410fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif  // ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP
411af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany
4123f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(int, strncmp, const char *s1, const char *s2, uptr size) {
4131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // strncmp is called from malloc_default_purgeable_zone()
4141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // in __asan::ReplaceSystemAlloc() on Mac.
4151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (asan_init_is_running) {
41609672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(strncmp)(s1, s2, size);
4171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
4188648e7734ff02a25706464e9e294bd217622bcaeKostya Serebryany  ENSURE_ASAN_INITED();
4191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  unsigned char c1 = 0, c2 = 0;
4203f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  uptr i;
4211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  for (i = 0; i < size; i++) {
4221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    c1 = (unsigned char)s1[i];
4231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    c2 = (unsigned char)s2[i];
4241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    if (c1 != c2 || c1 == '\0') break;
4251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
4262d8b3bdb112ebb8ed3f15ee41d4cebcd683b41b0Kostya Serebryany  ASAN_READ_RANGE(s1, Min(i + 1, size));
4272d8b3bdb112ebb8ed3f15ee41d4cebcd683b41b0Kostya Serebryany  ASAN_READ_RANGE(s2, Min(i + 1, size));
4281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return CharCmp(c1, c2);
4291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
4301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
4313f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) {
432e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
433cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_str) {
434c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov    uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1);
435c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany    CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size);
4361e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(from, from_size);
4371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_WRITE_RANGE(to, size);
4381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
43909672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(strncpy)(to, from, size);
4401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
4411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
44281a7a4ab53c94e76c3b131d6f0ed82894640900bAlexey Samsonov#if ASAN_INTERCEPT_STRNLEN
4433f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(uptr, strnlen, const char *s, uptr maxlen) {
444e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
4453f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  uptr length = REAL(strnlen)(s, maxlen);
446cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->replace_str) {
4472d8b3bdb112ebb8ed3f15ee41d4cebcd683b41b0Kostya Serebryany    ASAN_READ_RANGE(s, Min(length + 1, maxlen));
4481e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
4491e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return length;
4501e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
45181a7a4ab53c94e76c3b131d6f0ed82894640900bAlexey Samsonov#endif  // ASAN_INTERCEPT_STRNLEN
452547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany
4538f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonovstatic inline bool IsValidStrtolBase(int base) {
4548f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  return (base == 0) || (2 <= base && base <= 36);
4558f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov}
4568f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov
4578f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonovstatic inline void FixRealStrtolEndptr(const char *nptr, char **endptr) {
4583f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  CHECK(endptr != 0);
4598f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  if (nptr == *endptr) {
4608f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    // No digits were found at strtol call, we need to find out the last
4618f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    // symbol accessed by strtoll on our own.
4628f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    // We get this symbol by skipping leading blanks and optional +/- sign.
4638f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    while (IsSpace(*nptr)) nptr++;
4648f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    if (*nptr == '+' || *nptr == '-') nptr++;
4658f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    *endptr = (char*)nptr;
4668f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  }
4678f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  CHECK(*endptr >= nptr);
46884ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov}
46984ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov
470847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR(long, strtol, const char *nptr,  // NOLINT
47184ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov            char **endptr, int base) {
47284ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov  ENSURE_ASAN_INITED();
473cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (!flags()->replace_str) {
474847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov    return REAL(strtol)(nptr, endptr, base);
47584ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov  }
47684ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov  char *real_endptr;
477847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  long result = REAL(strtol)(nptr, &real_endptr, base);  // NOLINT
4783f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  if (endptr != 0) {
47984ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov    *endptr = real_endptr;
48084ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov  }
4818f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  if (IsValidStrtolBase(base)) {
4828f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    FixRealStrtolEndptr(nptr, &real_endptr);
48384ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov    ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
48484ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov  }
48584ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov  return result;
48684ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov}
48784ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov
488847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR(int, atoi, const char *nptr) {
489847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  ENSURE_ASAN_INITED();
490cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (!flags()->replace_str) {
491847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov    return REAL(atoi)(nptr);
492847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  }
493847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  char *real_endptr;
494847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  // "man atoi" tells that behavior of atoi(nptr) is the same as
4953f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
496847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  // parsed integer can't be stored in *long* type (even if it's
497847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  // different from int). So, we just imitate this behavior.
498847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  int result = REAL(strtol)(nptr, &real_endptr, 10);
499847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  FixRealStrtolEndptr(nptr, &real_endptr);
500847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
501847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  return result;
502847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov}
503847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov
504847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR(long, atol, const char *nptr) {  // NOLINT
505847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  ENSURE_ASAN_INITED();
506cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (!flags()->replace_str) {
507847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov    return REAL(atol)(nptr);
508847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  }
509847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  char *real_endptr;
510847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  long result = REAL(strtol)(nptr, &real_endptr, 10);  // NOLINT
511847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  FixRealStrtolEndptr(nptr, &real_endptr);
512847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
513847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  return result;
514847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov}
515847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov
516847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
517847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR(long long, strtoll, const char *nptr,  // NOLINT
5188f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov            char **endptr, int base) {
5198f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  ENSURE_ASAN_INITED();
520cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (!flags()->replace_str) {
521847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov    return REAL(strtoll)(nptr, endptr, base);
5228f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  }
5238f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  char *real_endptr;
524847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  long long result = REAL(strtoll)(nptr, &real_endptr, base);  // NOLINT
5253f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  if (endptr != 0) {
5268f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    *endptr = real_endptr;
5278f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  }
528847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  // If base has unsupported value, strtoll can exit with EINVAL
529847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  // without reading any characters. So do additional checks only
530847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  // if base is valid.
5318f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  if (IsValidStrtolBase(base)) {
5328f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    FixRealStrtolEndptr(nptr, &real_endptr);
5338f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov    ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
5348f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  }
5358f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov  return result;
5368f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov}
5378f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov
538847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR(long long, atoll, const char *nptr) {  // NOLINT
539847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  ENSURE_ASAN_INITED();
540cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (!flags()->replace_str) {
541847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov    return REAL(atoll)(nptr);
542847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  }
543847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  char *real_endptr;
544847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  long long result = REAL(strtoll)(nptr, &real_endptr, 10);  // NOLINT
545847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  FixRealStrtolEndptr(nptr, &real_endptr);
546847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
547847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov  return result;
548847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov}
549847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov#endif  // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
550847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov
551580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov#define ASAN_INTERCEPT_FUNC(name) do { \
552cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov      if (!INTERCEPT_FUNCTION(name) && flags()->verbosity > 0) \
553580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov        Report("AddressSanitizer: failed to intercept '" #name "'\n"); \
554580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov    } while (0)
555580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov
556600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov#if defined(_WIN32)
557600972e3427173cc8904d741decd1af0ed5de9fdTimur IskhodzhanovINTERCEPTOR_WINAPI(DWORD, CreateThread,
5583f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany                   void* security, uptr stack_size,
559600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov                   DWORD (__stdcall *start_routine)(void*), void* arg,
560600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov                   DWORD flags, void* tid) {
561600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  GET_STACK_TRACE_HERE(kStackTraceMax);
562e0cff0bc20ae51790c8edfbceb817e18ebf5355eKostya Serebryany  u32 current_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
563600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  AsanThread *t = AsanThread::Create(current_tid, start_routine, arg, &stack);
564600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  asanThreadRegistry().RegisterThread(t);
565600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  return REAL(CreateThread)(security, stack_size,
566600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov                            asan_thread_start, t, flags, tid);
567600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov}
568600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov
569600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanovnamespace __asan {
570600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanovvoid InitializeWindowsInterceptors() {
571580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(CreateThread);
572600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov}
573600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov
574600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov}  // namespace __asan
575600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov#endif
576600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov
577547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany// ---------------------- InitializeAsanInterceptors ---------------- {{{1
578547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryanynamespace __asan {
579547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryanyvoid InitializeAsanInterceptors() {
580fdbdab5ff8de4c23b58bb411ea2358a78e2d9b2fKostya Serebryany  static bool was_called_once;
581fdbdab5ff8de4c23b58bb411ea2358a78e2d9b2fKostya Serebryany  CHECK(was_called_once == false);
582fdbdab5ff8de4c23b58bb411ea2358a78e2d9b2fKostya Serebryany  was_called_once = true;
58307bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  // Intercept mem* functions.
584580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(memcmp);
585580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(memmove);
586580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(memset);
58738dd4ed885e714c376466f6fe0d69f5f22d37014Alexey Samsonov  if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) {
588580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov    ASAN_INTERCEPT_FUNC(memcpy);
589573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko  } else {
59009672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    REAL(memcpy) = REAL(memmove);
591573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko  }
59207bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov
59307bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  // Intercept str* functions.
594580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strcat);  // NOLINT
595580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strchr);
596580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strcmp);
597580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strcpy);  // NOLINT
598580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strlen);
599c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov  ASAN_INTERCEPT_FUNC(strncat);
600580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strncmp);
601580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strncpy);
602fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP
603580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strcasecmp);
604580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strncasecmp);
605fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif
606fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_STRDUP
607fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  ASAN_INTERCEPT_FUNC(strdup);
608fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif
609fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_STRNLEN
610fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  ASAN_INTERCEPT_FUNC(strnlen);
611fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif
612fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_INDEX
613fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov# if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
614580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(index);
61507bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov# else
616619e8bf99d2714c4411fefba22d54c233d93a177Meador Inge  CHECK(OVERRIDE_FUNCTION(index, WRAP(strchr)));
61707bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov# endif
61807bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov#endif
6195b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov
620580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(atoi);
621580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(atol);
622580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strtol);
623847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
624580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(atoll);
625580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(strtoll);
62684ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov#endif
62784ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov
628f0c6de3d91ba5cdfbb17a630e823523c7d433160Alexander Potapenko#if ASAN_INTERCEPT_MLOCKX
62900f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko  // Intercept mlock/munlock.
63000f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko  ASAN_INTERCEPT_FUNC(mlock);
63100f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko  ASAN_INTERCEPT_FUNC(munlock);
63200f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko  ASAN_INTERCEPT_FUNC(mlockall);
63300f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko  ASAN_INTERCEPT_FUNC(munlockall);
634f0c6de3d91ba5cdfbb17a630e823523c7d433160Alexander Potapenko#endif
63500f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko
63607bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  // Intecept signal- and jump-related functions.
637580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(longjmp);
63834a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
639580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(sigaction);
640580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(signal);
641919c24787a655597bdcf367e26c9dd1504e9f463Evgeniy Stepanov#endif
642fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT__LONGJMP
643580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(_longjmp);
644fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif
645fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_SIGLONGJMP
646580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(siglongjmp);
647fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif
648fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov
649fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  // Intercept exception handling functions.
650fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT___CXA_THROW
651fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov  INTERCEPT_FUNCTION(__cxa_throw);
6523e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov#endif
6533e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov
65407bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  // Intercept threading-related functions
655fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_PTHREAD_CREATE
656580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov  ASAN_INTERCEPT_FUNC(pthread_create);
65707bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov#endif
65807bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov
659600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  // Some Windows-specific interceptors.
660600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov#if defined(_WIN32)
661600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  InitializeWindowsInterceptors();
662600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov#endif
663600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov
66407bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  // Some Mac-specific interceptors.
66507bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov#if defined(__APPLE__)
666beba6448539095b67cab266d09cd7b7d313b8c3dAlexey Samsonov  InitializeMacInterceptors();
667547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany#endif
668547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany
669cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->verbosity > 0) {
6702962f26071ebef1d5fec52b5569e5ae7aae45c9bAlexander Potapenko    Report("AddressSanitizer: libc interceptors initialized\n");
671547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  }
672547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany}
673547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany
674547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany}  // namespace __asan
675