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