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