asan_interceptors.cc revision a4898423f0f69d9f7f96631e6384695b0c54d9a9
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"
191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_mapping.h"
201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_stack.h"
211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_stats.h"
224803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany#include "asan_thread_registry.h"
235b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov#include "interception/interception.h"
241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
254803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany#include <new>
261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
274e7abdcc8ed92a56561ed34f36295c6d01204e5dAlexey Samsonov// Use extern declarations of intercepted functions on Mac and Windows
284e7abdcc8ed92a56561ed34f36295c6d01204e5dAlexey Samsonov// to avoid including system headers.
294e7abdcc8ed92a56561ed34f36295c6d01204e5dAlexey Samsonov#if defined(__APPLE__) || (defined(_WIN32) && !defined(_DLL))
306ebea222e306fbe53aab78d7781e5ac19be46b5dAlexey Samsonovextern "C" {
3173fe35fa6b4c437c9a723eb7bbad4863c7edbe1eAlexey Samsonov// signal.h
324e7abdcc8ed92a56561ed34f36295c6d01204e5dAlexey Samsonov# if !defined(_WIN32)
3373fe35fa6b4c437c9a723eb7bbad4863c7edbe1eAlexey Samsonovstruct sigaction;
3473fe35fa6b4c437c9a723eb7bbad4863c7edbe1eAlexey Samsonovint sigaction(int sig, const struct sigaction *act,
3573fe35fa6b4c437c9a723eb7bbad4863c7edbe1eAlexey Samsonov              struct sigaction *oldact);
3673fe35fa6b4c437c9a723eb7bbad4863c7edbe1eAlexey Samsonovvoid *signal(int signum, void *handler);
374e7abdcc8ed92a56561ed34f36295c6d01204e5dAlexey Samsonov# endif
386ebea222e306fbe53aab78d7781e5ac19be46b5dAlexey Samsonov
394e7abdcc8ed92a56561ed34f36295c6d01204e5dAlexey Samsonov// setjmp.h
404e7abdcc8ed92a56561ed34f36295c6d01204e5dAlexey Samsonovvoid longjmp(void* env, int value);
414e7abdcc8ed92a56561ed34f36295c6d01204e5dAlexey Samsonov# if !defined(_WIN32)
424e7abdcc8ed92a56561ed34f36295c6d01204e5dAlexey Samsonovvoid _longjmp(void *env, int value);
434e7abdcc8ed92a56561ed34f36295c6d01204e5dAlexey Samsonov# endif
442716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanov
454e7abdcc8ed92a56561ed34f36295c6d01204e5dAlexey Samsonov// string.h / strings.h
464e7abdcc8ed92a56561ed34f36295c6d01204e5dAlexey Samsonovint memcmp(const void *a1, const void *a2, size_t size);
474e7abdcc8ed92a56561ed34f36295c6d01204e5dAlexey Samsonovvoid* memmove(void *to, const void *from, size_t size);
484e7abdcc8ed92a56561ed34f36295c6d01204e5dAlexey Samsonovvoid* memcpy(void *to, const void *from, size_t size);
494e7abdcc8ed92a56561ed34f36295c6d01204e5dAlexey Samsonovvoid* memset(void *block, int c, size_t size);
504e7abdcc8ed92a56561ed34f36295c6d01204e5dAlexey Samsonov# if defined(__APPLE__)
514e7abdcc8ed92a56561ed34f36295c6d01204e5dAlexey Samsonovchar* strchr(const char *str, int c);
5256e25249493ff0eeb20d5ab9b2ffe635a7b63ac5Alexey Samsonovchar* index(const char *string, int c);
534e7abdcc8ed92a56561ed34f36295c6d01204e5dAlexey Samsonov# elif defined(_WIN32)
542716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanovchar* strchr(const char *s, char c);
554e7abdcc8ed92a56561ed34f36295c6d01204e5dAlexey Samsonov# endif
564e7abdcc8ed92a56561ed34f36295c6d01204e5dAlexey Samsonovchar* strcat(char *to, const char* from);  // NOLINT
574e7abdcc8ed92a56561ed34f36295c6d01204e5dAlexey Samsonovchar* strcpy(char *to, const char* from);  // NOLINT
584e7abdcc8ed92a56561ed34f36295c6d01204e5dAlexey Samsonovchar* strncpy(char *to, const char* from, size_t size);
592716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanovint strcmp(const char *s1, const char* s2);
604e7abdcc8ed92a56561ed34f36295c6d01204e5dAlexey Samsonovint strncmp(const char *s1, const char* s2, size_t size);
6156e25249493ff0eeb20d5ab9b2ffe635a7b63ac5Alexey Samsonov# if !defined(_WIN32)
6256e25249493ff0eeb20d5ab9b2ffe635a7b63ac5Alexey Samsonovint strcasecmp(const char *s1, const char *s2);
6356e25249493ff0eeb20d5ab9b2ffe635a7b63ac5Alexey Samsonovint strncasecmp(const char *s1, const char *s2, size_t n);
6456e25249493ff0eeb20d5ab9b2ffe635a7b63ac5Alexey Samsonovchar* strdup(const char *s);
6556e25249493ff0eeb20d5ab9b2ffe635a7b63ac5Alexey Samsonov# endif
6656e25249493ff0eeb20d5ab9b2ffe635a7b63ac5Alexey Samsonovsize_t strlen(const char *s);
674e7abdcc8ed92a56561ed34f36295c6d01204e5dAlexey Samsonov# if !defined(__APPLE__)
684e7abdcc8ed92a56561ed34f36295c6d01204e5dAlexey Samsonovsize_t strnlen(const char *s, size_t maxlen);
694e7abdcc8ed92a56561ed34f36295c6d01204e5dAlexey Samsonov# endif
702716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanov
714e7abdcc8ed92a56561ed34f36295c6d01204e5dAlexey Samsonov// Windows threads.
724e7abdcc8ed92a56561ed34f36295c6d01204e5dAlexey Samsonov# if defined(_WIN32)
732716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanov__declspec(dllimport)
742716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanovvoid* __stdcall CreateThread(void *sec, size_t st, void* start,
752716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanov                             void *arg, DWORD fl, DWORD *id);
764e7abdcc8ed92a56561ed34f36295c6d01204e5dAlexey Samsonov# endif
77a4898423f0f69d9f7f96631e6384695b0c54d9a9Alexey Samsonov
78a4898423f0f69d9f7f96631e6384695b0c54d9a9Alexey Samsonov// Posix threads.
79a4898423f0f69d9f7f96631e6384695b0c54d9a9Alexey Samsonov# if !defined(_WIN32)
80a4898423f0f69d9f7f96631e6384695b0c54d9a9Alexey Samsonovint pthread_create(void *thread, void *attr, void *(*start_routine)(void*),
81a4898423f0f69d9f7f96631e6384695b0c54d9a9Alexey Samsonov                   void *arg);
82a4898423f0f69d9f7f96631e6384695b0c54d9a9Alexey Samsonov# endif
832716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanov}  // extern "C"
842716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanov#endif
852716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanov
861e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan {
871e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
881e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Instruments read/write access to a single byte in memory.
891e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// On error calls __asan_report_error, which aborts the program.
909f311bb0919d86ab3df2810dc0b81b70a87677e3Kostya Serebryany#define ACCESS_ADDRESS(address, isWrite)   do {         \
919f311bb0919d86ab3df2810dc0b81b70a87677e3Kostya Serebryany  if (AddressIsPoisoned(address)) {                     \
929f311bb0919d86ab3df2810dc0b81b70a87677e3Kostya Serebryany    GET_CURRENT_PC_BP_SP;                               \
939f311bb0919d86ab3df2810dc0b81b70a87677e3Kostya Serebryany    __asan_report_error(pc, bp, sp, address, isWrite, /* access_size */ 1); \
949f311bb0919d86ab3df2810dc0b81b70a87677e3Kostya Serebryany  } \
959f311bb0919d86ab3df2810dc0b81b70a87677e3Kostya Serebryany} while (0)
961e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
971e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE,
981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// and ASAN_WRITE_RANGE as macro instead of function so
991e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// that no extra frames are created, and stack trace contains
1001e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// relevant information only.
1011e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
1021e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Instruments read/write access to a memory range.
1031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// More complex implementation is possible, for now just
1041e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// checking the first and the last byte of a range.
1051e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#define ACCESS_MEMORY_RANGE(offset, size, isWrite) do { \
1061e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (size > 0) { \
1071e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    uintptr_t ptr = (uintptr_t)(offset); \
1089f311bb0919d86ab3df2810dc0b81b70a87677e3Kostya Serebryany    ACCESS_ADDRESS(ptr, isWrite); \
1099f311bb0919d86ab3df2810dc0b81b70a87677e3Kostya Serebryany    ACCESS_ADDRESS(ptr + (size) - 1, isWrite); \
1101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  } \
111e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany} while (0)
1121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
1131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#define ASAN_READ_RANGE(offset, size) do { \
1141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  ACCESS_MEMORY_RANGE(offset, size, false); \
115e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany} while (0)
1161e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
1171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#define ASAN_WRITE_RANGE(offset, size) do { \
1181e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  ACCESS_MEMORY_RANGE(offset, size, true); \
119e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany} while (0)
1201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
1211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Behavior of functions like "memcpy" or "strcpy" is undefined
1221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// if memory intervals overlap. We report error in this case.
1231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Macro is used to avoid creation of new frames.
1240985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryanystatic inline bool RangesOverlap(const char *offset1, size_t length1,
1250985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany                                 const char *offset2, size_t length2) {
1260985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany  return !((offset1 + length1 <= offset2) || (offset2 + length2 <= offset1));
1271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
128c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany#define CHECK_RANGES_OVERLAP(name, _offset1, length1, _offset2, length2) do { \
1291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  const char *offset1 = (const char*)_offset1; \
1301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  const char *offset2 = (const char*)_offset2; \
1310985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany  if (RangesOverlap(offset1, length1, offset2, length2)) { \
132c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany    Report("ERROR: AddressSanitizer %s-param-overlap: " \
1331e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany           "memory ranges [%p,%p) and [%p, %p) overlap\n", \
134c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany           name, offset1, offset1 + length1, offset2, offset2 + length2); \
1351e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    PRINT_CURRENT_STACK(); \
1361e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ShowStatsAndAbort(); \
1371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  } \
138e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany} while (0)
1391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
140e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany#define ENSURE_ASAN_INITED() do { \
141e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  CHECK(!asan_init_is_running); \
142e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  if (!asan_inited) { \
143e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany    __asan_init(); \
144e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  } \
145e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany} while (0)
1461e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
1478898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonovstatic inline bool IsSpace(int c) {
1488898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov  return (c == ' ') || (c == '\n') || (c == '\t') ||
1498898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov         (c == '\f') || (c == '\r') || (c == '\v');
1508898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov}
1518898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov
1528898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonovstatic inline bool IsDigit(int c) {
1538898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov  return (c >= '0') && (c <= '9');
1548898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov}
1558898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov
1568898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonovstatic inline int ToLower(int c) {
1578898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov  return (c >= 'A' && c <= 'Z') ? (c + 'a' - 'A') : c;
1588898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov}
1598898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov
1608898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov// ---------------------- Internal string functions ---------------- {{{1
1618898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov
1628898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonovint64_t internal_simple_strtoll(const char *nptr, char **endptr, int base) {
1638898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov  CHECK(base == 10);
1648898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov  while (IsSpace(*nptr)) nptr++;
1658898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov  int sgn = 1;
1668898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov  uint64_t res = 0;
1678898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov  bool have_digits = false;
1688898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov  char *old_nptr = (char*)nptr;
1698898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov  if (*nptr == '+') {
1708898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov    sgn = 1;
1718898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov    nptr++;
1728898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov  } else if (*nptr == '-') {
1738898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov    sgn = -1;
1748898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov    nptr++;
1758898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov  }
1768898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov  while (IsDigit(*nptr)) {
177e4092f6780e107797bc6f2c77219a7256f7b04f3Alexey Samsonov    res = (res <= UINT64_MAX / 10) ? res * 10 : UINT64_MAX;
1788898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov    int digit = ((*nptr) - '0');
179e4092f6780e107797bc6f2c77219a7256f7b04f3Alexey Samsonov    res = (res <= UINT64_MAX - digit) ? res + digit : UINT64_MAX;
1808898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov    have_digits = true;
1818898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov    nptr++;
1828898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov  }
1838898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov  if (endptr != NULL) {
1848898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov    *endptr = (have_digits) ? (char*)nptr : old_nptr;
1858898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov  }
1868898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov  if (sgn > 0) {
187e4092f6780e107797bc6f2c77219a7256f7b04f3Alexey Samsonov    return (int64_t)(Min((uint64_t)INT64_MAX, res));
1888898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov  } else {
189e4092f6780e107797bc6f2c77219a7256f7b04f3Alexey Samsonov    return (res > INT64_MAX) ? INT64_MIN : ((int64_t)res * -1);
1908898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov  }
1918898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov}
1928898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov
1938898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonovint64_t internal_atoll(const char *nptr) {
1948898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov  return internal_simple_strtoll(nptr, (char**)NULL, 10);
1958898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov}
1968898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov
1971e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanysize_t internal_strlen(const char *s) {
1981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  size_t i = 0;
1991e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  while (s[i]) i++;
2001e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return i;
2011e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
2021e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
2031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanysize_t internal_strnlen(const char *s, size_t maxlen) {
204f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov#ifndef __APPLE__
20509672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  if (REAL(strnlen) != NULL) {
20609672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(strnlen)(s, maxlen);
2071e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
208f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov#endif
2091e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  size_t i = 0;
2101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  while (i < maxlen && s[i]) i++;
2111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return i;
2121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
2131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
2145362717f2c121384778429b5cf34712925ad4a9bTimur Iskhodzhanovchar* internal_strchr(const char *s, int c) {
2155362717f2c121384778429b5cf34712925ad4a9bTimur Iskhodzhanov  while (true) {
2165362717f2c121384778429b5cf34712925ad4a9bTimur Iskhodzhanov    if (*s == (char)c)
2175362717f2c121384778429b5cf34712925ad4a9bTimur Iskhodzhanov      return (char*)s;
2185362717f2c121384778429b5cf34712925ad4a9bTimur Iskhodzhanov    if (*s == 0)
2195362717f2c121384778429b5cf34712925ad4a9bTimur Iskhodzhanov      return NULL;
2205362717f2c121384778429b5cf34712925ad4a9bTimur Iskhodzhanov    s++;
2215362717f2c121384778429b5cf34712925ad4a9bTimur Iskhodzhanov  }
2225362717f2c121384778429b5cf34712925ad4a9bTimur Iskhodzhanov}
2235362717f2c121384778429b5cf34712925ad4a9bTimur Iskhodzhanov
224de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryanyvoid* internal_memchr(const void* s, int c, size_t n) {
225de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany  const char* t = (char*)s;
226de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany  for (size_t i = 0; i < n; ++i, ++t)
227de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany    if (*t == c)
228de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany      return (void*)t;
229de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany  return NULL;
230de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany}
231de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany
232de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryanyint internal_memcmp(const void* s1, const void* s2, size_t n) {
233de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany  const char* t1 = (char*)s1;
234de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany  const char* t2 = (char*)s2;
235de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany  for (size_t i = 0; i < n; ++i, ++t1, ++t2)
236de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany    if (*t1 != *t2)
237de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany      return *t1 < *t2 ? -1 : 1;
238de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany  return 0;
239de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany}
240de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany
241a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryanychar *internal_strstr(const char *haystack, const char *needle) {
242a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany  // This is O(N^2), but we are not using it in hot places.
243a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany  size_t len1 = internal_strlen(haystack);
244a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany  size_t len2 = internal_strlen(needle);
245a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany  if (len1 < len2) return 0;
246a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany  for (size_t pos = 0; pos <= len1 - len2; pos++) {
247a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany    if (internal_memcmp(haystack + pos, needle, len2) == 0)
248a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany      return (char*)haystack + pos;
249a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany  }
250a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany  return 0;
251a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany}
252a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany
253a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryanychar *internal_strncat(char *dst, const char *src, size_t n) {
254a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany  size_t len = internal_strlen(dst);
255a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany  size_t i;
256a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany  for (i = 0; i < n && src[i]; i++)
257a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany    dst[len + i] = src[i];
258a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany  dst[len + i] = 0;
259a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany  return dst;
260a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany}
2611e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
262f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryanyint internal_strcmp(const char *s1, const char *s2) {
263f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryany  while (true) {
264f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryany    unsigned c1 = *s1;
265f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryany    unsigned c2 = *s2;
266f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryany    if (c1 != c2) return (c1 < c2) ? -1 : 1;
267f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryany    if (c1 == 0) break;
268f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryany    s1++;
269f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryany    s2++;
270f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryany  }
271f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryany  return 0;
272f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryany}
273f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryany
2743fe913558354f76707e2c5584559521399854b79Alexander Potapenkochar *internal_strncpy(char *dst, const char *src, size_t n) {
2753fe913558354f76707e2c5584559521399854b79Alexander Potapenko  size_t i;
2763fe913558354f76707e2c5584559521399854b79Alexander Potapenko  for (i = 0; i < n && src[i]; i++)
2773fe913558354f76707e2c5584559521399854b79Alexander Potapenko    dst[i] = src[i];
2783fe913558354f76707e2c5584559521399854b79Alexander Potapenko  return dst;
2793fe913558354f76707e2c5584559521399854b79Alexander Potapenko}
2803fe913558354f76707e2c5584559521399854b79Alexander Potapenko
2811e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}  // namespace __asan
2821e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
2831e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// ---------------------- Wrappers ---------------- {{{1
2841e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyusing namespace __asan;  // NOLINT
2851e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
2864803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany#define OPERATOR_NEW_BODY \
2874803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  GET_STACK_TRACE_HERE_FOR_MALLOC;\
2884803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  return asan_memalign(0, size, &stack);
2894803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
2904803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany#ifdef ANDROID
2914803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyvoid *operator new(size_t size) { OPERATOR_NEW_BODY; }
2924803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyvoid *operator new[](size_t size) { OPERATOR_NEW_BODY; }
2934803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany#else
2944803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyvoid *operator new(size_t size) throw(std::bad_alloc) { OPERATOR_NEW_BODY; }
2954803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyvoid *operator new[](size_t size) throw(std::bad_alloc) { OPERATOR_NEW_BODY; }
2964803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyvoid *operator new(size_t size, std::nothrow_t const&) throw()
2974803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany{ OPERATOR_NEW_BODY; }
2984803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyvoid *operator new[](size_t size, std::nothrow_t const&) throw()
2994803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany{ OPERATOR_NEW_BODY; }
3004803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany#endif
3014803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
3024803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany#define OPERATOR_DELETE_BODY \
3034803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  GET_STACK_TRACE_HERE_FOR_FREE(ptr);\
3044803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  asan_free(ptr, &stack);
3054803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
3064803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyvoid operator delete(void *ptr) throw() { OPERATOR_DELETE_BODY; }
3074803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyvoid operator delete[](void *ptr) throw() { OPERATOR_DELETE_BODY; }
3084803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyvoid operator delete(void *ptr, std::nothrow_t const&) throw()
3094803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany{ OPERATOR_DELETE_BODY; }
3104803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyvoid operator delete[](void *ptr, std::nothrow_t const&) throw()
3114803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany{ OPERATOR_DELETE_BODY;}
3124803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
313600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanovstatic thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
3144803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  AsanThread *t = (AsanThread*)arg;
3154803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  asanThreadRegistry().SetCurrent(t);
3164803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  return t->ThreadStart();
3174803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
3184803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
3196f0452914ec76c786eb865983793bc03b00fc7b6Alexander Potapenko#ifndef _WIN32
320b8ef925563f8dde5be837c4b0569082867c5f14cEvgeniy StepanovINTERCEPTOR(int, pthread_create, void *thread,
321b8ef925563f8dde5be837c4b0569082867c5f14cEvgeniy Stepanov    void *attr, void *(*start_routine)(void*), void *arg) {
3229cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov  GET_STACK_TRACE_HERE(kStackTraceMax);
3234803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  int current_tid = asanThreadRegistry().GetCurrentTidOrMinusOne();
32455cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov  AsanThread *t = AsanThread::Create(current_tid, start_routine, arg, &stack);
32555cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov  asanThreadRegistry().RegisterThread(t);
32609672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(pthread_create)(thread, attr, asan_thread_start, t);
3274803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
328919c24787a655597bdcf367e26c9dd1504e9f463Evgeniy Stepanov#endif  // !_WIN32
3294803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
330919c24787a655597bdcf367e26c9dd1504e9f463Evgeniy Stepanov#if !defined(ANDROID) && !defined(_WIN32)
331f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void*, signal, int signum, void *handler) {
3324803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  if (!AsanInterceptsSignal(signum)) {
33309672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(signal)(signum, handler);
3344803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  }
3354803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  return NULL;
3364803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
3374803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
338da13ba833b046553f50b54538e4828287ddbf5c0Alexey SamsonovINTERCEPTOR(int, sigaction, int signum, const struct sigaction *act,
339da13ba833b046553f50b54538e4828287ddbf5c0Alexey Samsonov                            struct sigaction *oldact) {
3404803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  if (!AsanInterceptsSignal(signum)) {
34109672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(sigaction)(signum, act, oldact);
3424803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  }
3434803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  return 0;
3444803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
345919c24787a655597bdcf367e26c9dd1504e9f463Evgeniy Stepanov#endif  // !ANDROID && !_WIN32
3464803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
347f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, longjmp, void *env, int val) {
348f54b1f9b73a6855d77ee270c282bd61407fa73a0Kostya Serebryany  __asan_handle_no_return();
34909672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  REAL(longjmp)(env, val);
3504803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
3514803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
35207bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov#if !defined(_WIN32)
353f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, _longjmp, void *env, int val) {
354f54b1f9b73a6855d77ee270c282bd61407fa73a0Kostya Serebryany  __asan_handle_no_return();
35509672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  REAL(_longjmp)(env, val);
3564803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
3574803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
358f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, siglongjmp, void *env, int val) {
359f54b1f9b73a6855d77ee270c282bd61407fa73a0Kostya Serebryany  __asan_handle_no_return();
36009672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  REAL(siglongjmp)(env, val);
3614803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
36207bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov#endif
3634803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
3643389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov#if ASAN_HAS_EXCEPTIONS == 1
3653389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov#ifdef __APPLE__
3664803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyextern "C" void __cxa_throw(void *a, void *b, void *c);
3673389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov#endif  // __APPLE__
3684803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
369f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
37009672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  CHECK(REAL(__cxa_throw));
371f54b1f9b73a6855d77ee270c282bd61407fa73a0Kostya Serebryany  __asan_handle_no_return();
37209672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  REAL(__cxa_throw)(a, b, c);
3734803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
3744803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany#endif
3754803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
3764803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany// intercept mlock and friends.
3774803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany// Since asan maps 16T of RAM, mlock is completely unfriendly to asan.
3784803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany// All functions return 0 (success).
3794803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanystatic void MlockIsUnsupported() {
3804803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  static bool printed = 0;
3814803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  if (printed) return;
3824803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  printed = true;
3834803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  Printf("INFO: AddressSanitizer ignores mlock/mlockall/munlock/munlockall\n");
3844803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
3853389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov
386f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonovextern "C" {
3873389b8ea81f51a28365a421b2646d594bac490f5Alexey SamsonovINTERCEPTOR_ATTRIBUTE
3884803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyint mlock(const void *addr, size_t len) {
3894803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  MlockIsUnsupported();
3904803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  return 0;
3914803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
3923389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov
3933389b8ea81f51a28365a421b2646d594bac490f5Alexey SamsonovINTERCEPTOR_ATTRIBUTE
3944803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyint munlock(const void *addr, size_t len) {
3954803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  MlockIsUnsupported();
3964803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  return 0;
3974803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
3983389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov
3993389b8ea81f51a28365a421b2646d594bac490f5Alexey SamsonovINTERCEPTOR_ATTRIBUTE
4004803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyint mlockall(int flags) {
4014803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  MlockIsUnsupported();
4024803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  return 0;
4034803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
4043389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov
4053389b8ea81f51a28365a421b2646d594bac490f5Alexey SamsonovINTERCEPTOR_ATTRIBUTE
4064803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyint munlockall(void) {
4074803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  MlockIsUnsupported();
4084803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany  return 0;
4094803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}
4104803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany}  // extern "C"
4114803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany
41252fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryanystatic inline int CharCmp(unsigned char c1, unsigned char c2) {
41352fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
41452fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany}
41552fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany
41652fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryanystatic inline int CharCaseCmp(unsigned char c1, unsigned char c2) {
4178898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov  int c1_low = ToLower(c1);
4188898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov  int c2_low = ToLower(c2);
41952fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  return c1_low - c2_low;
42052fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany}
42152fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany
422f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(int, memcmp, const void *a1, const void *a2, size_t size) {
42352fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  ENSURE_ASAN_INITED();
42452fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  unsigned char c1 = 0, c2 = 0;
42552fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  const unsigned char *s1 = (const unsigned char*)a1;
42652fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  const unsigned char *s2 = (const unsigned char*)a2;
42752fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  size_t i;
42852fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  for (i = 0; i < size; i++) {
42952fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany    c1 = s1[i];
43052fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany    c2 = s2[i];
43152fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany    if (c1 != c2) break;
43252fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  }
43352fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  ASAN_READ_RANGE(s1, Min(i + 1, size));
43452fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  ASAN_READ_RANGE(s2, Min(i + 1, size));
43552fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany  return CharCmp(c1, c2);
43652fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany}
43752fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany
438f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void*, memcpy, void *to, const void *from, size_t size) {
4391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // memcpy is called during __asan_init() from the internals
4401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // of printf(...).
4411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (asan_init_is_running) {
44209672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(memcpy)(to, from, size);
4431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
444e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
4451e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (FLAG_replace_intrin) {
446c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany    if (to != from) {
447c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany      // We do not treat memcpy with to==from as a bug.
448c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany      // See http://llvm.org/bugs/show_bug.cgi?id=11763.
449c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany      CHECK_RANGES_OVERLAP("memcpy", to, size, from, size);
450c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany    }
4511e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_WRITE_RANGE(from, size);
4521e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(to, size);
4531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
45409672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(memcpy)(to, from, size);
4551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
4561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
457f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void*, memmove, void *to, const void *from, size_t size) {
458e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
4591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (FLAG_replace_intrin) {
4601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_WRITE_RANGE(from, size);
4611e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(to, size);
4621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
46309672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(memmove)(to, from, size);
4641e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
4651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
466f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void*, memset, void *block, int c, size_t size) {
467e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  // memset is called inside INTERCEPT_FUNCTION on Mac.
468e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  if (asan_init_is_running) {
46909672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(memset)(block, c, size);
470e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  }
471e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
4721e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (FLAG_replace_intrin) {
4731e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_WRITE_RANGE(block, size);
4741e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
47509672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(memset)(block, c, size);
4761e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
4771e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
478f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strchr, const char *str, int c) {
479e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
48009672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  char *result = REAL(strchr)(str, c);
4811e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (FLAG_replace_str) {
48209672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    size_t bytes_read = (result ? result - str : REAL(strlen)(str)) + 1;
4831e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(str, bytes_read);
4841e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
4851e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return result;
4861e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
4871e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
488adf2b036127d7e887392d9be5b02069b777ee280Alexey Samsonov#ifdef __linux__
4894b0c5f240e71be4f375627e57d0f1b89600918a7Evgeniy StepanovINTERCEPTOR(char*, index, const char *string, int c)
490adf2b036127d7e887392d9be5b02069b777ee280Alexey Samsonov  ALIAS(WRAPPER_NAME(strchr));
491f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov#else
4924b0c5f240e71be4f375627e57d0f1b89600918a7Evgeniy StepanovDEFINE_REAL(char*, index, const char *string, int c);
493f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov#endif
494f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov
495919c24787a655597bdcf367e26c9dd1504e9f463Evgeniy Stepanov#ifdef ANDROID
496da13ba833b046553f50b54538e4828287ddbf5c0Alexey SamsonovDEFINE_REAL(int, sigaction, int signum, const struct sigaction *act,
497da13ba833b046553f50b54538e4828287ddbf5c0Alexey Samsonov    struct sigaction *oldact);
498919c24787a655597bdcf367e26c9dd1504e9f463Evgeniy Stepanov#endif
499919c24787a655597bdcf367e26c9dd1504e9f463Evgeniy Stepanov
500f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(int, strcasecmp, const char *s1, const char *s2) {
501af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany  ENSURE_ASAN_INITED();
502af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany  unsigned char c1, c2;
503af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany  size_t i;
504af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany  for (i = 0; ; i++) {
505af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany    c1 = (unsigned char)s1[i];
506af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany    c2 = (unsigned char)s2[i];
507af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany    if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
508af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany  }
509af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany  ASAN_READ_RANGE(s1, i + 1);
510af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany  ASAN_READ_RANGE(s2, i + 1);
511af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany  return CharCaseCmp(c1, c2);
512af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany}
513af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany
514f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strcat, char *to, const char *from) {  // NOLINT
5150985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany  ENSURE_ASAN_INITED();
5160985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany  if (FLAG_replace_str) {
51709672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    size_t from_length = REAL(strlen)(from);
5180985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany    ASAN_READ_RANGE(from, from_length + 1);
5190985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany    if (from_length > 0) {
52009672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov      size_t to_length = REAL(strlen)(to);
5210985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany      ASAN_READ_RANGE(to, to_length);
5220985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany      ASAN_WRITE_RANGE(to + to_length, from_length + 1);
523c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany      CHECK_RANGES_OVERLAP("strcat", to, to_length + 1, from, from_length + 1);
5240985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany    }
5250985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany  }
52609672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(strcat)(to, from);  // NOLINT
5270985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany}
5280985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany
529f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(int, strcmp, const char *s1, const char *s2) {
530f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryany  if (!asan_inited) {
531f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryany    return internal_strcmp(s1, s2);
5321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
5331e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  unsigned char c1, c2;
5341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  size_t i;
5351e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  for (i = 0; ; i++) {
5361e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    c1 = (unsigned char)s1[i];
5371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    c2 = (unsigned char)s2[i];
5381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    if (c1 != c2 || c1 == '\0') break;
5391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
5401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  ASAN_READ_RANGE(s1, i + 1);
5411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  ASAN_READ_RANGE(s2, i + 1);
5421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return CharCmp(c1, c2);
5431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
5441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
545f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strcpy, char *to, const char *from) {  // NOLINT
5461e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // strcpy is called from malloc_default_purgeable_zone()
5471e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // in __asan::ReplaceSystemAlloc() on Mac.
5481e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (asan_init_is_running) {
54909672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(strcpy)(to, from);  // NOLINT
5501e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
551e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
5521e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (FLAG_replace_str) {
55309672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    size_t from_size = REAL(strlen)(from) + 1;
554c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany    CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size);
5551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(from, from_size);
5561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_WRITE_RANGE(to, from_size);
5571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
55809672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(strcpy)(to, from);  // NOLINT
5591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
5601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
561f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strdup, const char *s) {
562e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
5631e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (FLAG_replace_str) {
56409672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    size_t length = REAL(strlen)(s);
5651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(s, length + 1);
5661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
56709672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(strdup)(s);
5681e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
5691e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
570f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(size_t, strlen, const char *s) {
5711e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // strlen is called from malloc_default_purgeable_zone()
5721e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // in __asan::ReplaceSystemAlloc() on Mac.
5731e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (asan_init_is_running) {
57409672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(strlen)(s);
5751e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
576e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
57709672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  size_t length = REAL(strlen)(s);
5781e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (FLAG_replace_str) {
5791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(s, length + 1);
5801e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
5811e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return length;
5821e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
5831e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
584f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, size_t n) {
585af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany  ENSURE_ASAN_INITED();
586af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany  unsigned char c1 = 0, c2 = 0;
587af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany  size_t i;
588f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov  for (i = 0; i < n; i++) {
589af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany    c1 = (unsigned char)s1[i];
590af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany    c2 = (unsigned char)s2[i];
591af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany    if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
592af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany  }
593f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov  ASAN_READ_RANGE(s1, Min(i + 1, n));
594f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov  ASAN_READ_RANGE(s2, Min(i + 1, n));
595af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany  return CharCaseCmp(c1, c2);
596af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany}
597af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany
598f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(int, strncmp, const char *s1, const char *s2, size_t size) {
5991e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // strncmp is called from malloc_default_purgeable_zone()
6001e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // in __asan::ReplaceSystemAlloc() on Mac.
6011e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (asan_init_is_running) {
60209672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    return REAL(strncmp)(s1, s2, size);
6031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
6041e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  unsigned char c1 = 0, c2 = 0;
6051e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  size_t i;
6061e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  for (i = 0; i < size; i++) {
6071e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    c1 = (unsigned char)s1[i];
6081e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    c2 = (unsigned char)s2[i];
6091e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    if (c1 != c2 || c1 == '\0') break;
6101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
6112d8b3bdb112ebb8ed3f15ee41d4cebcd683b41b0Kostya Serebryany  ASAN_READ_RANGE(s1, Min(i + 1, size));
6122d8b3bdb112ebb8ed3f15ee41d4cebcd683b41b0Kostya Serebryany  ASAN_READ_RANGE(s2, Min(i + 1, size));
6131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return CharCmp(c1, c2);
6141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
6151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
616f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strncpy, char *to, const char *from, size_t size) {
617e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
6181e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (FLAG_replace_str) {
6192d8b3bdb112ebb8ed3f15ee41d4cebcd683b41b0Kostya Serebryany    size_t from_size = Min(size, internal_strnlen(from, size) + 1);
620c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany    CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size);
6211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(from, from_size);
6221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_WRITE_RANGE(to, size);
6231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
62409672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(strncpy)(to, from, size);
6251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
6261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
6271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#ifndef __APPLE__
628f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(size_t, strnlen, const char *s, size_t maxlen) {
629e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
63009672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  size_t length = REAL(strnlen)(s, maxlen);
6311e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (FLAG_replace_str) {
6322d8b3bdb112ebb8ed3f15ee41d4cebcd683b41b0Kostya Serebryany    ASAN_READ_RANGE(s, Min(length + 1, maxlen));
6331e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
6341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return length;
6351e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
636d66a8d8f56c66c9749b6d75c61870a121d4d9307Kostya Serebryany#endif
637547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany
638600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov#if defined(_WIN32)
639600972e3427173cc8904d741decd1af0ed5de9fdTimur IskhodzhanovINTERCEPTOR_WINAPI(DWORD, CreateThread,
640600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov                   void* security, size_t stack_size,
641600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov                   DWORD (__stdcall *start_routine)(void*), void* arg,
642600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov                   DWORD flags, void* tid) {
643600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  GET_STACK_TRACE_HERE(kStackTraceMax);
644600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  int current_tid = asanThreadRegistry().GetCurrentTidOrMinusOne();
645600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  AsanThread *t = AsanThread::Create(current_tid, start_routine, arg, &stack);
646600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  asanThreadRegistry().RegisterThread(t);
647600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  return REAL(CreateThread)(security, stack_size,
648600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov                            asan_thread_start, t, flags, tid);
649600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov}
650600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov
651600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanovnamespace __asan {
652600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanovvoid InitializeWindowsInterceptors() {
653600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  CHECK(INTERCEPT_FUNCTION(CreateThread));
654600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov}
655600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov
656600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov}  // namespace __asan
657600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov#endif
658600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov
659547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany// ---------------------- InitializeAsanInterceptors ---------------- {{{1
660547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryanynamespace __asan {
661547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryanyvoid InitializeAsanInterceptors() {
662fdbdab5ff8de4c23b58bb411ea2358a78e2d9b2fKostya Serebryany  static bool was_called_once;
663fdbdab5ff8de4c23b58bb411ea2358a78e2d9b2fKostya Serebryany  CHECK(was_called_once == false);
664fdbdab5ff8de4c23b58bb411ea2358a78e2d9b2fKostya Serebryany  was_called_once = true;
66507bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  // Intercept mem* functions.
6665b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  CHECK(INTERCEPT_FUNCTION(memcmp));
6675b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  CHECK(INTERCEPT_FUNCTION(memmove));
66807bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  CHECK(INTERCEPT_FUNCTION(memset));
66938dd4ed885e714c376466f6fe0d69f5f22d37014Alexey Samsonov  if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) {
6705b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov    CHECK(INTERCEPT_FUNCTION(memcpy));
671573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko  } else {
67209672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    REAL(memcpy) = REAL(memmove);
673573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko  }
67407bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov
67507bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  // Intercept str* functions.
6765b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  CHECK(INTERCEPT_FUNCTION(strcat));  // NOLINT
6775b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  CHECK(INTERCEPT_FUNCTION(strchr));
6785b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  CHECK(INTERCEPT_FUNCTION(strcmp));
6795b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  CHECK(INTERCEPT_FUNCTION(strcpy));  // NOLINT
6805b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  CHECK(INTERCEPT_FUNCTION(strlen));
6815b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  CHECK(INTERCEPT_FUNCTION(strncmp));
6825b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  CHECK(INTERCEPT_FUNCTION(strncpy));
68307bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov#if !defined(_WIN32)
68407bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  CHECK(INTERCEPT_FUNCTION(strcasecmp));
68507bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  CHECK(INTERCEPT_FUNCTION(strdup));
68607bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  CHECK(INTERCEPT_FUNCTION(strncasecmp));
68707bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov# ifndef __APPLE__
68807bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  CHECK(INTERCEPT_FUNCTION(index));
68907bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov# else
69007bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  CHECK(OVERRIDE_FUNCTION(index, WRAP(strchr)));
69107bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov# endif
69207bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov#endif
69307bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov#if !defined(__APPLE__)
69407bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  CHECK(INTERCEPT_FUNCTION(strnlen));
69507bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov#endif
6965b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov
69707bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  // Intecept signal- and jump-related functions.
69807bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  CHECK(INTERCEPT_FUNCTION(longjmp));
69907bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov#if !defined(ANDROID) && !defined(_WIN32)
7005b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  CHECK(INTERCEPT_FUNCTION(sigaction));
7015b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  CHECK(INTERCEPT_FUNCTION(signal));
702919c24787a655597bdcf367e26c9dd1504e9f463Evgeniy Stepanov#endif
703919c24787a655597bdcf367e26c9dd1504e9f463Evgeniy Stepanov
70407bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov#if !defined(_WIN32)
7055b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  CHECK(INTERCEPT_FUNCTION(_longjmp));
7065b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov  INTERCEPT_FUNCTION(__cxa_throw);
70707bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov# if !defined(__APPLE__)
70807bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  // On Darwin siglongjmp tailcalls longjmp, so we don't want to intercept it
70907bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  // there.
71007bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  CHECK(INTERCEPT_FUNCTION(siglongjmp));
71107bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov# endif
7123e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov#endif
7133e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov
71407bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  // Intercept threading-related functions
71507bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov#if !defined(_WIN32)
71607bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  CHECK(INTERCEPT_FUNCTION(pthread_create));
71707bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov#endif
71807bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov
719600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  // Some Windows-specific interceptors.
720600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov#if defined(_WIN32)
721600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  InitializeWindowsInterceptors();
722600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov#endif
723600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov
72407bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov  // Some Mac-specific interceptors.
72507bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov#if defined(__APPLE__)
726beba6448539095b67cab266d09cd7b7d313b8c3dAlexey Samsonov  InitializeMacInterceptors();
727547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany#endif
728547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany
729547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  if (FLAG_v > 0) {
7302962f26071ebef1d5fec52b5569e5ae7aae45c9bAlexander Potapenko    Report("AddressSanitizer: libc interceptors initialized\n");
731547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany  }
732547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany}
733547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany
734547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany}  // namespace __asan
735