asan_interceptors.cc revision 09672caefb5694f1981a1712fdefa44840a95e67
11e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===-- asan_interceptors.cc ------------------------------------*- C++ -*-===//
21e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//
31e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//                     The LLVM Compiler Infrastructure
41e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//
51e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// This file is distributed under the University of Illinois Open Source
61e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// License. See LICENSE.TXT for details.
71e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//
81e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===----------------------------------------------------------------------===//
91e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//
101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// This file is a part of AddressSanitizer, an address sanity checker.
111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//
12d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany// Intercept various libc functions.
131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===----------------------------------------------------------------------===//
141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_interceptors.h"
151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
161e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_allocator.h"
171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_interface.h"
181e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_internal.h"
19547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany#include "asan_mac.h"
201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_mapping.h"
211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_stack.h"
221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_stats.h"
234803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany#include "asan_thread_registry.h"
241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
254803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany#include <new>
26af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany#include <ctype.h>
271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
286f0452914ec76c786eb865983793bc03b00fc7b6Alexander Potapenko#ifndef _WIN32
296f0452914ec76c786eb865983793bc03b00fc7b6Alexander Potapenko#include <dlfcn.h>
302fc648c5d1775f13844d4459347e2b7328411e85Kostya Serebryany#include <pthread.h>
316f0452914ec76c786eb865983793bc03b00fc7b6Alexander Potapenko#endif
3235dd9d8f54f15f16be6c224e303bbf75d667f248Kostya Serebryany
33d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany// To replace weak system functions on Linux we just need to declare functions
34d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany// with same names in our library and then obtain the real function pointers
35d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany// using dlsym(). This is not so on Mac OS, where the two-level namespace makes
36d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany// our replacement functions invisible to other libraries. This may be overcomed
37d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany// using the DYLD_FORCE_FLAT_NAMESPACE, but some errors loading the shared
38d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany// libraries in Chromium were noticed when doing so.
39d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany// Instead we use mach_override, a handy framework for patching functions at
40d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany// runtime. To avoid possible name clashes, our replacement functions have
41d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany// the "wrap_" prefix on Mac.
42d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany//
43d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany// After interception, the calls to system functions will be substituted by
44d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany// calls to our interceptors. We store pointers to system function f()
45d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany// in __asan::real_f().
466f0452914ec76c786eb865983793bc03b00fc7b6Alexander Potapenko#if defined(__APPLE__)
47c8365231004cb1d956aba4164c89ea1398eadd6bAlexander Potapenko// Include the declarations of the original functions.
483389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov#include <signal.h>
49c8365231004cb1d956aba4164c89ea1398eadd6bAlexander Potapenko#include <string.h>
50c8365231004cb1d956aba4164c89ea1398eadd6bAlexander Potapenko#include <strings.h>
51c8365231004cb1d956aba4164c89ea1398eadd6bAlexander Potapenko
52d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany#include "mach_override/mach_override.h"
53d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany
543281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko#define OVERRIDE_FUNCTION(oldfunc, newfunc)                                   \
553281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko  do {CHECK(0 == __asan_mach_override_ptr_custom((void*)(oldfunc),            \
563281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko                                                 (void*)(newfunc),            \
573281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko                                                 (void**)&real_##oldfunc,     \
583281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko                                                 __asan_allocate_island,      \
593281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko                                                 __asan_deallocate_island));  \
604dd8ba8238b1b698953628affe6e5b2edf3b3e3fAlexey Samsonov  CHECK(real_##oldfunc != NULL);   } while (0)
61d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany
623281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko#define OVERRIDE_FUNCTION_IF_EXISTS(oldfunc, newfunc)               \
633281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko  do { __asan_mach_override_ptr_custom((void*)(oldfunc),            \
643281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko                                       (void*)(newfunc),            \
653281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko                                       (void**)&real_##oldfunc,     \
663281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko                                       __asan_allocate_island,      \
673281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko                                       __asan_deallocate_island);   \
683281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko  } while (0)
69d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany
70d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany#define INTERCEPT_FUNCTION(func)                                        \
71d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany  OVERRIDE_FUNCTION(func, WRAP(func))
72d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany
73d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany#define INTERCEPT_FUNCTION_IF_EXISTS(func)                              \
74d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany  OVERRIDE_FUNCTION_IF_EXISTS(func, WRAP(func))
75d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany
766f0452914ec76c786eb865983793bc03b00fc7b6Alexander Potapenko#elif defined(_WIN32)
776f0452914ec76c786eb865983793bc03b00fc7b6Alexander Potapenko// TODO(timurrrr): change these macros once we decide how to intercept
786f0452914ec76c786eb865983793bc03b00fc7b6Alexander Potapenko// functions on Windows.
796f0452914ec76c786eb865983793bc03b00fc7b6Alexander Potapenko#define INTERCEPT_FUNCTION(func)                                        \
806f0452914ec76c786eb865983793bc03b00fc7b6Alexander Potapenko  do { } while (0)
816f0452914ec76c786eb865983793bc03b00fc7b6Alexander Potapenko
826f0452914ec76c786eb865983793bc03b00fc7b6Alexander Potapenko#define INTERCEPT_FUNCTION_IF_EXISTS(func)                              \
836f0452914ec76c786eb865983793bc03b00fc7b6Alexander Potapenko  do { } while (0)
846f0452914ec76c786eb865983793bc03b00fc7b6Alexander Potapenko
85d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany#else  // __linux__
86d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany#define INTERCEPT_FUNCTION(func)                                        \
87d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany  CHECK((real_##func = (func##_f)dlsym(RTLD_NEXT, #func)));
88d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany
89d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany#define INTERCEPT_FUNCTION_IF_EXISTS(func)                              \
90d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany  do { real_##func = (func##_f)dlsym(RTLD_NEXT, #func); } while (0)
91d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany#endif
92d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany
931e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan {
941e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
951e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Instruments read/write access to a single byte in memory.
961e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// On error calls __asan_report_error, which aborts the program.
97adf2b036127d7e887392d9be5b02069b777ee280Alexey Samsonovstatic NOINLINE void AccessAddress(uintptr_t address, bool isWrite) {
981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (__asan_address_is_poisoned((void*)address)) {
991e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    GET_BP_PC_SP;
1001e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    __asan_report_error(pc, bp, sp, address, isWrite, /* access_size */ 1);
1011e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
1021e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
1031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
1041e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE,
1051e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// and ASAN_WRITE_RANGE as macro instead of function so
1061e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// that no extra frames are created, and stack trace contains
1071e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// relevant information only.
1081e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
1091e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Instruments read/write access to a memory range.
1101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// More complex implementation is possible, for now just
1111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// checking the first and the last byte of a range.
1121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#define ACCESS_MEMORY_RANGE(offset, size, isWrite) do { \
1131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (size > 0) { \
1141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    uintptr_t ptr = (uintptr_t)(offset); \
1151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    AccessAddress(ptr, isWrite); \
1161e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    AccessAddress(ptr + (size) - 1, isWrite); \
1171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  } \
118e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany} while (0)
1191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
1201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#define ASAN_READ_RANGE(offset, size) do { \
1211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  ACCESS_MEMORY_RANGE(offset, size, false); \
122e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany} while (0)
1231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
1241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#define ASAN_WRITE_RANGE(offset, size) do { \
1251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  ACCESS_MEMORY_RANGE(offset, size, true); \
126e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany} while (0)
1271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
1281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Behavior of functions like "memcpy" or "strcpy" is undefined
1291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// if memory intervals overlap. We report error in this case.
1301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Macro is used to avoid creation of new frames.
1310985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryanystatic inline bool RangesOverlap(const char *offset1, size_t length1,
1320985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany                                 const char *offset2, size_t length2) {
1330985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany  return !((offset1 + length1 <= offset2) || (offset2 + length2 <= offset1));
1341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
135c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany#define CHECK_RANGES_OVERLAP(name, _offset1, length1, _offset2, length2) do { \
1361e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  const char *offset1 = (const char*)_offset1; \
1371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  const char *offset2 = (const char*)_offset2; \
1380985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany  if (RangesOverlap(offset1, length1, offset2, length2)) { \
139c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany    Report("ERROR: AddressSanitizer %s-param-overlap: " \
1401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany           "memory ranges [%p,%p) and [%p, %p) overlap\n", \
141c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany           name, offset1, offset1 + length1, offset2, offset2 + length2); \
1421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    PRINT_CURRENT_STACK(); \
1431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ShowStatsAndAbort(); \
1441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  } \
145e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany} while (0)
1461e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
147e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany#define ENSURE_ASAN_INITED() do { \
148e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  CHECK(!asan_init_is_running); \
149e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  if (!asan_inited) { \
150e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany    __asan_init(); \
151e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  } \
152e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany} while (0)
1531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
1541e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanysize_t internal_strlen(const char *s) {
1551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  size_t i = 0;
1561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  while (s[i]) i++;
1571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return i;
1581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
1591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
1601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanysize_t internal_strnlen(const char *s, size_t maxlen) {
161f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov#ifndef __APPLE__
16209672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  if (REAL(strnlen) != NULL) {
16309672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(strnlen)(s, maxlen);
1641e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
165f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov#endif
1661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  size_t i = 0;
1671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  while (i < maxlen && s[i]) i++;
1681e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return i;
1691e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
1701e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
171de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryanyvoid* internal_memchr(const void* s, int c, size_t n) {
172de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany  const char* t = (char*)s;
173de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany  for (size_t i = 0; i < n; ++i, ++t)
174de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany    if (*t == c)
175de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany      return (void*)t;
176de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany  return NULL;
177de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany}
178de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany
179de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryanyint internal_memcmp(const void* s1, const void* s2, size_t n) {
180de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany  const char* t1 = (char*)s1;
181de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany  const char* t2 = (char*)s2;
182de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany  for (size_t i = 0; i < n; ++i, ++t1, ++t2)
183de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany    if (*t1 != *t2)
184de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany      return *t1 < *t2 ? -1 : 1;
185de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany  return 0;
186de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany}
187de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany
188a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryanychar *internal_strstr(const char *haystack, const char *needle) {
189a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany  // This is O(N^2), but we are not using it in hot places.
190a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany  size_t len1 = internal_strlen(haystack);
191a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany  size_t len2 = internal_strlen(needle);
192a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany  if (len1 < len2) return 0;
193a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany  for (size_t pos = 0; pos <= len1 - len2; pos++) {
194a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany    if (internal_memcmp(haystack + pos, needle, len2) == 0)
195a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany      return (char*)haystack + pos;
196a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany  }
197a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany  return 0;
198a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany}
199a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany
200a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryanychar *internal_strncat(char *dst, const char *src, size_t n) {
201a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany  size_t len = internal_strlen(dst);
202a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany  size_t i;
203a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany  for (i = 0; i < n && src[i]; i++)
204a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany    dst[len + i] = src[i];
205a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany  dst[len + i] = 0;
206a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany  return dst;
207a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany}
2081e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
209f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryanyint internal_strcmp(const char *s1, const char *s2) {
210f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryany  while (true) {
211f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryany    unsigned c1 = *s1;
212f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryany    unsigned c2 = *s2;
213f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryany    if (c1 != c2) return (c1 < c2) ? -1 : 1;
214f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryany    if (c1 == 0) break;
215f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryany    s1++;
216f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryany    s2++;
217f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryany  }
218f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryany  return 0;
219f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryany}
220f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryany
2211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}  // namespace __asan
2221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
2231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// ---------------------- Wrappers ---------------- {{{1
2241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyusing namespace __asan;  // NOLINT
2251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
2264803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany#define OPERATOR_NEW_BODY \
2274803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  GET_STACK_TRACE_HERE_FOR_MALLOC;\
2284803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  return asan_memalign(0, size, &stack);
2294803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
2304803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany#ifdef ANDROID
2314803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyvoid *operator new(size_t size) { OPERATOR_NEW_BODY; }
2324803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyvoid *operator new[](size_t size) { OPERATOR_NEW_BODY; }
2334803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany#else
2344803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyvoid *operator new(size_t size) throw(std::bad_alloc) { OPERATOR_NEW_BODY; }
2354803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyvoid *operator new[](size_t size) throw(std::bad_alloc) { OPERATOR_NEW_BODY; }
2364803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyvoid *operator new(size_t size, std::nothrow_t const&) throw()
2374803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany{ OPERATOR_NEW_BODY; }
2384803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyvoid *operator new[](size_t size, std::nothrow_t const&) throw()
2394803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany{ OPERATOR_NEW_BODY; }
2404803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany#endif
2414803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
2424803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany#define OPERATOR_DELETE_BODY \
2434803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  GET_STACK_TRACE_HERE_FOR_FREE(ptr);\
2444803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  asan_free(ptr, &stack);
2454803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
2464803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyvoid operator delete(void *ptr) throw() { OPERATOR_DELETE_BODY; }
2474803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyvoid operator delete[](void *ptr) throw() { OPERATOR_DELETE_BODY; }
2484803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyvoid operator delete(void *ptr, std::nothrow_t const&) throw()
2494803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany{ OPERATOR_DELETE_BODY; }
2504803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyvoid operator delete[](void *ptr, std::nothrow_t const&) throw()
2514803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany{ OPERATOR_DELETE_BODY;}
2524803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
2534803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanystatic void *asan_thread_start(void *arg) {
2544803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  AsanThread *t = (AsanThread*)arg;
2554803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  asanThreadRegistry().SetCurrent(t);
2564803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  return t->ThreadStart();
2574803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
2584803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
2596f0452914ec76c786eb865983793bc03b00fc7b6Alexander Potapenko#ifndef _WIN32
260f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(int, pthread_create, pthread_t *thread,
261f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov                                 const pthread_attr_t *attr,
262f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov                                 void *(*start_routine)(void*), void *arg) {
2639cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov  GET_STACK_TRACE_HERE(kStackTraceMax);
2644803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  int current_tid = asanThreadRegistry().GetCurrentTidOrMinusOne();
26555cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov  AsanThread *t = AsanThread::Create(current_tid, start_routine, arg, &stack);
26655cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov  asanThreadRegistry().RegisterThread(t);
26709672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(pthread_create)(thread, attr, asan_thread_start, t);
2684803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
2694803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
270f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void*, signal, int signum, void *handler) {
2714803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  if (!AsanInterceptsSignal(signum)) {
27209672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(signal)(signum, handler);
2734803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  }
2744803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  return NULL;
2754803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
2764803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
277f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(int, sigaction, int signum, const struct sigaction *act,
278f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov                            struct sigaction *oldact) {
2794803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  if (!AsanInterceptsSignal(signum)) {
28009672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(sigaction)(signum, act, oldact);
2814803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  }
2824803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  return 0;
2834803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
2846f0452914ec76c786eb865983793bc03b00fc7b6Alexander Potapenko#endif  // _WIN32
2854803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
2864803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
2874803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanystatic void UnpoisonStackFromHereToTop() {
2884803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  int local_stack;
2894803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  AsanThread *curr_thread = asanThreadRegistry().GetCurrent();
2904803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  CHECK(curr_thread);
2914803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  uintptr_t top = curr_thread->stack_top();
2924803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  uintptr_t bottom = ((uintptr_t)&local_stack - kPageSize) & ~(kPageSize-1);
2934803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  PoisonShadow(bottom, top - bottom, 0);
2944803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
2954803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
296f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, longjmp, void *env, int val) {
2974803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  UnpoisonStackFromHereToTop();
29809672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  REAL(longjmp)(env, val);
2994803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
3004803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
301f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, _longjmp, void *env, int val) {
3024803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  UnpoisonStackFromHereToTop();
30309672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  REAL(_longjmp)(env, val);
3044803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
3054803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
306f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, siglongjmp, void *env, int val) {
3074803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  UnpoisonStackFromHereToTop();
30809672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  REAL(siglongjmp)(env, val);
3094803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
3104803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
3113389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov#if ASAN_HAS_EXCEPTIONS == 1
3123389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov#ifdef __APPLE__
3134803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyextern "C" void __cxa_throw(void *a, void *b, void *c);
3143389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov#endif  // __APPLE__
3154803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
316f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
31709672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  CHECK(REAL(__cxa_throw));
3184803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  UnpoisonStackFromHereToTop();
31909672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  REAL(__cxa_throw)(a, b, c);
3204803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
3214803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany#endif
3224803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
3234803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany// intercept mlock and friends.
3244803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany// Since asan maps 16T of RAM, mlock is completely unfriendly to asan.
3254803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany// All functions return 0 (success).
3264803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanystatic void MlockIsUnsupported() {
3274803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  static bool printed = 0;
3284803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  if (printed) return;
3294803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  printed = true;
3304803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  Printf("INFO: AddressSanitizer ignores mlock/mlockall/munlock/munlockall\n");
3314803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
3323389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov
333f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonovextern "C" {
3343389b8ea81f51a28365a421b2646d594bac490f5Alexey SamsonovINTERCEPTOR_ATTRIBUTE
3354803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyint mlock(const void *addr, size_t len) {
3364803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  MlockIsUnsupported();
3374803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  return 0;
3384803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
3393389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov
3403389b8ea81f51a28365a421b2646d594bac490f5Alexey SamsonovINTERCEPTOR_ATTRIBUTE
3414803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyint munlock(const void *addr, size_t len) {
3424803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  MlockIsUnsupported();
3434803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  return 0;
3444803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
3453389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov
3463389b8ea81f51a28365a421b2646d594bac490f5Alexey SamsonovINTERCEPTOR_ATTRIBUTE
3474803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyint mlockall(int flags) {
3484803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  MlockIsUnsupported();
3494803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  return 0;
3504803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
3513389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov
3523389b8ea81f51a28365a421b2646d594bac490f5Alexey SamsonovINTERCEPTOR_ATTRIBUTE
3534803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyint munlockall(void) {
3544803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  MlockIsUnsupported();
3554803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  return 0;
3564803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
3574803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}  // extern "C"
3584803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
35952fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryanystatic inline int CharCmp(unsigned char c1, unsigned char c2) {
36052fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
36152fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany}
36252fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany
36352fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryanystatic inline int CharCaseCmp(unsigned char c1, unsigned char c2) {
36452fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  int c1_low = tolower(c1);
36552fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  int c2_low = tolower(c2);
36652fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  return c1_low - c2_low;
36752fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany}
36852fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany
369f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(int, memcmp, const void *a1, const void *a2, size_t size) {
37052fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  ENSURE_ASAN_INITED();
37152fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  unsigned char c1 = 0, c2 = 0;
37252fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  const unsigned char *s1 = (const unsigned char*)a1;
37352fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  const unsigned char *s2 = (const unsigned char*)a2;
37452fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  size_t i;
37552fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  for (i = 0; i < size; i++) {
37652fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany    c1 = s1[i];
37752fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany    c2 = s2[i];
37852fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany    if (c1 != c2) break;
37952fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  }
38052fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  ASAN_READ_RANGE(s1, Min(i + 1, size));
38152fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  ASAN_READ_RANGE(s2, Min(i + 1, size));
38252fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  return CharCmp(c1, c2);
38352fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany}
38452fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany
385f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void*, memcpy, void *to, const void *from, size_t size) {
3861e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // memcpy is called during __asan_init() from the internals
3871e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // of printf(...).
3881e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (asan_init_is_running) {
38909672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(memcpy)(to, from, size);
3901e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
391e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
3921e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (FLAG_replace_intrin) {
393c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany    if (to != from) {
394c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany      // We do not treat memcpy with to==from as a bug.
395c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany      // See http://llvm.org/bugs/show_bug.cgi?id=11763.
396c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany      CHECK_RANGES_OVERLAP("memcpy", to, size, from, size);
397c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany    }
3981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_WRITE_RANGE(from, size);
3991e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(to, size);
4001e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
40109672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(memcpy)(to, from, size);
4021e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
4031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
404f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void*, memmove, void *to, const void *from, size_t size) {
405e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
4061e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (FLAG_replace_intrin) {
4071e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_WRITE_RANGE(from, size);
4081e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(to, size);
4091e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
41009672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(memmove)(to, from, size);
4111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
4121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
413f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void*, memset, void *block, int c, size_t size) {
414e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  // memset is called inside INTERCEPT_FUNCTION on Mac.
415e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  if (asan_init_is_running) {
41609672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(memset)(block, c, size);
417e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  }
418e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
4191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (FLAG_replace_intrin) {
4201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_WRITE_RANGE(block, size);
4211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
42209672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(memset)(block, c, size);
4231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
4241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
425f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strchr, const char *str, int c) {
426e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
42709672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  char *result = REAL(strchr)(str, c);
4281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (FLAG_replace_str) {
42909672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    size_t bytes_read = (result ? result - str : REAL(strlen)(str)) + 1;
4301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(str, bytes_read);
4311e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
4321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return result;
4331e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
4341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
435adf2b036127d7e887392d9be5b02069b777ee280Alexey Samsonov#ifdef __linux__
436f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void*, index, const char *string, int c)
437adf2b036127d7e887392d9be5b02069b777ee280Alexey Samsonov  ALIAS(WRAPPER_NAME(strchr));
438f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov#else
439f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovDEFINE_REAL(void*, index, const char *string, int c);
440f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov#endif
441f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov
442f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(int, strcasecmp, const char *s1, const char *s2) {
443af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany  ENSURE_ASAN_INITED();
444af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany  unsigned char c1, c2;
445af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany  size_t i;
446af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany  for (i = 0; ; i++) {
447af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany    c1 = (unsigned char)s1[i];
448af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany    c2 = (unsigned char)s2[i];
449af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany    if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
450af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany  }
451af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany  ASAN_READ_RANGE(s1, i + 1);
452af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany  ASAN_READ_RANGE(s2, i + 1);
453af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany  return CharCaseCmp(c1, c2);
454af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany}
455af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany
456f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strcat, char *to, const char *from) {  // NOLINT
4570985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany  ENSURE_ASAN_INITED();
4580985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany  if (FLAG_replace_str) {
45909672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    size_t from_length = REAL(strlen)(from);
4600985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany    ASAN_READ_RANGE(from, from_length + 1);
4610985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany    if (from_length > 0) {
46209672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov      size_t to_length = REAL(strlen)(to);
4630985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany      ASAN_READ_RANGE(to, to_length);
4640985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany      ASAN_WRITE_RANGE(to + to_length, from_length + 1);
465c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany      CHECK_RANGES_OVERLAP("strcat", to, to_length + 1, from, from_length + 1);
4660985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany    }
4670985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany  }
46809672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(strcat)(to, from);  // NOLINT
4690985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany}
4700985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany
471f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(int, strcmp, const char *s1, const char *s2) {
472f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryany  if (!asan_inited) {
473f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryany    return internal_strcmp(s1, s2);
4741e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
4751e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  unsigned char c1, c2;
4761e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  size_t i;
4771e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  for (i = 0; ; i++) {
4781e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    c1 = (unsigned char)s1[i];
4791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    c2 = (unsigned char)s2[i];
4801e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    if (c1 != c2 || c1 == '\0') break;
4811e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
4821e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  ASAN_READ_RANGE(s1, i + 1);
4831e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  ASAN_READ_RANGE(s2, i + 1);
4841e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return CharCmp(c1, c2);
4851e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
4861e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
487f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strcpy, char *to, const char *from) {  // NOLINT
4881e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // strcpy is called from malloc_default_purgeable_zone()
4891e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // in __asan::ReplaceSystemAlloc() on Mac.
4901e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (asan_init_is_running) {
49109672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(strcpy)(to, from);  // NOLINT
4921e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
493e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
4941e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (FLAG_replace_str) {
49509672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    size_t from_size = REAL(strlen)(from) + 1;
496c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany    CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size);
4971e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(from, from_size);
4981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_WRITE_RANGE(to, from_size);
4991e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
50009672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(strcpy)(to, from);  // NOLINT
5011e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
5021e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
503f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strdup, const char *s) {
504e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
5051e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (FLAG_replace_str) {
50609672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    size_t length = REAL(strlen)(s);
5071e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(s, length + 1);
5081e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
50909672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(strdup)(s);
5101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
5111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
512f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(size_t, strlen, const char *s) {
5131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // strlen is called from malloc_default_purgeable_zone()
5141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // in __asan::ReplaceSystemAlloc() on Mac.
5151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (asan_init_is_running) {
51609672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(strlen)(s);
5171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
518e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
51909672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  size_t length = REAL(strlen)(s);
5201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (FLAG_replace_str) {
5211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(s, length + 1);
5221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
5231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return length;
5241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
5251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
526f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, size_t n) {
527af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany  ENSURE_ASAN_INITED();
528af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany  unsigned char c1 = 0, c2 = 0;
529af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany  size_t i;
530f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov  for (i = 0; i < n; i++) {
531af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany    c1 = (unsigned char)s1[i];
532af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany    c2 = (unsigned char)s2[i];
533af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany    if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
534af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany  }
535f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov  ASAN_READ_RANGE(s1, Min(i + 1, n));
536f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov  ASAN_READ_RANGE(s2, Min(i + 1, n));
537af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany  return CharCaseCmp(c1, c2);
538af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany}
539af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany
540f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(int, strncmp, const char *s1, const char *s2, size_t size) {
5411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // strncmp is called from malloc_default_purgeable_zone()
5421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // in __asan::ReplaceSystemAlloc() on Mac.
5431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (asan_init_is_running) {
54409672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(strncmp)(s1, s2, size);
5451e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
5461e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  unsigned char c1 = 0, c2 = 0;
5471e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  size_t i;
5481e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  for (i = 0; i < size; i++) {
5491e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    c1 = (unsigned char)s1[i];
5501e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    c2 = (unsigned char)s2[i];
5511e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    if (c1 != c2 || c1 == '\0') break;
5521e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
5532d8b3bdb112ebb8ed3f15ee41d4cebcd683b41b0Kostya Serebryany  ASAN_READ_RANGE(s1, Min(i + 1, size));
5542d8b3bdb112ebb8ed3f15ee41d4cebcd683b41b0Kostya Serebryany  ASAN_READ_RANGE(s2, Min(i + 1, size));
5551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return CharCmp(c1, c2);
5561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
5571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
558f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strncpy, char *to, const char *from, size_t size) {
559e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
5601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (FLAG_replace_str) {
5612d8b3bdb112ebb8ed3f15ee41d4cebcd683b41b0Kostya Serebryany    size_t from_size = Min(size, internal_strnlen(from, size) + 1);
562c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany    CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size);
5631e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(from, from_size);
5641e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_WRITE_RANGE(to, size);
5651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
56609672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(strncpy)(to, from, size);
5671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
5681e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
5691e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#ifndef __APPLE__
570f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(size_t, strnlen, const char *s, size_t maxlen) {
571e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
57209672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  size_t length = REAL(strnlen)(s, maxlen);
5731e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (FLAG_replace_str) {
5742d8b3bdb112ebb8ed3f15ee41d4cebcd683b41b0Kostya Serebryany    ASAN_READ_RANGE(s, Min(length + 1, maxlen));
5751e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
5761e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return length;
5771e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
578d66a8d8f56c66c9749b6d75c61870a121d4d9307Kostya Serebryany#endif
579547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany
580547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany// ---------------------- InitializeAsanInterceptors ---------------- {{{1
581547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryanynamespace __asan {
582547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryanyvoid InitializeAsanInterceptors() {
583547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany#ifndef __APPLE__
584547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  INTERCEPT_FUNCTION(index);
585547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany#else
586547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  OVERRIDE_FUNCTION(index, WRAP(strchr));
587547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany#endif
588547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  INTERCEPT_FUNCTION(memcmp);
589547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  INTERCEPT_FUNCTION(memmove);
590573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko#ifdef __APPLE__
591573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko  // Wrap memcpy() on OS X 10.6 only, because on 10.7 memcpy() and memmove()
592573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko  // are resolved into memmove$VARIANT$sse42.
593573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko  // See also http://code.google.com/p/address-sanitizer/issues/detail?id=34.
594573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko  // TODO(glider): need to check dynamically that memcpy() and memmove() are
595573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko  // actually the same function.
596573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko  if (GetMacosVersion() == MACOS_VERSION_SNOW_LEOPARD) {
597573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko    INTERCEPT_FUNCTION(memcpy);
598573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko  } else {
59909672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    REAL(memcpy) = REAL(memmove);
600573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko  }
601573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko#else
602573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko  // Always wrap memcpy() on non-Darwin platforms.
603573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko  INTERCEPT_FUNCTION(memcpy);
604573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko#endif
605547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  INTERCEPT_FUNCTION(memset);
606547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  INTERCEPT_FUNCTION(strcasecmp);
607547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  INTERCEPT_FUNCTION(strcat);  // NOLINT
608547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  INTERCEPT_FUNCTION(strchr);
609547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  INTERCEPT_FUNCTION(strcmp);
610547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  INTERCEPT_FUNCTION(strcpy);  // NOLINT
611547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  INTERCEPT_FUNCTION(strdup);
612547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  INTERCEPT_FUNCTION(strlen);
613547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  INTERCEPT_FUNCTION(strncasecmp);
614547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  INTERCEPT_FUNCTION(strncmp);
615547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  INTERCEPT_FUNCTION(strncpy);
616547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany
617547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  INTERCEPT_FUNCTION(sigaction);
618547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  INTERCEPT_FUNCTION(signal);
619547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  INTERCEPT_FUNCTION(longjmp);
620547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  INTERCEPT_FUNCTION(_longjmp);
621547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  INTERCEPT_FUNCTION_IF_EXISTS(__cxa_throw);
622547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  INTERCEPT_FUNCTION(pthread_create);
623547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany
624547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany#ifdef __APPLE__
625547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  INTERCEPT_FUNCTION(dispatch_async_f);
626547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  INTERCEPT_FUNCTION(dispatch_sync_f);
627547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  INTERCEPT_FUNCTION(dispatch_after_f);
628547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  INTERCEPT_FUNCTION(dispatch_barrier_async_f);
629547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  INTERCEPT_FUNCTION(dispatch_group_async_f);
630547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  // We don't need to intercept pthread_workqueue_additem_np() to support the
631547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  // libdispatch API, but it helps us to debug the unsupported functions. Let's
632547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  // intercept it only during verbose runs.
633547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  if (FLAG_v >= 2) {
634547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany    INTERCEPT_FUNCTION(pthread_workqueue_additem_np);
635547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  }
636431e51782d62d1257348e41e24da6b544fe70507Alexander Potapenko  // Normally CFStringCreateCopy should not copy constant CF strings.
637431e51782d62d1257348e41e24da6b544fe70507Alexander Potapenko  // Replacing the default CFAllocator causes constant strings to be copied
638431e51782d62d1257348e41e24da6b544fe70507Alexander Potapenko  // rather than just returned, which leads to bugs in big applications like
639431e51782d62d1257348e41e24da6b544fe70507Alexander Potapenko  // Chromium and WebKit, see
640431e51782d62d1257348e41e24da6b544fe70507Alexander Potapenko  // http://code.google.com/p/address-sanitizer/issues/detail?id=10
641431e51782d62d1257348e41e24da6b544fe70507Alexander Potapenko  // Until this problem is fixed we need to check that the string is
642431e51782d62d1257348e41e24da6b544fe70507Alexander Potapenko  // non-constant before calling CFStringCreateCopy.
643431e51782d62d1257348e41e24da6b544fe70507Alexander Potapenko  INTERCEPT_FUNCTION(CFStringCreateCopy);
644547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany#else
645547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  // On Darwin siglongjmp tailcalls longjmp, so we don't want to intercept it
646547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  // there.
647547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  INTERCEPT_FUNCTION(siglongjmp);
648547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany#endif
649547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany
650547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany#ifndef __APPLE__
651547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  INTERCEPT_FUNCTION(strnlen);
652547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany#endif
653547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  if (FLAG_v > 0) {
654547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany    Printf("AddressSanitizer: libc interceptors initialized\n");
655547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  }
656547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany}
657547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany
658547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany}  // namespace __asan
659