asan_interceptors.cc revision e130191a254064bfd1c8d373afdacf6d52979713
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//
121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Intercept various libc functions to catch buggy memory accesses there.
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"
221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <dlfcn.h>
241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <string.h>
251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan {
271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyindex_f       real_index;
291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanymemcpy_f      real_memcpy;
301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanymemmove_f     real_memmove;
311e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanymemset_f      real_memset;
321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanystrchr_f      real_strchr;
331e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanystrcmp_f      real_strcmp;
341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanystrcpy_f      real_strcpy;
351e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanystrdup_f      real_strdup;
361e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanystrlen_f      real_strlen;
371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanystrncmp_f     real_strncmp;
381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanystrncpy_f     real_strncpy;
391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanystrnlen_f     real_strnlen;
401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Instruments read/write access to a single byte in memory.
421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// On error calls __asan_report_error, which aborts the program.
431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany__attribute__((noinline))
441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanystatic void AccessAddress(uintptr_t address, bool isWrite) {
451e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (__asan_address_is_poisoned((void*)address)) {
461e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    GET_BP_PC_SP;
471e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    __asan_report_error(pc, bp, sp, address, isWrite, /* access_size */ 1);
481e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
491e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
501e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
511e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE,
521e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// and ASAN_WRITE_RANGE as macro instead of function so
531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// that no extra frames are created, and stack trace contains
541e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// relevant information only.
551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Instruments read/write access to a memory range.
571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// More complex implementation is possible, for now just
581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// checking the first and the last byte of a range.
591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#define ACCESS_MEMORY_RANGE(offset, size, isWrite) do { \
601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (size > 0) { \
611e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    uintptr_t ptr = (uintptr_t)(offset); \
621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    AccessAddress(ptr, isWrite); \
631e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    AccessAddress(ptr + (size) - 1, isWrite); \
641e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  } \
65e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany} while (0)
661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#define ASAN_READ_RANGE(offset, size) do { \
681e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  ACCESS_MEMORY_RANGE(offset, size, false); \
69e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany} while (0)
701e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
711e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#define ASAN_WRITE_RANGE(offset, size) do { \
721e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  ACCESS_MEMORY_RANGE(offset, size, true); \
73e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany} while (0)
741e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
751e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Behavior of functions like "memcpy" or "strcpy" is undefined
761e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// if memory intervals overlap. We report error in this case.
771e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Macro is used to avoid creation of new frames.
781e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanystatic inline bool RangesOverlap(const char *offset1, const char *offset2,
791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany                                 size_t length) {
801e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return !((offset1 + length <= offset2) || (offset2 + length <= offset1));
811e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
821e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#define CHECK_RANGES_OVERLAP(_offset1, _offset2, length) do { \
831e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  const char *offset1 = (const char*)_offset1; \
841e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  const char *offset2 = (const char*)_offset2; \
851e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (RangesOverlap((const char*)offset1, (const char*)offset2, \
861e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany                    length)) { \
871e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    Printf("ERROR: AddressSanitizer strcpy-param-overlap: " \
881e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany           "memory ranges [%p,%p) and [%p, %p) overlap\n", \
891e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany           offset1, offset1 + length, offset2, offset2 + length); \
901e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    PRINT_CURRENT_STACK(); \
911e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ShowStatsAndAbort(); \
921e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  } \
93e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany} while (0)
941e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
95e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany#define ENSURE_ASAN_INITED() do { \
96e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  CHECK(!asan_init_is_running); \
97e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  if (!asan_inited) { \
98e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany    __asan_init(); \
99e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  } \
100e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany} while (0)
1011e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
1021e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanysize_t internal_strlen(const char *s) {
1031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  size_t i = 0;
1041e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  while (s[i]) i++;
1051e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return i;
1061e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
1071e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
1081e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanysize_t internal_strnlen(const char *s, size_t maxlen) {
1091e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (real_strnlen != NULL) {
1101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    return real_strnlen(s, maxlen);
1111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
1121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  size_t i = 0;
1131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  while (i < maxlen && s[i]) i++;
1141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return i;
1151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
1161e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
1171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid InitializeAsanInterceptors() {
1181e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#ifndef __APPLE__
1191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  INTERCEPT_FUNCTION(index);
1201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#else
1211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  OVERRIDE_FUNCTION(index, WRAP(strchr));
1221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#endif
1231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  INTERCEPT_FUNCTION(memcpy);
1241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  INTERCEPT_FUNCTION(memmove);
1251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  INTERCEPT_FUNCTION(memset);
1261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  INTERCEPT_FUNCTION(strchr);
1271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  INTERCEPT_FUNCTION(strcmp);
1281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  INTERCEPT_FUNCTION(strcpy);  // NOLINT
1291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  INTERCEPT_FUNCTION(strdup);
1301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  INTERCEPT_FUNCTION(strlen);
1311e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  INTERCEPT_FUNCTION(strncmp);
1321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  INTERCEPT_FUNCTION(strncpy);
1331e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#ifndef __APPLE__
1341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  INTERCEPT_FUNCTION(strnlen);
1351e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#endif
1361e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (FLAG_v > 0) {
1371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    Printf("AddressSanitizer: libc interceptors initialized\n");
1381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
1391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
1401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
1411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}  // namespace __asan
1421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
1431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// ---------------------- Wrappers ---------------- {{{1
1441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyusing namespace __asan;  // NOLINT
1451e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
1461e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid *WRAP(memcpy)(void *to, const void *from, size_t size) {
1471e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // memcpy is called during __asan_init() from the internals
1481e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // of printf(...).
1491e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (asan_init_is_running) {
1501e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    return real_memcpy(to, from, size);
1511e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
152e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
1531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (FLAG_replace_intrin) {
1541e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    CHECK_RANGES_OVERLAP(to, from, size);
1551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_WRITE_RANGE(from, size);
1561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(to, size);
1571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
1581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return real_memcpy(to, from, size);
1591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
1601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
1611e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid *WRAP(memmove)(void *to, const void *from, size_t size) {
162e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
1631e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (FLAG_replace_intrin) {
1641e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_WRITE_RANGE(from, size);
1651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(to, size);
1661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
1671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return real_memmove(to, from, size);
1681e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
1691e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
1701e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid *WRAP(memset)(void *block, int c, size_t size) {
171e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  // memset is called inside INTERCEPT_FUNCTION on Mac.
172e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  if (asan_init_is_running) {
173e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany    return real_memset(block, c, size);
174e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  }
175e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
1761e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (FLAG_replace_intrin) {
1771e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_WRITE_RANGE(block, size);
1781e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
1791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return real_memset(block, c, size);
1801e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
1811e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
1821e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Note that on Linux index and strchr are definined differently depending on
1831e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// the compiler (gcc vs clang).
1841e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// see __CORRECT_ISO_CPP_STRING_H_PROTO in /usr/include/string.h
1851e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
1861e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#ifndef __APPLE__
1871e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanychar *WRAP(index)(const char *str, int c)
1881e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  __attribute__((alias(WRAPPER_NAME(strchr))));
1891e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#endif
1901e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
1911e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanychar *WRAP(strchr)(const char *str, int c) {
192e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
1931e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  char *result = real_strchr(str, c);
1941e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (FLAG_replace_str) {
1951e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    size_t bytes_read = (result ? result - str : real_strlen(str)) + 1;
1961e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(str, bytes_read);
1971e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
1981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return result;
1991e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
2001e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
2011e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanystatic inline int CharCmp(unsigned char c1, unsigned char c2) {
2021e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
2031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
2041e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
2051e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyint WRAP(strcmp)(const char *s1, const char *s2) {
2061e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // strcmp is called from malloc_default_purgeable_zone()
2071e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // in __asan::ReplaceSystemAlloc() on Mac.
2081e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (asan_init_is_running) {
2091e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    return real_strcmp(s1, s2);
2101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
2111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  unsigned char c1, c2;
2121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  size_t i;
2131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  for (i = 0; ; i++) {
2141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    c1 = (unsigned char)s1[i];
2151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    c2 = (unsigned char)s2[i];
2161e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    if (c1 != c2 || c1 == '\0') break;
2171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
2181e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  ASAN_READ_RANGE(s1, i + 1);
2191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  ASAN_READ_RANGE(s2, i + 1);
2201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return CharCmp(c1, c2);
2211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
2221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
2231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanychar *WRAP(strcpy)(char *to, const char *from) {  // NOLINT
2241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // strcpy is called from malloc_default_purgeable_zone()
2251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // in __asan::ReplaceSystemAlloc() on Mac.
2261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (asan_init_is_running) {
2271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    return real_strcpy(to, from);
2281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
229e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
2301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (FLAG_replace_str) {
2311e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    size_t from_size = real_strlen(from) + 1;
2321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    CHECK_RANGES_OVERLAP(to, from, from_size);
2331e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(from, from_size);
2341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_WRITE_RANGE(to, from_size);
2351e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
2361e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return real_strcpy(to, from);
2371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
2381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
2391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanychar *WRAP(strdup)(const char *s) {
240e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
2411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (FLAG_replace_str) {
2421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    size_t length = real_strlen(s);
2431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(s, length + 1);
2441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
2451e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return real_strdup(s);
2461e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
2471e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
2481e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanysize_t WRAP(strlen)(const char *s) {
2491e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // strlen is called from malloc_default_purgeable_zone()
2501e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // in __asan::ReplaceSystemAlloc() on Mac.
2511e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (asan_init_is_running) {
2521e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    return real_strlen(s);
2531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
254e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
2551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  size_t length = real_strlen(s);
2561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (FLAG_replace_str) {
2571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(s, length + 1);
2581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
2591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return length;
2601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
2611e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
2621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyint WRAP(strncmp)(const char *s1, const char *s2, size_t size) {
2631e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // strncmp is called from malloc_default_purgeable_zone()
2641e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // in __asan::ReplaceSystemAlloc() on Mac.
2651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (asan_init_is_running) {
2661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    return real_strncmp(s1, s2, size);
2671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
2681e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  unsigned char c1 = 0, c2 = 0;
2691e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  size_t i;
2701e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  for (i = 0; i < size; i++) {
2711e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    c1 = (unsigned char)s1[i];
2721e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    c2 = (unsigned char)s2[i];
2731e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    if (c1 != c2 || c1 == '\0') break;
2741e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
2752d8b3bdb112ebb8ed3f15ee41d4cebcd683b41b0Kostya Serebryany  ASAN_READ_RANGE(s1, Min(i + 1, size));
2762d8b3bdb112ebb8ed3f15ee41d4cebcd683b41b0Kostya Serebryany  ASAN_READ_RANGE(s2, Min(i + 1, size));
2771e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return CharCmp(c1, c2);
2781e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
2791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
2801e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanychar *WRAP(strncpy)(char *to, const char *from, size_t size) {
281e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
2821e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (FLAG_replace_str) {
2832d8b3bdb112ebb8ed3f15ee41d4cebcd683b41b0Kostya Serebryany    size_t from_size = Min(size, internal_strnlen(from, size) + 1);
2841e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    CHECK_RANGES_OVERLAP(to, from, from_size);
2851e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_READ_RANGE(from, from_size);
2861e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ASAN_WRITE_RANGE(to, size);
2871e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
2881e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return real_strncpy(to, from, size);
2891e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
2901e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
2911e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#ifndef __APPLE__
2921e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanysize_t WRAP(strnlen)(const char *s, size_t maxlen) {
293e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany  ENSURE_ASAN_INITED();
2941e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  size_t length = real_strnlen(s, maxlen);
2951e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (FLAG_replace_str) {
2962d8b3bdb112ebb8ed3f15ee41d4cebcd683b41b0Kostya Serebryany    ASAN_READ_RANGE(s, Min(length + 1, maxlen));
2971e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
2981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return length;
2991e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
3001e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#endif
301