1//===-- asan_interceptors.cc ----------------------------------------------===// 2// 3// This file is distributed under the University of Illinois Open Source 4// License. See LICENSE.TXT for details. 5// 6//===----------------------------------------------------------------------===// 7// 8// This file is a part of AddressSanitizer, an address sanity checker. 9// 10// Interceptors for operators new and delete. 11//===----------------------------------------------------------------------===// 12 13#include "asan_allocator.h" 14#include "asan_internal.h" 15#include "asan_stack.h" 16 17#include "sanitizer_common/sanitizer_interception.h" 18 19#include <stddef.h> 20 21// C++ operators can't have visibility attributes on Windows. 22#if SANITIZER_WINDOWS 23# define CXX_OPERATOR_ATTRIBUTE 24#else 25# define CXX_OPERATOR_ATTRIBUTE INTERCEPTOR_ATTRIBUTE 26#endif 27 28using namespace __asan; // NOLINT 29 30// This code has issues on OSX. 31// See https://code.google.com/p/address-sanitizer/issues/detail?id=131. 32 33// Fake std::nothrow_t to avoid including <new>. 34namespace std { 35struct nothrow_t {}; 36} // namespace std 37 38#define OPERATOR_NEW_BODY(type) \ 39 GET_STACK_TRACE_MALLOC;\ 40 return asan_memalign(0, size, &stack, type); 41 42// On OS X it's not enough to just provide our own 'operator new' and 43// 'operator delete' implementations, because they're going to be in the 44// runtime dylib, and the main executable will depend on both the runtime 45// dylib and libstdc++, each of those'll have its implementation of new and 46// delete. 47// To make sure that C++ allocation/deallocation operators are overridden on 48// OS X we need to intercept them using their mangled names. 49#if !SANITIZER_MAC 50// FreeBSD prior v9.2 have wrong definition of 'size_t'. 51// http://svnweb.freebsd.org/base?view=revision&revision=232261 52#if SANITIZER_FREEBSD && SANITIZER_WORDSIZE == 32 53#include <sys/param.h> 54#if __FreeBSD_version <= 902001 // v9.2 55#define size_t unsigned 56#endif // __FreeBSD_version 57#endif // SANITIZER_FREEBSD && SANITIZER_WORDSIZE == 32 58 59CXX_OPERATOR_ATTRIBUTE 60void *operator new(size_t size) { OPERATOR_NEW_BODY(FROM_NEW); } 61CXX_OPERATOR_ATTRIBUTE 62void *operator new[](size_t size) { OPERATOR_NEW_BODY(FROM_NEW_BR); } 63CXX_OPERATOR_ATTRIBUTE 64void *operator new(size_t size, std::nothrow_t const&) 65{ OPERATOR_NEW_BODY(FROM_NEW); } 66CXX_OPERATOR_ATTRIBUTE 67void *operator new[](size_t size, std::nothrow_t const&) 68{ OPERATOR_NEW_BODY(FROM_NEW_BR); } 69 70#else // SANITIZER_MAC 71INTERCEPTOR(void *, _Znwm, size_t size) { 72 OPERATOR_NEW_BODY(FROM_NEW); 73} 74INTERCEPTOR(void *, _Znam, size_t size) { 75 OPERATOR_NEW_BODY(FROM_NEW_BR); 76} 77INTERCEPTOR(void *, _ZnwmRKSt9nothrow_t, size_t size, std::nothrow_t const&) { 78 OPERATOR_NEW_BODY(FROM_NEW); 79} 80INTERCEPTOR(void *, _ZnamRKSt9nothrow_t, size_t size, std::nothrow_t const&) { 81 OPERATOR_NEW_BODY(FROM_NEW_BR); 82} 83#endif 84 85#define OPERATOR_DELETE_BODY(type) \ 86 GET_STACK_TRACE_FREE;\ 87 asan_free(ptr, &stack, type); 88 89#if !SANITIZER_MAC 90CXX_OPERATOR_ATTRIBUTE 91void operator delete(void *ptr) throw() { 92 OPERATOR_DELETE_BODY(FROM_NEW); 93} 94CXX_OPERATOR_ATTRIBUTE 95void operator delete[](void *ptr) throw() { 96 OPERATOR_DELETE_BODY(FROM_NEW_BR); 97} 98CXX_OPERATOR_ATTRIBUTE 99void operator delete(void *ptr, std::nothrow_t const&) { 100 OPERATOR_DELETE_BODY(FROM_NEW); 101} 102CXX_OPERATOR_ATTRIBUTE 103void operator delete[](void *ptr, std::nothrow_t const&) { 104 OPERATOR_DELETE_BODY(FROM_NEW_BR); 105} 106CXX_OPERATOR_ATTRIBUTE 107void operator delete(void *ptr, size_t size) throw() { 108 GET_STACK_TRACE_FREE; 109 asan_sized_free(ptr, size, &stack, FROM_NEW); 110} 111CXX_OPERATOR_ATTRIBUTE 112void operator delete[](void *ptr, size_t size) throw() { 113 GET_STACK_TRACE_FREE; 114 asan_sized_free(ptr, size, &stack, FROM_NEW_BR); 115} 116 117#else // SANITIZER_MAC 118INTERCEPTOR(void, _ZdlPv, void *ptr) { 119 OPERATOR_DELETE_BODY(FROM_NEW); 120} 121INTERCEPTOR(void, _ZdaPv, void *ptr) { 122 OPERATOR_DELETE_BODY(FROM_NEW_BR); 123} 124INTERCEPTOR(void, _ZdlPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&) { 125 OPERATOR_DELETE_BODY(FROM_NEW); 126} 127INTERCEPTOR(void, _ZdaPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&) { 128 OPERATOR_DELETE_BODY(FROM_NEW_BR); 129} 130#endif 131