asan_interceptors.cc revision f2598fc21bf651d23feab396a7581d48c01c3be5
11e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===-- asan_interceptors.cc ------------------------------------*- C++ -*-===// 21e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 31e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// The LLVM Compiler Infrastructure 41e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 51e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// This file is distributed under the University of Illinois Open Source 61e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// License. See LICENSE.TXT for details. 71e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 81e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===----------------------------------------------------------------------===// 91e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// This file is a part of AddressSanitizer, an address sanity checker. 111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 12d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany// Intercept various libc functions. 131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===----------------------------------------------------------------------===// 141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_interceptors.h" 151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 161e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_allocator.h" 171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_interface.h" 181e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_internal.h" 19547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany#include "asan_mac.h" 201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_mapping.h" 211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_stack.h" 221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_stats.h" 234803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany#include "asan_thread_registry.h" 241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 254803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany#include <new> 26af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany#include <ctype.h> 271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 286f0452914ec76c786eb865983793bc03b00fc7b6Alexander Potapenko#ifndef _WIN32 296f0452914ec76c786eb865983793bc03b00fc7b6Alexander Potapenko#include <dlfcn.h> 302fc648c5d1775f13844d4459347e2b7328411e85Kostya Serebryany#include <pthread.h> 316f0452914ec76c786eb865983793bc03b00fc7b6Alexander Potapenko#endif 3235dd9d8f54f15f16be6c224e303bbf75d667f248Kostya Serebryany 33d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany// To replace weak system functions on Linux we just need to declare functions 34d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany// with same names in our library and then obtain the real function pointers 35d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany// using dlsym(). This is not so on Mac OS, where the two-level namespace makes 36d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany// our replacement functions invisible to other libraries. This may be overcomed 37d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany// using the DYLD_FORCE_FLAT_NAMESPACE, but some errors loading the shared 38d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany// libraries in Chromium were noticed when doing so. 39d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany// Instead we use mach_override, a handy framework for patching functions at 40d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany// runtime. To avoid possible name clashes, our replacement functions have 41d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany// the "wrap_" prefix on Mac. 42d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany// 43d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany// After interception, the calls to system functions will be substituted by 44d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany// calls to our interceptors. We store pointers to system function f() 45d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany// in __asan::real_f(). 466f0452914ec76c786eb865983793bc03b00fc7b6Alexander Potapenko#if defined(__APPLE__) 47c8365231004cb1d956aba4164c89ea1398eadd6bAlexander Potapenko// Include the declarations of the original functions. 483389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov#include <signal.h> 49c8365231004cb1d956aba4164c89ea1398eadd6bAlexander Potapenko#include <string.h> 50c8365231004cb1d956aba4164c89ea1398eadd6bAlexander Potapenko#include <strings.h> 51c8365231004cb1d956aba4164c89ea1398eadd6bAlexander Potapenko 52d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany#include "mach_override/mach_override.h" 53d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany 543281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko#define OVERRIDE_FUNCTION(oldfunc, newfunc) \ 553281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko do {CHECK(0 == __asan_mach_override_ptr_custom((void*)(oldfunc), \ 563281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko (void*)(newfunc), \ 573281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko (void**)&real_##oldfunc, \ 583281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko __asan_allocate_island, \ 593281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko __asan_deallocate_island)); \ 604dd8ba8238b1b698953628affe6e5b2edf3b3e3fAlexey Samsonov CHECK(real_##oldfunc != NULL); } while (0) 61d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany 623281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko#define OVERRIDE_FUNCTION_IF_EXISTS(oldfunc, newfunc) \ 633281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko do { __asan_mach_override_ptr_custom((void*)(oldfunc), \ 643281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko (void*)(newfunc), \ 653281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko (void**)&real_##oldfunc, \ 663281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko __asan_allocate_island, \ 673281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko __asan_deallocate_island); \ 683281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko } while (0) 69d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany 70d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany#define INTERCEPT_FUNCTION(func) \ 71d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany OVERRIDE_FUNCTION(func, WRAP(func)) 72d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany 73d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany#define INTERCEPT_FUNCTION_IF_EXISTS(func) \ 74d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany OVERRIDE_FUNCTION_IF_EXISTS(func, WRAP(func)) 75d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany 766f0452914ec76c786eb865983793bc03b00fc7b6Alexander Potapenko#elif defined(_WIN32) 776f0452914ec76c786eb865983793bc03b00fc7b6Alexander Potapenko// TODO(timurrrr): change these macros once we decide how to intercept 786f0452914ec76c786eb865983793bc03b00fc7b6Alexander Potapenko// functions on Windows. 796f0452914ec76c786eb865983793bc03b00fc7b6Alexander Potapenko#define INTERCEPT_FUNCTION(func) \ 806f0452914ec76c786eb865983793bc03b00fc7b6Alexander Potapenko do { } while (0) 816f0452914ec76c786eb865983793bc03b00fc7b6Alexander Potapenko 826f0452914ec76c786eb865983793bc03b00fc7b6Alexander Potapenko#define INTERCEPT_FUNCTION_IF_EXISTS(func) \ 836f0452914ec76c786eb865983793bc03b00fc7b6Alexander Potapenko do { } while (0) 846f0452914ec76c786eb865983793bc03b00fc7b6Alexander Potapenko 85d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany#else // __linux__ 86d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany#define INTERCEPT_FUNCTION(func) \ 87d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany CHECK((real_##func = (func##_f)dlsym(RTLD_NEXT, #func))); 88d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany 89d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany#define INTERCEPT_FUNCTION_IF_EXISTS(func) \ 90d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany do { real_##func = (func##_f)dlsym(RTLD_NEXT, #func); } while (0) 91d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany#endif 92d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany 931e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan { 941e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 951e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Instruments read/write access to a single byte in memory. 961e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// On error calls __asan_report_error, which aborts the program. 971e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany__attribute__((noinline)) 981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanystatic void AccessAddress(uintptr_t address, bool isWrite) { 991e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (__asan_address_is_poisoned((void*)address)) { 1001e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_BP_PC_SP; 1011e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany __asan_report_error(pc, bp, sp, address, isWrite, /* access_size */ 1); 1021e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 1031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1041e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1051e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE, 1061e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// and ASAN_WRITE_RANGE as macro instead of function so 1071e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// that no extra frames are created, and stack trace contains 1081e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// relevant information only. 1091e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Instruments read/write access to a memory range. 1111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// More complex implementation is possible, for now just 1121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// checking the first and the last byte of a range. 1131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#define ACCESS_MEMORY_RANGE(offset, size, isWrite) do { \ 1141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (size > 0) { \ 1151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany uintptr_t ptr = (uintptr_t)(offset); \ 1161e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany AccessAddress(ptr, isWrite); \ 1171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany AccessAddress(ptr + (size) - 1, isWrite); \ 1181e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } \ 119e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany} while (0) 1201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#define ASAN_READ_RANGE(offset, size) do { \ 1221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ACCESS_MEMORY_RANGE(offset, size, false); \ 123e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany} while (0) 1241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#define ASAN_WRITE_RANGE(offset, size) do { \ 1261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ACCESS_MEMORY_RANGE(offset, size, true); \ 127e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany} while (0) 1281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Behavior of functions like "memcpy" or "strcpy" is undefined 1301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// if memory intervals overlap. We report error in this case. 1311e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Macro is used to avoid creation of new frames. 1320985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryanystatic inline bool RangesOverlap(const char *offset1, size_t length1, 1330985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany const char *offset2, size_t length2) { 1340985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany return !((offset1 + length1 <= offset2) || (offset2 + length2 <= offset1)); 1351e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 136c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany#define CHECK_RANGES_OVERLAP(name, _offset1, length1, _offset2, length2) do { \ 1371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany const char *offset1 = (const char*)_offset1; \ 1381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany const char *offset2 = (const char*)_offset2; \ 1390985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany if (RangesOverlap(offset1, length1, offset2, length2)) { \ 140c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany Report("ERROR: AddressSanitizer %s-param-overlap: " \ 1411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany "memory ranges [%p,%p) and [%p, %p) overlap\n", \ 142c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany name, offset1, offset1 + length1, offset2, offset2 + length2); \ 1431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany PRINT_CURRENT_STACK(); \ 1441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ShowStatsAndAbort(); \ 1451e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } \ 146e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany} while (0) 1471e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 148e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany#define ENSURE_ASAN_INITED() do { \ 149e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany CHECK(!asan_init_is_running); \ 150e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany if (!asan_inited) { \ 151e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany __asan_init(); \ 152e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany } \ 153e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany} while (0) 1541e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanysize_t internal_strlen(const char *s) { 1561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany size_t i = 0; 1571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany while (s[i]) i++; 1581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return i; 1591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1611e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanysize_t internal_strnlen(const char *s, size_t maxlen) { 162f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov#ifndef __APPLE__ 1631e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (real_strnlen != NULL) { 1641e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return real_strnlen(s, maxlen); 1651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 166f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov#endif 1671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany size_t i = 0; 1681e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany while (i < maxlen && s[i]) i++; 1691e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return i; 1701e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1711e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 172de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryanyvoid* internal_memchr(const void* s, int c, size_t n) { 173de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany const char* t = (char*)s; 174de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany for (size_t i = 0; i < n; ++i, ++t) 175de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany if (*t == c) 176de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany return (void*)t; 177de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany return NULL; 178de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany} 179de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany 180de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryanyint internal_memcmp(const void* s1, const void* s2, size_t n) { 181de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany const char* t1 = (char*)s1; 182de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany const char* t2 = (char*)s2; 183de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany for (size_t i = 0; i < n; ++i, ++t1, ++t2) 184de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany if (*t1 != *t2) 185de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany return *t1 < *t2 ? -1 : 1; 186de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany return 0; 187de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany} 188de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany 189a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryanychar *internal_strstr(const char *haystack, const char *needle) { 190a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany // This is O(N^2), but we are not using it in hot places. 191a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany size_t len1 = internal_strlen(haystack); 192a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany size_t len2 = internal_strlen(needle); 193a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany if (len1 < len2) return 0; 194a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany for (size_t pos = 0; pos <= len1 - len2; pos++) { 195a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany if (internal_memcmp(haystack + pos, needle, len2) == 0) 196a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany return (char*)haystack + pos; 197a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany } 198a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany return 0; 199a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany} 200a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany 201a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryanychar *internal_strncat(char *dst, const char *src, size_t n) { 202a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany size_t len = internal_strlen(dst); 203a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany size_t i; 204a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany for (i = 0; i < n && src[i]; i++) 205a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany dst[len + i] = src[i]; 206a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany dst[len + i] = 0; 207a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany return dst; 208a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany} 2091e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 210f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryanyint internal_strcmp(const char *s1, const char *s2) { 211f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryany while (true) { 212f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryany unsigned c1 = *s1; 213f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryany unsigned c2 = *s2; 214f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryany if (c1 != c2) return (c1 < c2) ? -1 : 1; 215f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryany if (c1 == 0) break; 216f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryany s1++; 217f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryany s2++; 218f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryany } 219f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryany return 0; 220f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryany} 221f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryany 2221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} // namespace __asan 2231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// ---------------------- Wrappers ---------------- {{{1 2251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyusing namespace __asan; // NOLINT 2261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2274803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany#define OPERATOR_NEW_BODY \ 2284803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany GET_STACK_TRACE_HERE_FOR_MALLOC;\ 2294803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany return asan_memalign(0, size, &stack); 2304803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 2314803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany#ifdef ANDROID 2324803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyvoid *operator new(size_t size) { OPERATOR_NEW_BODY; } 2334803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyvoid *operator new[](size_t size) { OPERATOR_NEW_BODY; } 2344803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany#else 2354803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyvoid *operator new(size_t size) throw(std::bad_alloc) { OPERATOR_NEW_BODY; } 2364803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyvoid *operator new[](size_t size) throw(std::bad_alloc) { OPERATOR_NEW_BODY; } 2374803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyvoid *operator new(size_t size, std::nothrow_t const&) throw() 2384803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany{ OPERATOR_NEW_BODY; } 2394803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyvoid *operator new[](size_t size, std::nothrow_t const&) throw() 2404803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany{ OPERATOR_NEW_BODY; } 2414803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany#endif 2424803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 2434803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany#define OPERATOR_DELETE_BODY \ 2444803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany GET_STACK_TRACE_HERE_FOR_FREE(ptr);\ 2454803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany asan_free(ptr, &stack); 2464803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 2474803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyvoid operator delete(void *ptr) throw() { OPERATOR_DELETE_BODY; } 2484803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyvoid operator delete[](void *ptr) throw() { OPERATOR_DELETE_BODY; } 2494803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyvoid operator delete(void *ptr, std::nothrow_t const&) throw() 2504803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany{ OPERATOR_DELETE_BODY; } 2514803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyvoid operator delete[](void *ptr, std::nothrow_t const&) throw() 2524803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany{ OPERATOR_DELETE_BODY;} 2534803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 2544803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanystatic void *asan_thread_start(void *arg) { 2554803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany AsanThread *t = (AsanThread*)arg; 2564803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany asanThreadRegistry().SetCurrent(t); 2574803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany return t->ThreadStart(); 2584803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 2594803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 2606f0452914ec76c786eb865983793bc03b00fc7b6Alexander Potapenko#ifndef _WIN32 261f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(int, pthread_create, pthread_t *thread, 262f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov const pthread_attr_t *attr, 263f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov void *(*start_routine)(void*), void *arg) { 2649cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov GET_STACK_TRACE_HERE(kStackTraceMax); 2654803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany int current_tid = asanThreadRegistry().GetCurrentTidOrMinusOne(); 26655cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov AsanThread *t = AsanThread::Create(current_tid, start_routine, arg, &stack); 26755cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov asanThreadRegistry().RegisterThread(t); 2684803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany return real_pthread_create(thread, attr, asan_thread_start, t); 2694803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 2704803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 271f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void*, signal, int signum, void *handler) { 2724803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany if (!AsanInterceptsSignal(signum)) { 2734803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany return real_signal(signum, handler); 2744803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany } 2754803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany return NULL; 2764803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 2774803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 278f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(int, sigaction, int signum, const struct sigaction *act, 279f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov struct sigaction *oldact) { 2804803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany if (!AsanInterceptsSignal(signum)) { 2814803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany return real_sigaction(signum, act, oldact); 2824803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany } 2834803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany return 0; 2844803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 2856f0452914ec76c786eb865983793bc03b00fc7b6Alexander Potapenko#endif // _WIN32 2864803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 2874803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 2884803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanystatic void UnpoisonStackFromHereToTop() { 2894803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany int local_stack; 2904803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany AsanThread *curr_thread = asanThreadRegistry().GetCurrent(); 2914803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany CHECK(curr_thread); 2924803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany uintptr_t top = curr_thread->stack_top(); 2934803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany uintptr_t bottom = ((uintptr_t)&local_stack - kPageSize) & ~(kPageSize-1); 2944803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany PoisonShadow(bottom, top - bottom, 0); 2954803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 2964803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 297f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, longjmp, void *env, int val) { 2984803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany UnpoisonStackFromHereToTop(); 2994803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany real_longjmp(env, val); 3004803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 3014803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 302f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, _longjmp, void *env, int val) { 3034803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany UnpoisonStackFromHereToTop(); 3044803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany real__longjmp(env, val); 3054803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 3064803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 307f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, siglongjmp, void *env, int val) { 3084803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany UnpoisonStackFromHereToTop(); 3094803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany real_siglongjmp(env, val); 3104803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 3114803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 3123389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov#if ASAN_HAS_EXCEPTIONS == 1 3133389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov#ifdef __APPLE__ 3144803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyextern "C" void __cxa_throw(void *a, void *b, void *c); 3153389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov#endif // __APPLE__ 3164803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 317f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) { 3184803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany CHECK(&real___cxa_throw); 3194803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany UnpoisonStackFromHereToTop(); 3204803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany real___cxa_throw(a, b, c); 3214803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 3224803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany#endif 3234803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 3244803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany// intercept mlock and friends. 3254803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany// Since asan maps 16T of RAM, mlock is completely unfriendly to asan. 3264803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany// All functions return 0 (success). 3274803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanystatic void MlockIsUnsupported() { 3284803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany static bool printed = 0; 3294803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany if (printed) return; 3304803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany printed = true; 3314803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany Printf("INFO: AddressSanitizer ignores mlock/mlockall/munlock/munlockall\n"); 3324803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 3333389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov 334f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonovextern "C" { 3353389b8ea81f51a28365a421b2646d594bac490f5Alexey SamsonovINTERCEPTOR_ATTRIBUTE 3364803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyint mlock(const void *addr, size_t len) { 3374803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany MlockIsUnsupported(); 3384803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany return 0; 3394803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 3403389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov 3413389b8ea81f51a28365a421b2646d594bac490f5Alexey SamsonovINTERCEPTOR_ATTRIBUTE 3424803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyint munlock(const void *addr, size_t len) { 3434803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany MlockIsUnsupported(); 3444803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany return 0; 3454803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 3463389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov 3473389b8ea81f51a28365a421b2646d594bac490f5Alexey SamsonovINTERCEPTOR_ATTRIBUTE 3484803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyint mlockall(int flags) { 3494803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany MlockIsUnsupported(); 3504803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany return 0; 3514803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 3523389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov 3533389b8ea81f51a28365a421b2646d594bac490f5Alexey SamsonovINTERCEPTOR_ATTRIBUTE 3544803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanyint munlockall(void) { 3554803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany MlockIsUnsupported(); 3564803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany return 0; 3574803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 3584803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} // extern "C" 3594803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 36052fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryanystatic inline int CharCmp(unsigned char c1, unsigned char c2) { 36152fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1; 36252fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany} 36352fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany 36452fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryanystatic inline int CharCaseCmp(unsigned char c1, unsigned char c2) { 36552fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany int c1_low = tolower(c1); 36652fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany int c2_low = tolower(c2); 36752fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany return c1_low - c2_low; 36852fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany} 36952fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany 370f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(int, memcmp, const void *a1, const void *a2, size_t size) { 37152fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany ENSURE_ASAN_INITED(); 37252fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany unsigned char c1 = 0, c2 = 0; 37352fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany const unsigned char *s1 = (const unsigned char*)a1; 37452fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany const unsigned char *s2 = (const unsigned char*)a2; 37552fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany size_t i; 37652fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany for (i = 0; i < size; i++) { 37752fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany c1 = s1[i]; 37852fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany c2 = s2[i]; 37952fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany if (c1 != c2) break; 38052fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany } 38152fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany ASAN_READ_RANGE(s1, Min(i + 1, size)); 38252fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany ASAN_READ_RANGE(s2, Min(i + 1, size)); 38352fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany return CharCmp(c1, c2); 38452fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany} 38552fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany 386f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void*, memcpy, void *to, const void *from, size_t size) { 3871e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // memcpy is called during __asan_init() from the internals 3881e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // of printf(...). 3891e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (asan_init_is_running) { 3901e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return real_memcpy(to, from, size); 3911e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 392e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany ENSURE_ASAN_INITED(); 3931e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (FLAG_replace_intrin) { 394c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany if (to != from) { 395c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany // We do not treat memcpy with to==from as a bug. 396c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany // See http://llvm.org/bugs/show_bug.cgi?id=11763. 397c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany CHECK_RANGES_OVERLAP("memcpy", to, size, from, size); 398c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany } 3991e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_WRITE_RANGE(from, size); 4001e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_READ_RANGE(to, size); 4011e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 4021e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return real_memcpy(to, from, size); 4031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 4041e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 405f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void*, memmove, void *to, const void *from, size_t size) { 406e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany ENSURE_ASAN_INITED(); 4071e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (FLAG_replace_intrin) { 4081e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_WRITE_RANGE(from, size); 4091e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_READ_RANGE(to, size); 4101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 4111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return real_memmove(to, from, size); 4121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 4131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 414f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void*, memset, void *block, int c, size_t size) { 415e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany // memset is called inside INTERCEPT_FUNCTION on Mac. 416e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany if (asan_init_is_running) { 417e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany return real_memset(block, c, size); 418e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany } 419e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany ENSURE_ASAN_INITED(); 4201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (FLAG_replace_intrin) { 4211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_WRITE_RANGE(block, size); 4221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 4231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return real_memset(block, c, size); 4241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 4251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 426f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strchr, const char *str, int c) { 427e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany ENSURE_ASAN_INITED(); 4281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany char *result = real_strchr(str, c); 4291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (FLAG_replace_str) { 4301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany size_t bytes_read = (result ? result - str : real_strlen(str)) + 1; 4311e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_READ_RANGE(str, bytes_read); 4321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 4331e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return result; 4341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 4351e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 436f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov#ifndef __APPLE__ 437f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void*, index, const char *string, int c) 438f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov __attribute__((alias(WRAPPER_NAME(strchr)))); 439f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov#else 440f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovDEFINE_REAL(void*, index, const char *string, int c); 441f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov#endif 442f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov 443f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(int, strcasecmp, const char *s1, const char *s2) { 444af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany ENSURE_ASAN_INITED(); 445af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany unsigned char c1, c2; 446af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany size_t i; 447af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany for (i = 0; ; i++) { 448af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany c1 = (unsigned char)s1[i]; 449af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany c2 = (unsigned char)s2[i]; 450af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break; 451af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany } 452af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany ASAN_READ_RANGE(s1, i + 1); 453af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany ASAN_READ_RANGE(s2, i + 1); 454af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany return CharCaseCmp(c1, c2); 455af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany} 456af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany 457f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strcat, char *to, const char *from) { // NOLINT 4580985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany ENSURE_ASAN_INITED(); 4590985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany if (FLAG_replace_str) { 4600985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany size_t from_length = real_strlen(from); 4610985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany ASAN_READ_RANGE(from, from_length + 1); 4620985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany if (from_length > 0) { 4630985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany size_t to_length = real_strlen(to); 4640985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany ASAN_READ_RANGE(to, to_length); 4650985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany ASAN_WRITE_RANGE(to + to_length, from_length + 1); 466c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany CHECK_RANGES_OVERLAP("strcat", to, to_length + 1, from, from_length + 1); 4670985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany } 4680985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany } 4690985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany return real_strcat(to, from); 4700985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany} 4710985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany 472f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(int, strcmp, const char *s1, const char *s2) { 473f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryany if (!asan_inited) { 474f3810ea150e140f49bd62123885df922fe3c3b81Kostya Serebryany return internal_strcmp(s1, s2); 4751e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 4761e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany unsigned char c1, c2; 4771e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany size_t i; 4781e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany for (i = 0; ; i++) { 4791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany c1 = (unsigned char)s1[i]; 4801e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany c2 = (unsigned char)s2[i]; 4811e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (c1 != c2 || c1 == '\0') break; 4821e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 4831e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_READ_RANGE(s1, i + 1); 4841e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_READ_RANGE(s2, i + 1); 4851e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return CharCmp(c1, c2); 4861e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 4871e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 488f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strcpy, char *to, const char *from) { // NOLINT 4891e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // strcpy is called from malloc_default_purgeable_zone() 4901e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // in __asan::ReplaceSystemAlloc() on Mac. 4911e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (asan_init_is_running) { 4921e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return real_strcpy(to, from); 4931e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 494e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany ENSURE_ASAN_INITED(); 4951e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (FLAG_replace_str) { 4961e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany size_t from_size = real_strlen(from) + 1; 497c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size); 4981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_READ_RANGE(from, from_size); 4991e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_WRITE_RANGE(to, from_size); 5001e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 5011e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return real_strcpy(to, from); 5021e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 5031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 504f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strdup, const char *s) { 505e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany ENSURE_ASAN_INITED(); 5061e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (FLAG_replace_str) { 5071e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany size_t length = real_strlen(s); 5081e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_READ_RANGE(s, length + 1); 5091e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 5101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return real_strdup(s); 5111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 5121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 513f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(size_t, strlen, const char *s) { 5141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // strlen is called from malloc_default_purgeable_zone() 5151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // in __asan::ReplaceSystemAlloc() on Mac. 5161e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (asan_init_is_running) { 5171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return real_strlen(s); 5181e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 519e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany ENSURE_ASAN_INITED(); 5201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany size_t length = real_strlen(s); 5211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (FLAG_replace_str) { 5221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_READ_RANGE(s, length + 1); 5231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 5241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return length; 5251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 5261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 527f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, size_t n) { 528af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany ENSURE_ASAN_INITED(); 529af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany unsigned char c1 = 0, c2 = 0; 530af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany size_t i; 531f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov for (i = 0; i < n; i++) { 532af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany c1 = (unsigned char)s1[i]; 533af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany c2 = (unsigned char)s2[i]; 534af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break; 535af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany } 536f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov ASAN_READ_RANGE(s1, Min(i + 1, n)); 537f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov ASAN_READ_RANGE(s2, Min(i + 1, n)); 538af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany return CharCaseCmp(c1, c2); 539af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany} 540af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany 541f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(int, strncmp, const char *s1, const char *s2, size_t size) { 5421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // strncmp is called from malloc_default_purgeable_zone() 5431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // in __asan::ReplaceSystemAlloc() on Mac. 5441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (asan_init_is_running) { 5451e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return real_strncmp(s1, s2, size); 5461e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 5471e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany unsigned char c1 = 0, c2 = 0; 5481e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany size_t i; 5491e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany for (i = 0; i < size; i++) { 5501e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany c1 = (unsigned char)s1[i]; 5511e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany c2 = (unsigned char)s2[i]; 5521e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (c1 != c2 || c1 == '\0') break; 5531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 5542d8b3bdb112ebb8ed3f15ee41d4cebcd683b41b0Kostya Serebryany ASAN_READ_RANGE(s1, Min(i + 1, size)); 5552d8b3bdb112ebb8ed3f15ee41d4cebcd683b41b0Kostya Serebryany ASAN_READ_RANGE(s2, Min(i + 1, size)); 5561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return CharCmp(c1, c2); 5571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 5581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 559f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strncpy, char *to, const char *from, size_t size) { 560e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany ENSURE_ASAN_INITED(); 5611e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (FLAG_replace_str) { 5622d8b3bdb112ebb8ed3f15ee41d4cebcd683b41b0Kostya Serebryany size_t from_size = Min(size, internal_strnlen(from, size) + 1); 563c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size); 5641e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_READ_RANGE(from, from_size); 5651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_WRITE_RANGE(to, size); 5661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 5671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return real_strncpy(to, from, size); 5681e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 5691e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 5701e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#ifndef __APPLE__ 571f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(size_t, strnlen, const char *s, size_t maxlen) { 572e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany ENSURE_ASAN_INITED(); 5731e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany size_t length = real_strnlen(s, maxlen); 5741e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (FLAG_replace_str) { 5752d8b3bdb112ebb8ed3f15ee41d4cebcd683b41b0Kostya Serebryany ASAN_READ_RANGE(s, Min(length + 1, maxlen)); 5761e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 5771e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return length; 5781e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 579d66a8d8f56c66c9749b6d75c61870a121d4d9307Kostya Serebryany#endif 580547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany 581547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany// ---------------------- InitializeAsanInterceptors ---------------- {{{1 582547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryanynamespace __asan { 583547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryanyvoid InitializeAsanInterceptors() { 584547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany#ifndef __APPLE__ 585547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany INTERCEPT_FUNCTION(index); 586547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany#else 587547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany OVERRIDE_FUNCTION(index, WRAP(strchr)); 588547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany#endif 589547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany INTERCEPT_FUNCTION(memcmp); 590547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany INTERCEPT_FUNCTION(memmove); 591573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko#ifdef __APPLE__ 592573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko // Wrap memcpy() on OS X 10.6 only, because on 10.7 memcpy() and memmove() 593573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko // are resolved into memmove$VARIANT$sse42. 594573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko // See also http://code.google.com/p/address-sanitizer/issues/detail?id=34. 595573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko // TODO(glider): need to check dynamically that memcpy() and memmove() are 596573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko // actually the same function. 597573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko if (GetMacosVersion() == MACOS_VERSION_SNOW_LEOPARD) { 598573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko INTERCEPT_FUNCTION(memcpy); 599573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko } else { 600573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko real_memcpy = real_memmove; 601573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko } 602573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko#else 603573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko // Always wrap memcpy() on non-Darwin platforms. 604573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko INTERCEPT_FUNCTION(memcpy); 605573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko#endif 606547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany INTERCEPT_FUNCTION(memset); 607547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany INTERCEPT_FUNCTION(strcasecmp); 608547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany INTERCEPT_FUNCTION(strcat); // NOLINT 609547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany INTERCEPT_FUNCTION(strchr); 610547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany INTERCEPT_FUNCTION(strcmp); 611547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany INTERCEPT_FUNCTION(strcpy); // NOLINT 612547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany INTERCEPT_FUNCTION(strdup); 613547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany INTERCEPT_FUNCTION(strlen); 614547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany INTERCEPT_FUNCTION(strncasecmp); 615547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany INTERCEPT_FUNCTION(strncmp); 616547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany INTERCEPT_FUNCTION(strncpy); 617547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany 618547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany INTERCEPT_FUNCTION(sigaction); 619547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany INTERCEPT_FUNCTION(signal); 620547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany INTERCEPT_FUNCTION(longjmp); 621547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany INTERCEPT_FUNCTION(_longjmp); 622547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany INTERCEPT_FUNCTION_IF_EXISTS(__cxa_throw); 623547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany INTERCEPT_FUNCTION(pthread_create); 624547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany 625547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany#ifdef __APPLE__ 626547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany INTERCEPT_FUNCTION(dispatch_async_f); 627547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany INTERCEPT_FUNCTION(dispatch_sync_f); 628547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany INTERCEPT_FUNCTION(dispatch_after_f); 629547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany INTERCEPT_FUNCTION(dispatch_barrier_async_f); 630547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany INTERCEPT_FUNCTION(dispatch_group_async_f); 631547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany // We don't need to intercept pthread_workqueue_additem_np() to support the 632547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany // libdispatch API, but it helps us to debug the unsupported functions. Let's 633547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany // intercept it only during verbose runs. 634547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany if (FLAG_v >= 2) { 635547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany INTERCEPT_FUNCTION(pthread_workqueue_additem_np); 636547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany } 637431e51782d62d1257348e41e24da6b544fe70507Alexander Potapenko // Normally CFStringCreateCopy should not copy constant CF strings. 638431e51782d62d1257348e41e24da6b544fe70507Alexander Potapenko // Replacing the default CFAllocator causes constant strings to be copied 639431e51782d62d1257348e41e24da6b544fe70507Alexander Potapenko // rather than just returned, which leads to bugs in big applications like 640431e51782d62d1257348e41e24da6b544fe70507Alexander Potapenko // Chromium and WebKit, see 641431e51782d62d1257348e41e24da6b544fe70507Alexander Potapenko // http://code.google.com/p/address-sanitizer/issues/detail?id=10 642431e51782d62d1257348e41e24da6b544fe70507Alexander Potapenko // Until this problem is fixed we need to check that the string is 643431e51782d62d1257348e41e24da6b544fe70507Alexander Potapenko // non-constant before calling CFStringCreateCopy. 644431e51782d62d1257348e41e24da6b544fe70507Alexander Potapenko INTERCEPT_FUNCTION(CFStringCreateCopy); 645547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany#else 646547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany // On Darwin siglongjmp tailcalls longjmp, so we don't want to intercept it 647547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany // there. 648547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany INTERCEPT_FUNCTION(siglongjmp); 649547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany#endif 650547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany 651547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany#ifndef __APPLE__ 652547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany INTERCEPT_FUNCTION(strnlen); 653547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany#endif 654547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany if (FLAG_v > 0) { 655547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany Printf("AddressSanitizer: libc interceptors initialized\n"); 656547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany } 657547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany} 658547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany 659547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany} // namespace __asan 660