1//===-- asan_interceptors.cpp ---------------------------------------------===// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8// 9// This file is a part of AddressSanitizer, an address sanity checker. 10// 11// Interceptors for operators new and delete. 12//===----------------------------------------------------------------------===// 13 14#include "asan_allocator.h" 15#include "asan_internal.h" 16#include "asan_malloc_local.h" 17#include "asan_report.h" 18#include "asan_stack.h" 19 20#include "interception/interception.h" 21 22#include <stddef.h> 23 24// C++ operators can't have dllexport attributes on Windows. We export them 25// anyway by passing extra -export flags to the linker, which is exactly that 26// dllexport would normally do. We need to export them in order to make the 27// VS2015 dynamic CRT (MD) work. 28#if SANITIZER_WINDOWS && defined(_MSC_VER) 29#define CXX_OPERATOR_ATTRIBUTE 30#define COMMENT_EXPORT(sym) __pragma(comment(linker, "/export:" sym)) 31#ifdef _WIN64 32COMMENT_EXPORT("??2@YAPEAX_K@Z") // operator new 33COMMENT_EXPORT("??2@YAPEAX_KAEBUnothrow_t@std@@@Z") // operator new nothrow 34COMMENT_EXPORT("??3@YAXPEAX@Z") // operator delete 35COMMENT_EXPORT("??3@YAXPEAX_K@Z") // sized operator delete 36COMMENT_EXPORT("??_U@YAPEAX_K@Z") // operator new[] 37COMMENT_EXPORT("??_V@YAXPEAX@Z") // operator delete[] 38#else 39COMMENT_EXPORT("??2@YAPAXI@Z") // operator new 40COMMENT_EXPORT("??2@YAPAXIABUnothrow_t@std@@@Z") // operator new nothrow 41COMMENT_EXPORT("??3@YAXPAX@Z") // operator delete 42COMMENT_EXPORT("??3@YAXPAXI@Z") // sized operator delete 43COMMENT_EXPORT("??_U@YAPAXI@Z") // operator new[] 44COMMENT_EXPORT("??_V@YAXPAX@Z") // operator delete[] 45#endif 46#undef COMMENT_EXPORT 47#else 48#define CXX_OPERATOR_ATTRIBUTE INTERCEPTOR_ATTRIBUTE 49#endif 50 51using namespace __asan; 52 53// FreeBSD prior v9.2 have wrong definition of 'size_t'. 54// http://svnweb.freebsd.org/base?view=revision&revision=232261 55#if SANITIZER_FREEBSD && SANITIZER_WORDSIZE == 32 56#include <sys/param.h> 57#if __FreeBSD_version <= 902001 // v9.2 58#define size_t unsigned 59#endif // __FreeBSD_version 60#endif // SANITIZER_FREEBSD && SANITIZER_WORDSIZE == 32 61 62// This code has issues on OSX. 63// See https://github.com/google/sanitizers/issues/131. 64 65// Fake std::nothrow_t and std::align_val_t to avoid including <new>. 66namespace std { 67struct nothrow_t {}; 68enum class align_val_t: size_t {}; 69} // namespace std 70 71// TODO(alekseyshl): throw std::bad_alloc instead of dying on OOM. 72// For local pool allocation, align to SHADOW_GRANULARITY to match asan 73// allocator behavior. 74#define OPERATOR_NEW_BODY(type, nothrow) \ 75 MAYBE_ALLOCATE_FROM_LOCAL_POOL(nothrow); \ 76 GET_STACK_TRACE_MALLOC; \ 77 void *res = asan_memalign(0, size, &stack, type); \ 78 if (!nothrow && UNLIKELY(!res)) \ 79 ReportOutOfMemory(size, &stack); \ 80 return res; 81#define OPERATOR_NEW_BODY_ALIGN(type, nothrow) \ 82 MAYBE_ALLOCATE_FROM_LOCAL_POOL(nothrow); \ 83 GET_STACK_TRACE_MALLOC; \ 84 void *res = asan_memalign((uptr)align, size, &stack, type); \ 85 if (!nothrow && UNLIKELY(!res)) \ 86 ReportOutOfMemory(size, &stack); \ 87 return res; 88 89// On OS X it's not enough to just provide our own 'operator new' and 90// 'operator delete' implementations, because they're going to be in the 91// runtime dylib, and the main executable will depend on both the runtime 92// dylib and libstdc++, each of those'll have its implementation of new and 93// delete. 94// To make sure that C++ allocation/deallocation operators are overridden on 95// OS X we need to intercept them using their mangled names. 96#if !SANITIZER_MAC 97CXX_OPERATOR_ATTRIBUTE 98void *operator new(size_t size) 99{ OPERATOR_NEW_BODY(FROM_NEW, false /*nothrow*/); } 100CXX_OPERATOR_ATTRIBUTE 101void *operator new[](size_t size) 102{ OPERATOR_NEW_BODY(FROM_NEW_BR, false /*nothrow*/); } 103CXX_OPERATOR_ATTRIBUTE 104void *operator new(size_t size, std::nothrow_t const&) 105{ OPERATOR_NEW_BODY(FROM_NEW, true /*nothrow*/); } 106CXX_OPERATOR_ATTRIBUTE 107void *operator new[](size_t size, std::nothrow_t const&) 108{ OPERATOR_NEW_BODY(FROM_NEW_BR, true /*nothrow*/); } 109CXX_OPERATOR_ATTRIBUTE 110void *operator new(size_t size, std::align_val_t align) 111{ OPERATOR_NEW_BODY_ALIGN(FROM_NEW, false /*nothrow*/); } 112CXX_OPERATOR_ATTRIBUTE 113void *operator new[](size_t size, std::align_val_t align) 114{ OPERATOR_NEW_BODY_ALIGN(FROM_NEW_BR, false /*nothrow*/); } 115CXX_OPERATOR_ATTRIBUTE 116void *operator new(size_t size, std::align_val_t align, std::nothrow_t const&) 117{ OPERATOR_NEW_BODY_ALIGN(FROM_NEW, true /*nothrow*/); } 118CXX_OPERATOR_ATTRIBUTE 119void *operator new[](size_t size, std::align_val_t align, std::nothrow_t const&) 120{ OPERATOR_NEW_BODY_ALIGN(FROM_NEW_BR, true /*nothrow*/); } 121 122#else // SANITIZER_MAC 123INTERCEPTOR(void *, _Znwm, size_t size) { 124 OPERATOR_NEW_BODY(FROM_NEW, false /*nothrow*/); 125} 126INTERCEPTOR(void *, _Znam, size_t size) { 127 OPERATOR_NEW_BODY(FROM_NEW_BR, false /*nothrow*/); 128} 129INTERCEPTOR(void *, _ZnwmRKSt9nothrow_t, size_t size, std::nothrow_t const&) { 130 OPERATOR_NEW_BODY(FROM_NEW, true /*nothrow*/); 131} 132INTERCEPTOR(void *, _ZnamRKSt9nothrow_t, size_t size, std::nothrow_t const&) { 133 OPERATOR_NEW_BODY(FROM_NEW_BR, true /*nothrow*/); 134} 135#endif // !SANITIZER_MAC 136 137#define OPERATOR_DELETE_BODY(type) \ 138 if (IS_FROM_LOCAL_POOL(ptr)) return;\ 139 GET_STACK_TRACE_FREE;\ 140 asan_delete(ptr, 0, 0, &stack, type); 141 142#define OPERATOR_DELETE_BODY_SIZE(type) \ 143 if (IS_FROM_LOCAL_POOL(ptr)) return;\ 144 GET_STACK_TRACE_FREE;\ 145 asan_delete(ptr, size, 0, &stack, type); 146 147#define OPERATOR_DELETE_BODY_ALIGN(type) \ 148 if (IS_FROM_LOCAL_POOL(ptr)) return;\ 149 GET_STACK_TRACE_FREE;\ 150 asan_delete(ptr, 0, static_cast<uptr>(align), &stack, type); 151 152#define OPERATOR_DELETE_BODY_SIZE_ALIGN(type) \ 153 if (IS_FROM_LOCAL_POOL(ptr)) return;\ 154 GET_STACK_TRACE_FREE;\ 155 asan_delete(ptr, size, static_cast<uptr>(align), &stack, type); 156 157#if !SANITIZER_MAC 158CXX_OPERATOR_ATTRIBUTE 159void operator delete(void *ptr) NOEXCEPT 160{ OPERATOR_DELETE_BODY(FROM_NEW); } 161CXX_OPERATOR_ATTRIBUTE 162void operator delete[](void *ptr) NOEXCEPT 163{ OPERATOR_DELETE_BODY(FROM_NEW_BR); } 164CXX_OPERATOR_ATTRIBUTE 165void operator delete(void *ptr, std::nothrow_t const&) 166{ OPERATOR_DELETE_BODY(FROM_NEW); } 167CXX_OPERATOR_ATTRIBUTE 168void operator delete[](void *ptr, std::nothrow_t const&) 169{ OPERATOR_DELETE_BODY(FROM_NEW_BR); } 170CXX_OPERATOR_ATTRIBUTE 171void operator delete(void *ptr, size_t size) NOEXCEPT 172{ OPERATOR_DELETE_BODY_SIZE(FROM_NEW); } 173CXX_OPERATOR_ATTRIBUTE 174void operator delete[](void *ptr, size_t size) NOEXCEPT 175{ OPERATOR_DELETE_BODY_SIZE(FROM_NEW_BR); } 176CXX_OPERATOR_ATTRIBUTE 177void operator delete(void *ptr, std::align_val_t align) NOEXCEPT 178{ OPERATOR_DELETE_BODY_ALIGN(FROM_NEW); } 179CXX_OPERATOR_ATTRIBUTE 180void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT 181{ OPERATOR_DELETE_BODY_ALIGN(FROM_NEW_BR); } 182CXX_OPERATOR_ATTRIBUTE 183void operator delete(void *ptr, std::align_val_t align, std::nothrow_t const&) 184{ OPERATOR_DELETE_BODY_ALIGN(FROM_NEW); } 185CXX_OPERATOR_ATTRIBUTE 186void operator delete[](void *ptr, std::align_val_t align, std::nothrow_t const&) 187{ OPERATOR_DELETE_BODY_ALIGN(FROM_NEW_BR); } 188CXX_OPERATOR_ATTRIBUTE 189void operator delete(void *ptr, size_t size, std::align_val_t align) NOEXCEPT 190{ OPERATOR_DELETE_BODY_SIZE_ALIGN(FROM_NEW); } 191CXX_OPERATOR_ATTRIBUTE 192void operator delete[](void *ptr, size_t size, std::align_val_t align) NOEXCEPT 193{ OPERATOR_DELETE_BODY_SIZE_ALIGN(FROM_NEW_BR); } 194 195#else // SANITIZER_MAC 196INTERCEPTOR(void, _ZdlPv, void *ptr) 197{ OPERATOR_DELETE_BODY(FROM_NEW); } 198INTERCEPTOR(void, _ZdaPv, void *ptr) 199{ OPERATOR_DELETE_BODY(FROM_NEW_BR); } 200INTERCEPTOR(void, _ZdlPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&) 201{ OPERATOR_DELETE_BODY(FROM_NEW); } 202INTERCEPTOR(void, _ZdaPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&) 203{ OPERATOR_DELETE_BODY(FROM_NEW_BR); } 204#endif // !SANITIZER_MAC 205