asan_new_delete.cc revision 1.6
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 "interception/interception.h" 18 19#include <stddef.h> 20 21// C++ operators can't have dllexport attributes on Windows. We export them 22// anyway by passing extra -export flags to the linker, which is exactly that 23// dllexport would normally do. We need to export them in order to make the 24// VS2015 dynamic CRT (MD) work. 25#if SANITIZER_WINDOWS 26# define CXX_OPERATOR_ATTRIBUTE 27# ifdef _WIN64 28# pragma comment(linker, "/export:??2@YAPEAX_K@Z") // operator new 29# pragma comment(linker, "/export:??3@YAXPEAX@Z") // operator delete 30# pragma comment(linker, "/export:??3@YAXPEAX_K@Z") // sized operator delete 31# pragma comment(linker, "/export:??_U@YAPEAX_K@Z") // operator new[] 32# pragma comment(linker, "/export:??_V@YAXPEAX@Z") // operator delete[] 33# else 34# pragma comment(linker, "/export:??2@YAPAXI@Z") // operator new 35# pragma comment(linker, "/export:??3@YAXPAX@Z") // operator delete 36# pragma comment(linker, "/export:??3@YAXPAXI@Z") // sized operator delete 37# pragma comment(linker, "/export:??_U@YAPAXI@Z") // operator new[] 38# pragma comment(linker, "/export:??_V@YAXPAX@Z") // operator delete[] 39# endif 40#else 41# define CXX_OPERATOR_ATTRIBUTE INTERCEPTOR_ATTRIBUTE 42#endif 43 44using namespace __asan; // NOLINT 45 46// FreeBSD prior v9.2 have wrong definition of 'size_t'. 47// http://svnweb.freebsd.org/base?view=revision&revision=232261 48#if SANITIZER_FREEBSD && SANITIZER_WORDSIZE == 32 49#include <sys/param.h> 50#if __FreeBSD_version <= 902001 // v9.2 51#define size_t unsigned 52#endif // __FreeBSD_version 53#endif // SANITIZER_FREEBSD && SANITIZER_WORDSIZE == 32 54 55// This code has issues on OSX. 56// See https://github.com/google/sanitizers/issues/131. 57 58// Fake std::nothrow_t and std::align_val_t to avoid including <new>. 59namespace std { 60struct nothrow_t {}; 61enum class align_val_t: size_t {}; 62} // namespace std 63 64#define OPERATOR_NEW_BODY(type) \ 65 GET_STACK_TRACE_MALLOC;\ 66 return asan_memalign(0, size, &stack, type); 67#define OPERATOR_NEW_BODY_ALIGN(type) \ 68 GET_STACK_TRACE_MALLOC;\ 69 return asan_memalign((uptr)align, size, &stack, type); 70 71// On OS X it's not enough to just provide our own 'operator new' and 72// 'operator delete' implementations, because they're going to be in the 73// runtime dylib, and the main executable will depend on both the runtime 74// dylib and libstdc++, each of those'll have its implementation of new and 75// delete. 76// To make sure that C++ allocation/deallocation operators are overridden on 77// OS X we need to intercept them using their mangled names. 78#if !SANITIZER_MAC 79CXX_OPERATOR_ATTRIBUTE 80void *operator new(size_t size) { OPERATOR_NEW_BODY(FROM_NEW); } 81CXX_OPERATOR_ATTRIBUTE 82void *operator new[](size_t size) { OPERATOR_NEW_BODY(FROM_NEW_BR); } 83CXX_OPERATOR_ATTRIBUTE 84void *operator new(size_t size, std::nothrow_t const&) 85{ OPERATOR_NEW_BODY(FROM_NEW); } 86CXX_OPERATOR_ATTRIBUTE 87void *operator new[](size_t size, std::nothrow_t const&) 88{ OPERATOR_NEW_BODY(FROM_NEW_BR); } 89CXX_OPERATOR_ATTRIBUTE 90void *operator new(size_t size, std::align_val_t align) 91{ OPERATOR_NEW_BODY_ALIGN(FROM_NEW); } 92CXX_OPERATOR_ATTRIBUTE 93void *operator new[](size_t size, std::align_val_t align) 94{ OPERATOR_NEW_BODY_ALIGN(FROM_NEW_BR); } 95CXX_OPERATOR_ATTRIBUTE 96void *operator new(size_t size, std::align_val_t align, std::nothrow_t const&) 97{ OPERATOR_NEW_BODY_ALIGN(FROM_NEW); } 98CXX_OPERATOR_ATTRIBUTE 99void *operator new[](size_t size, std::align_val_t align, std::nothrow_t const&) 100{ OPERATOR_NEW_BODY_ALIGN(FROM_NEW_BR); } 101 102#else // SANITIZER_MAC 103INTERCEPTOR(void *, _Znwm, size_t size) { 104 OPERATOR_NEW_BODY(FROM_NEW); 105} 106INTERCEPTOR(void *, _Znam, size_t size) { 107 OPERATOR_NEW_BODY(FROM_NEW_BR); 108} 109INTERCEPTOR(void *, _ZnwmRKSt9nothrow_t, size_t size, std::nothrow_t const&) { 110 OPERATOR_NEW_BODY(FROM_NEW); 111} 112INTERCEPTOR(void *, _ZnamRKSt9nothrow_t, size_t size, std::nothrow_t const&) { 113 OPERATOR_NEW_BODY(FROM_NEW_BR); 114} 115#endif 116 117#define OPERATOR_DELETE_BODY(type) \ 118 GET_STACK_TRACE_FREE;\ 119 asan_free(ptr, &stack, type); 120 121#if !SANITIZER_MAC 122CXX_OPERATOR_ATTRIBUTE 123void operator delete(void *ptr) NOEXCEPT { 124 OPERATOR_DELETE_BODY(FROM_NEW); 125} 126CXX_OPERATOR_ATTRIBUTE 127void operator delete[](void *ptr) NOEXCEPT { 128 OPERATOR_DELETE_BODY(FROM_NEW_BR); 129} 130CXX_OPERATOR_ATTRIBUTE 131void operator delete(void *ptr, std::nothrow_t const&) { 132 OPERATOR_DELETE_BODY(FROM_NEW); 133} 134CXX_OPERATOR_ATTRIBUTE 135void operator delete[](void *ptr, std::nothrow_t const&) { 136 OPERATOR_DELETE_BODY(FROM_NEW_BR); 137} 138CXX_OPERATOR_ATTRIBUTE 139void operator delete(void *ptr, size_t size) NOEXCEPT { 140 GET_STACK_TRACE_FREE; 141 asan_sized_free(ptr, size, &stack, FROM_NEW); 142} 143CXX_OPERATOR_ATTRIBUTE 144void operator delete[](void *ptr, size_t size) NOEXCEPT { 145 GET_STACK_TRACE_FREE; 146 asan_sized_free(ptr, size, &stack, FROM_NEW_BR); 147} 148CXX_OPERATOR_ATTRIBUTE 149void operator delete(void *ptr, std::align_val_t) NOEXCEPT { 150 OPERATOR_DELETE_BODY(FROM_NEW); 151} 152CXX_OPERATOR_ATTRIBUTE 153void operator delete[](void *ptr, std::align_val_t) NOEXCEPT { 154 OPERATOR_DELETE_BODY(FROM_NEW_BR); 155} 156CXX_OPERATOR_ATTRIBUTE 157void operator delete(void *ptr, std::align_val_t, std::nothrow_t const&) { 158 OPERATOR_DELETE_BODY(FROM_NEW); 159} 160CXX_OPERATOR_ATTRIBUTE 161void operator delete[](void *ptr, std::align_val_t, std::nothrow_t const&) { 162 OPERATOR_DELETE_BODY(FROM_NEW_BR); 163} 164CXX_OPERATOR_ATTRIBUTE 165void operator delete(void *ptr, size_t size, std::align_val_t) NOEXCEPT { 166 GET_STACK_TRACE_FREE; 167 asan_sized_free(ptr, size, &stack, FROM_NEW); 168} 169CXX_OPERATOR_ATTRIBUTE 170void operator delete[](void *ptr, size_t size, std::align_val_t) NOEXCEPT { 171 GET_STACK_TRACE_FREE; 172 asan_sized_free(ptr, size, &stack, FROM_NEW_BR); 173} 174 175#else // SANITIZER_MAC 176INTERCEPTOR(void, _ZdlPv, void *ptr) { 177 OPERATOR_DELETE_BODY(FROM_NEW); 178} 179INTERCEPTOR(void, _ZdaPv, void *ptr) { 180 OPERATOR_DELETE_BODY(FROM_NEW_BR); 181} 182INTERCEPTOR(void, _ZdlPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&) { 183 OPERATOR_DELETE_BODY(FROM_NEW); 184} 185INTERCEPTOR(void, _ZdaPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&) { 186 OPERATOR_DELETE_BODY(FROM_NEW_BR); 187} 188#endif 189