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