asan_interceptors.cc revision 487fee7f6f7497906a00d7d2fe2c75e6d5d4feb1
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===-- asan_interceptors.cc ----------------------------------------------===// 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The LLVM Compiler Infrastructure 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file is distributed under the University of Illinois Open Source 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// License. See LICENSE.TXT for details. 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file is a part of AddressSanitizer, an address sanity checker. 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Intercept various libc functions. 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "asan_interceptors.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "asan_allocator.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "asan_interface.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "asan_internal.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "asan_mapping.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "asan_report.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "asan_stack.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "asan_stats.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "asan_thread_registry.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "interception/interception.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sanitizer_common/sanitizer_libc.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use macro to describe if specific function should be 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// intercepted on a given platform. 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(_WIN32) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define ASAN_INTERCEPT_ATOLL_AND_STRTOLL 1 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define ASAN_INTERCEPT__LONGJMP 1 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define ASAN_INTERCEPT_STRDUP 1 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP 1 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define ASAN_INTERCEPT_INDEX 1 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define ASAN_INTERCEPT_PTHREAD_CREATE 1 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define ASAN_INTERCEPT_ATOLL_AND_STRTOLL 0 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define ASAN_INTERCEPT__LONGJMP 0 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define ASAN_INTERCEPT_STRDUP 0 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP 0 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define ASAN_INTERCEPT_INDEX 0 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define ASAN_INTERCEPT_PTHREAD_CREATE 0 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__linux__) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 1 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 0 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(__APPLE__) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define ASAN_INTERCEPT_STRNLEN 1 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define ASAN_INTERCEPT_STRNLEN 0 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(ANDROID) && !defined(_WIN32) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 1 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 0 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// On Darwin siglongjmp tailcalls longjmp, so we don't want to intercept it 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// there. 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(_WIN32) && !defined(__APPLE__) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define ASAN_INTERCEPT_SIGLONGJMP 1 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define ASAN_INTERCEPT_SIGLONGJMP 0 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if ASAN_HAS_EXCEPTIONS && !defined(_WIN32) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define ASAN_INTERCEPT___CXA_THROW 1 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define ASAN_INTERCEPT___CXA_THROW 0 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use extern declarations of intercepted functions on Mac and Windows 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to avoid including system headers. 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__APPLE__) || (defined(_WIN32) && !defined(_DLL)) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// signal.h 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct sigaction; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int sigaction(int sig, const struct sigaction *act, 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct sigaction *oldact); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void *signal(int signum, void *handler); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# endif 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// setjmp.h 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void longjmp(void* env, int value); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# if ASAN_INTERCEPT__LONGJMP 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void _longjmp(void *env, int value); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# endif 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# if ASAN_INTERCEPT___CXA_THROW 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void __cxa_throw(void *a, void *b, void *c); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// string.h / strings.h 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int memcmp(const void *a1, const void *a2, uptr size); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* memmove(void *to, const void *from, uptr size); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* memcpy(void *to, const void *from, uptr size); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* memset(void *block, int c, uptr size); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)char* strchr(const char *str, int c); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)char* strcat(char *to, const char* from); // NOLINT 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)char *strncat(char *to, const char* from, uptr size); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)char* strcpy(char *to, const char* from); // NOLINT 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)char* strncpy(char *to, const char* from, uptr size); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int strcmp(const char *s1, const char* s2); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int strncmp(const char *s1, const char* s2, uptr size); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uptr strlen(const char *s); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# if ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int strcasecmp(const char *s1, const char *s2); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int strncasecmp(const char *s1, const char *s2, uptr n); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# endif 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# if ASAN_INTERCEPT_STRDUP 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)char* strdup(const char *s); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# endif 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# if ASAN_INTERCEPT_STRNLEN 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uptr strnlen(const char *s, uptr maxlen); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# endif 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# if ASAN_INTERCEPT_INDEX 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)char* index(const char *string, int c); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# endif 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// stdlib.h 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int atoi(const char *nptr); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)long atol(const char *nptr); // NOLINT 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)long strtol(const char *nptr, char **endptr, int base); // NOLINT 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# if ASAN_INTERCEPT_ATOLL_AND_STRTOLL 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)long long atoll(const char *nptr); // NOLINT 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)long long strtoll(const char *nptr, char **endptr, int base); // NOLINT 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# endif 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Windows threads. 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# if defined(_WIN32) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)__declspec(dllimport) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* __stdcall CreateThread(void *sec, uptr st, void* start, 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *arg, DWORD fl, DWORD *id); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# endif 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Posix threads. 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# if ASAN_INTERCEPT_PTHREAD_CREATE 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int pthread_create(void *thread, void *attr, void *(*start_routine)(void*), 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *arg); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# endif 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // extern "C" 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace __asan { 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Instruments read/write access to a single byte in memory. 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// On error calls __asan_report_error, which aborts the program. 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ACCESS_ADDRESS(address, isWrite) do { \ 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!AddrIsInMem(address) || AddressIsPoisoned(address)) { \ 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GET_CURRENT_PC_BP_SP; \ 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __asan_report_error(pc, bp, sp, address, isWrite, /* access_size */ 1); \ 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } \ 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} while (0) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE, 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and ASAN_WRITE_RANGE as macro instead of function so 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that no extra frames are created, and stack trace contains 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// relevant information only. 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Instruments read/write access to a memory range. 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// More complex implementation is possible, for now just 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// checking the first and the last byte of a range. 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ACCESS_MEMORY_RANGE(offset, size, isWrite) do { \ 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (size > 0) { \ 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uptr ptr = (uptr)(offset); \ 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ACCESS_ADDRESS(ptr, isWrite); \ 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ACCESS_ADDRESS(ptr + (size) - 1, isWrite); \ 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } \ 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} while (0) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ASAN_READ_RANGE(offset, size) do { \ 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ACCESS_MEMORY_RANGE(offset, size, false); \ 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} while (0) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ASAN_WRITE_RANGE(offset, size) do { \ 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ACCESS_MEMORY_RANGE(offset, size, true); \ 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} while (0) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Behavior of functions like "memcpy" or "strcpy" is undefined 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// if memory intervals overlap. We report error in this case. 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Macro is used to avoid creation of new frames. 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline bool RangesOverlap(const char *offset1, uptr length1, 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *offset2, uptr length2) { 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !((offset1 + length1 <= offset2) || (offset2 + length2 <= offset1)); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CHECK_RANGES_OVERLAP(name, _offset1, length1, _offset2, length2) do { \ 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *offset1 = (const char*)_offset1; \ 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *offset2 = (const char*)_offset2; \ 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (RangesOverlap(offset1, length1, offset2, length2)) { \ 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GET_STACK_TRACE_HERE(kStackTraceMax); \ 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportStringFunctionMemoryRangesOverlap(name, offset1, length1, \ 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) offset2, length2, &stack); \ 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } \ 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} while (0) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ENSURE_ASAN_INITED() do { \ 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(!asan_init_is_running); \ 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!asan_inited) { \ 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __asan_init(); \ 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } \ 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} while (0) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) { 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if ASAN_INTERCEPT_STRNLEN 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (REAL(strnlen) != 0) { 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return REAL(strnlen)(s, maxlen); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return internal_strnlen(s, maxlen); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace __asan 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------- Wrappers ---------------- {{{1 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace __asan; // NOLINT 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) { 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AsanThread *t = (AsanThread*)arg; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) asanThreadRegistry().SetCurrent(t); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return t->ThreadStart(); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if ASAN_INTERCEPT_PTHREAD_CREATE 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)INTERCEPTOR(int, pthread_create, void *thread, 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *attr, void *(*start_routine)(void*), void *arg) { 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GET_STACK_TRACE_HERE(kStackTraceMax); 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u32 current_tid = asanThreadRegistry().GetCurrentTidOrInvalid(); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AsanThread *t = AsanThread::Create(current_tid, start_routine, arg, &stack); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) asanThreadRegistry().RegisterThread(t); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return REAL(pthread_create)(thread, attr, asan_thread_start, t); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // ASAN_INTERCEPT_PTHREAD_CREATE 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)INTERCEPTOR(void*, signal, int signum, void *handler) { 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!AsanInterceptsSignal(signum)) { 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return REAL(signal)(signum, handler); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)INTERCEPTOR(int, sigaction, int signum, const struct sigaction *act, 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct sigaction *oldact) { 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!AsanInterceptsSignal(signum)) { 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return REAL(sigaction)(signum, act, oldact); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif ASAN_POSIX 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We need to have defined REAL(sigaction) on posix systems. 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_REAL(int, sigaction, int signum, const struct sigaction *act, 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct sigaction *oldact); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)INTERCEPTOR(void, longjmp, void *env, int val) { 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __asan_handle_no_return(); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) REAL(longjmp)(env, val); 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if ASAN_INTERCEPT__LONGJMP 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)INTERCEPTOR(void, _longjmp, void *env, int val) { 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __asan_handle_no_return(); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) REAL(_longjmp)(env, val); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if ASAN_INTERCEPT_SIGLONGJMP 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)INTERCEPTOR(void, siglongjmp, void *env, int val) { 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __asan_handle_no_return(); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) REAL(siglongjmp)(env, val); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 276#endif 277 278#if ASAN_INTERCEPT___CXA_THROW 279INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) { 280 CHECK(REAL(__cxa_throw)); 281 __asan_handle_no_return(); 282 REAL(__cxa_throw)(a, b, c); 283} 284#endif 285 286// intercept mlock and friends. 287// Since asan maps 16T of RAM, mlock is completely unfriendly to asan. 288// All functions return 0 (success). 289static void MlockIsUnsupported() { 290 static bool printed = 0; 291 if (printed) return; 292 printed = true; 293 Printf("INFO: AddressSanitizer ignores mlock/mlockall/munlock/munlockall\n"); 294} 295 296extern "C" { 297INTERCEPTOR_ATTRIBUTE 298int mlock(const void *addr, uptr len) { 299 MlockIsUnsupported(); 300 return 0; 301} 302 303INTERCEPTOR_ATTRIBUTE 304int munlock(const void *addr, uptr len) { 305 MlockIsUnsupported(); 306 return 0; 307} 308 309INTERCEPTOR_ATTRIBUTE 310int mlockall(int flags) { 311 MlockIsUnsupported(); 312 return 0; 313} 314 315INTERCEPTOR_ATTRIBUTE 316int munlockall(void) { 317 MlockIsUnsupported(); 318 return 0; 319} 320} // extern "C" 321 322static inline int CharCmp(unsigned char c1, unsigned char c2) { 323 return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1; 324} 325 326static inline int CharCaseCmp(unsigned char c1, unsigned char c2) { 327 int c1_low = ToLower(c1); 328 int c2_low = ToLower(c2); 329 return c1_low - c2_low; 330} 331 332INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) { 333 ENSURE_ASAN_INITED(); 334 unsigned char c1 = 0, c2 = 0; 335 const unsigned char *s1 = (const unsigned char*)a1; 336 const unsigned char *s2 = (const unsigned char*)a2; 337 uptr i; 338 for (i = 0; i < size; i++) { 339 c1 = s1[i]; 340 c2 = s2[i]; 341 if (c1 != c2) break; 342 } 343 ASAN_READ_RANGE(s1, Min(i + 1, size)); 344 ASAN_READ_RANGE(s2, Min(i + 1, size)); 345 return CharCmp(c1, c2); 346} 347 348INTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) { 349 // memcpy is called during __asan_init() from the internals 350 // of printf(...). 351 if (asan_init_is_running) { 352 return REAL(memcpy)(to, from, size); 353 } 354 ENSURE_ASAN_INITED(); 355 if (flags()->replace_intrin) { 356 if (to != from) { 357 // We do not treat memcpy with to==from as a bug. 358 // See http://llvm.org/bugs/show_bug.cgi?id=11763. 359 CHECK_RANGES_OVERLAP("memcpy", to, size, from, size); 360 } 361 ASAN_WRITE_RANGE(from, size); 362 ASAN_READ_RANGE(to, size); 363 } 364 return REAL(memcpy)(to, from, size); 365} 366 367INTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) { 368 if (asan_init_is_running) { 369 return REAL(memmove)(to, from, size); 370 } 371 ENSURE_ASAN_INITED(); 372 if (flags()->replace_intrin) { 373 ASAN_WRITE_RANGE(from, size); 374 ASAN_READ_RANGE(to, size); 375 } 376 return REAL(memmove)(to, from, size); 377} 378 379INTERCEPTOR(void*, memset, void *block, int c, uptr size) { 380 // memset is called inside Printf. 381 if (asan_init_is_running) { 382 return REAL(memset)(block, c, size); 383 } 384 ENSURE_ASAN_INITED(); 385 if (flags()->replace_intrin) { 386 ASAN_WRITE_RANGE(block, size); 387 } 388 return REAL(memset)(block, c, size); 389} 390 391INTERCEPTOR(char*, strchr, const char *str, int c) { 392 ENSURE_ASAN_INITED(); 393 char *result = REAL(strchr)(str, c); 394 if (flags()->replace_str) { 395 uptr bytes_read = (result ? result - str : REAL(strlen)(str)) + 1; 396 ASAN_READ_RANGE(str, bytes_read); 397 } 398 return result; 399} 400 401#if ASAN_INTERCEPT_INDEX 402# if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 403INTERCEPTOR(char*, index, const char *string, int c) 404 ALIAS(WRAPPER_NAME(strchr)); 405# else 406DEFINE_REAL(char*, index, const char *string, int c) 407# endif 408#endif // ASAN_INTERCEPT_INDEX 409 410// For both strcat() and strncat() we need to check the validity of |to| 411// argument irrespective of the |from| length. 412INTERCEPTOR(char*, strcat, char *to, const char *from) { // NOLINT 413 ENSURE_ASAN_INITED(); 414 if (flags()->replace_str) { 415 uptr from_length = REAL(strlen)(from); 416 ASAN_READ_RANGE(from, from_length + 1); 417 uptr to_length = REAL(strlen)(to); 418 ASAN_READ_RANGE(to, to_length); 419 ASAN_WRITE_RANGE(to + to_length, from_length + 1); 420 // If the copying actually happens, the |from| string should not overlap 421 // with the resulting string starting at |to|, which has a length of 422 // to_length + from_length + 1. 423 if (from_length > 0) { 424 CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1, 425 from, from_length + 1); 426 } 427 } 428 return REAL(strcat)(to, from); // NOLINT 429} 430 431INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) { 432 ENSURE_ASAN_INITED(); 433 if (flags()->replace_str) { 434 uptr from_length = MaybeRealStrnlen(from, size); 435 uptr copy_length = Min(size, from_length + 1); 436 ASAN_READ_RANGE(from, copy_length); 437 uptr to_length = REAL(strlen)(to); 438 ASAN_READ_RANGE(to, to_length); 439 ASAN_WRITE_RANGE(to + to_length, from_length + 1); 440 if (from_length > 0) { 441 CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1, 442 from, copy_length); 443 } 444 } 445 return REAL(strncat)(to, from, size); 446} 447 448INTERCEPTOR(int, strcmp, const char *s1, const char *s2) { 449 if (asan_init_is_running) { 450 return REAL(strcmp)(s1, s2); 451 } 452 ENSURE_ASAN_INITED(); 453 unsigned char c1, c2; 454 uptr i; 455 for (i = 0; ; i++) { 456 c1 = (unsigned char)s1[i]; 457 c2 = (unsigned char)s2[i]; 458 if (c1 != c2 || c1 == '\0') break; 459 } 460 ASAN_READ_RANGE(s1, i + 1); 461 ASAN_READ_RANGE(s2, i + 1); 462 return CharCmp(c1, c2); 463} 464 465INTERCEPTOR(char*, strcpy, char *to, const char *from) { // NOLINT 466 // strcpy is called from malloc_default_purgeable_zone() 467 // in __asan::ReplaceSystemAlloc() on Mac. 468 if (asan_init_is_running) { 469 return REAL(strcpy)(to, from); // NOLINT 470 } 471 ENSURE_ASAN_INITED(); 472 if (flags()->replace_str) { 473 uptr from_size = REAL(strlen)(from) + 1; 474 CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size); 475 ASAN_READ_RANGE(from, from_size); 476 ASAN_WRITE_RANGE(to, from_size); 477 } 478 return REAL(strcpy)(to, from); // NOLINT 479} 480 481#if ASAN_INTERCEPT_STRDUP 482INTERCEPTOR(char*, strdup, const char *s) { 483 ENSURE_ASAN_INITED(); 484 if (flags()->replace_str) { 485 uptr length = REAL(strlen)(s); 486 ASAN_READ_RANGE(s, length + 1); 487 } 488 return REAL(strdup)(s); 489} 490#endif 491 492INTERCEPTOR(uptr, strlen, const char *s) { 493 // strlen is called from malloc_default_purgeable_zone() 494 // in __asan::ReplaceSystemAlloc() on Mac. 495 if (asan_init_is_running) { 496 return REAL(strlen)(s); 497 } 498 ENSURE_ASAN_INITED(); 499 uptr length = REAL(strlen)(s); 500 if (flags()->replace_str) { 501 ASAN_READ_RANGE(s, length + 1); 502 } 503 return length; 504} 505 506#if ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP 507INTERCEPTOR(int, strcasecmp, const char *s1, const char *s2) { 508 ENSURE_ASAN_INITED(); 509 unsigned char c1, c2; 510 uptr i; 511 for (i = 0; ; i++) { 512 c1 = (unsigned char)s1[i]; 513 c2 = (unsigned char)s2[i]; 514 if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break; 515 } 516 ASAN_READ_RANGE(s1, i + 1); 517 ASAN_READ_RANGE(s2, i + 1); 518 return CharCaseCmp(c1, c2); 519} 520 521INTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, uptr n) { 522 ENSURE_ASAN_INITED(); 523 unsigned char c1 = 0, c2 = 0; 524 uptr i; 525 for (i = 0; i < n; i++) { 526 c1 = (unsigned char)s1[i]; 527 c2 = (unsigned char)s2[i]; 528 if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break; 529 } 530 ASAN_READ_RANGE(s1, Min(i + 1, n)); 531 ASAN_READ_RANGE(s2, Min(i + 1, n)); 532 return CharCaseCmp(c1, c2); 533} 534#endif // ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP 535 536INTERCEPTOR(int, strncmp, const char *s1, const char *s2, uptr size) { 537 // strncmp is called from malloc_default_purgeable_zone() 538 // in __asan::ReplaceSystemAlloc() on Mac. 539 if (asan_init_is_running) { 540 return REAL(strncmp)(s1, s2, size); 541 } 542 ENSURE_ASAN_INITED(); 543 unsigned char c1 = 0, c2 = 0; 544 uptr i; 545 for (i = 0; i < size; i++) { 546 c1 = (unsigned char)s1[i]; 547 c2 = (unsigned char)s2[i]; 548 if (c1 != c2 || c1 == '\0') break; 549 } 550 ASAN_READ_RANGE(s1, Min(i + 1, size)); 551 ASAN_READ_RANGE(s2, Min(i + 1, size)); 552 return CharCmp(c1, c2); 553} 554 555INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) { 556 ENSURE_ASAN_INITED(); 557 if (flags()->replace_str) { 558 uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1); 559 CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size); 560 ASAN_READ_RANGE(from, from_size); 561 ASAN_WRITE_RANGE(to, size); 562 } 563 return REAL(strncpy)(to, from, size); 564} 565 566#if ASAN_INTERCEPT_STRNLEN 567INTERCEPTOR(uptr, strnlen, const char *s, uptr maxlen) { 568 ENSURE_ASAN_INITED(); 569 uptr length = REAL(strnlen)(s, maxlen); 570 if (flags()->replace_str) { 571 ASAN_READ_RANGE(s, Min(length + 1, maxlen)); 572 } 573 return length; 574} 575#endif // ASAN_INTERCEPT_STRNLEN 576 577static inline bool IsValidStrtolBase(int base) { 578 return (base == 0) || (2 <= base && base <= 36); 579} 580 581static inline void FixRealStrtolEndptr(const char *nptr, char **endptr) { 582 CHECK(endptr != 0); 583 if (nptr == *endptr) { 584 // No digits were found at strtol call, we need to find out the last 585 // symbol accessed by strtoll on our own. 586 // We get this symbol by skipping leading blanks and optional +/- sign. 587 while (IsSpace(*nptr)) nptr++; 588 if (*nptr == '+' || *nptr == '-') nptr++; 589 *endptr = (char*)nptr; 590 } 591 CHECK(*endptr >= nptr); 592} 593 594INTERCEPTOR(long, strtol, const char *nptr, // NOLINT 595 char **endptr, int base) { 596 ENSURE_ASAN_INITED(); 597 if (!flags()->replace_str) { 598 return REAL(strtol)(nptr, endptr, base); 599 } 600 char *real_endptr; 601 long result = REAL(strtol)(nptr, &real_endptr, base); // NOLINT 602 if (endptr != 0) { 603 *endptr = real_endptr; 604 } 605 if (IsValidStrtolBase(base)) { 606 FixRealStrtolEndptr(nptr, &real_endptr); 607 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 608 } 609 return result; 610} 611 612INTERCEPTOR(int, atoi, const char *nptr) { 613 ENSURE_ASAN_INITED(); 614 if (!flags()->replace_str) { 615 return REAL(atoi)(nptr); 616 } 617 char *real_endptr; 618 // "man atoi" tells that behavior of atoi(nptr) is the same as 619 // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the 620 // parsed integer can't be stored in *long* type (even if it's 621 // different from int). So, we just imitate this behavior. 622 int result = REAL(strtol)(nptr, &real_endptr, 10); 623 FixRealStrtolEndptr(nptr, &real_endptr); 624 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 625 return result; 626} 627 628INTERCEPTOR(long, atol, const char *nptr) { // NOLINT 629 ENSURE_ASAN_INITED(); 630 if (!flags()->replace_str) { 631 return REAL(atol)(nptr); 632 } 633 char *real_endptr; 634 long result = REAL(strtol)(nptr, &real_endptr, 10); // NOLINT 635 FixRealStrtolEndptr(nptr, &real_endptr); 636 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 637 return result; 638} 639 640#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL 641INTERCEPTOR(long long, strtoll, const char *nptr, // NOLINT 642 char **endptr, int base) { 643 ENSURE_ASAN_INITED(); 644 if (!flags()->replace_str) { 645 return REAL(strtoll)(nptr, endptr, base); 646 } 647 char *real_endptr; 648 long long result = REAL(strtoll)(nptr, &real_endptr, base); // NOLINT 649 if (endptr != 0) { 650 *endptr = real_endptr; 651 } 652 // If base has unsupported value, strtoll can exit with EINVAL 653 // without reading any characters. So do additional checks only 654 // if base is valid. 655 if (IsValidStrtolBase(base)) { 656 FixRealStrtolEndptr(nptr, &real_endptr); 657 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 658 } 659 return result; 660} 661 662INTERCEPTOR(long long, atoll, const char *nptr) { // NOLINT 663 ENSURE_ASAN_INITED(); 664 if (!flags()->replace_str) { 665 return REAL(atoll)(nptr); 666 } 667 char *real_endptr; 668 long long result = REAL(strtoll)(nptr, &real_endptr, 10); // NOLINT 669 FixRealStrtolEndptr(nptr, &real_endptr); 670 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 671 return result; 672} 673#endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL 674 675#define ASAN_INTERCEPT_FUNC(name) do { \ 676 if (!INTERCEPT_FUNCTION(name) && flags()->verbosity > 0) \ 677 Report("AddressSanitizer: failed to intercept '" #name "'\n"); \ 678 } while (0) 679 680#if defined(_WIN32) 681INTERCEPTOR_WINAPI(DWORD, CreateThread, 682 void* security, uptr stack_size, 683 DWORD (__stdcall *start_routine)(void*), void* arg, 684 DWORD flags, void* tid) { 685 GET_STACK_TRACE_HERE(kStackTraceMax); 686 u32 current_tid = asanThreadRegistry().GetCurrentTidOrInvalid(); 687 AsanThread *t = AsanThread::Create(current_tid, start_routine, arg, &stack); 688 asanThreadRegistry().RegisterThread(t); 689 return REAL(CreateThread)(security, stack_size, 690 asan_thread_start, t, flags, tid); 691} 692 693namespace __asan { 694void InitializeWindowsInterceptors() { 695 ASAN_INTERCEPT_FUNC(CreateThread); 696} 697 698} // namespace __asan 699#endif 700 701// ---------------------- InitializeAsanInterceptors ---------------- {{{1 702namespace __asan { 703void InitializeAsanInterceptors() { 704 static bool was_called_once; 705 CHECK(was_called_once == false); 706 was_called_once = true; 707 // Intercept mem* functions. 708 ASAN_INTERCEPT_FUNC(memcmp); 709 ASAN_INTERCEPT_FUNC(memmove); 710 ASAN_INTERCEPT_FUNC(memset); 711 if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) { 712 ASAN_INTERCEPT_FUNC(memcpy); 713 } else { 714 REAL(memcpy) = REAL(memmove); 715 } 716 717 // Intercept str* functions. 718 ASAN_INTERCEPT_FUNC(strcat); // NOLINT 719 ASAN_INTERCEPT_FUNC(strchr); 720 ASAN_INTERCEPT_FUNC(strcmp); 721 ASAN_INTERCEPT_FUNC(strcpy); // NOLINT 722 ASAN_INTERCEPT_FUNC(strlen); 723 ASAN_INTERCEPT_FUNC(strncat); 724 ASAN_INTERCEPT_FUNC(strncmp); 725 ASAN_INTERCEPT_FUNC(strncpy); 726#if ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP 727 ASAN_INTERCEPT_FUNC(strcasecmp); 728 ASAN_INTERCEPT_FUNC(strncasecmp); 729#endif 730#if ASAN_INTERCEPT_STRDUP 731 ASAN_INTERCEPT_FUNC(strdup); 732#endif 733#if ASAN_INTERCEPT_STRNLEN 734 ASAN_INTERCEPT_FUNC(strnlen); 735#endif 736#if ASAN_INTERCEPT_INDEX 737# if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 738 ASAN_INTERCEPT_FUNC(index); 739# else 740 CHECK(OVERRIDE_FUNCTION(index, WRAP(strchr))); 741# endif 742#endif 743 744 ASAN_INTERCEPT_FUNC(atoi); 745 ASAN_INTERCEPT_FUNC(atol); 746 ASAN_INTERCEPT_FUNC(strtol); 747#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL 748 ASAN_INTERCEPT_FUNC(atoll); 749 ASAN_INTERCEPT_FUNC(strtoll); 750#endif 751 752 // Intecept signal- and jump-related functions. 753 ASAN_INTERCEPT_FUNC(longjmp); 754#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 755 ASAN_INTERCEPT_FUNC(sigaction); 756 ASAN_INTERCEPT_FUNC(signal); 757#endif 758#if ASAN_INTERCEPT__LONGJMP 759 ASAN_INTERCEPT_FUNC(_longjmp); 760#endif 761#if ASAN_INTERCEPT_SIGLONGJMP 762 ASAN_INTERCEPT_FUNC(siglongjmp); 763#endif 764 765 // Intercept exception handling functions. 766#if ASAN_INTERCEPT___CXA_THROW 767 INTERCEPT_FUNCTION(__cxa_throw); 768#endif 769 770 // Intercept threading-related functions 771#if ASAN_INTERCEPT_PTHREAD_CREATE 772 ASAN_INTERCEPT_FUNC(pthread_create); 773#endif 774 775 // Some Windows-specific interceptors. 776#if defined(_WIN32) 777 InitializeWindowsInterceptors(); 778#endif 779 780 // Some Mac-specific interceptors. 781#if defined(__APPLE__) 782 InitializeMacInterceptors(); 783#endif 784 785 if (flags()->verbosity > 0) { 786 Report("AddressSanitizer: libc interceptors initialized\n"); 787 } 788} 789 790} // namespace __asan 791