1 //===-- msan_new_delete.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 MemorySanitizer. 10 // 11 // Interceptors for operators new and delete. 12 //===----------------------------------------------------------------------===// 13 14 #include "msan.h" 15 #include "interception/interception.h" 16 #include "sanitizer_common/sanitizer_allocator.h" 17 #include "sanitizer_common/sanitizer_allocator_report.h" 18 19 #if MSAN_REPLACE_OPERATORS_NEW_AND_DELETE 20 21 #include <stddef.h> 22 23 using namespace __msan; 24 25 // Fake std::nothrow_t and std::align_val_t to avoid including <new>. 26 namespace std { 27 struct nothrow_t {}; 28 enum class align_val_t: size_t {}; 29 } // namespace std 30 31 32 // TODO(alekseys): throw std::bad_alloc instead of dying on OOM. 33 # define OPERATOR_NEW_BODY(nothrow) \ 34 GET_MALLOC_STACK_TRACE; \ 35 void *res = msan_malloc(size, &stack); \ 36 if (!nothrow && UNLIKELY(!res)) { \ 37 GET_FATAL_STACK_TRACE_IF_EMPTY(&stack); \ 38 ReportOutOfMemory(size, &stack); \ 39 } \ 40 return res 41 # define OPERATOR_NEW_BODY_ALIGN(nothrow) \ 42 GET_MALLOC_STACK_TRACE; \ 43 void *res = msan_memalign((uptr)align, size, &stack); \ 44 if (!nothrow && UNLIKELY(!res)) { \ 45 GET_FATAL_STACK_TRACE_IF_EMPTY(&stack); \ 46 ReportOutOfMemory(size, &stack); \ 47 } \ 48 return res; 49 50 INTERCEPTOR_ATTRIBUTE 51 void *operator new(size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); } 52 INTERCEPTOR_ATTRIBUTE 53 void *operator new[](size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); } 54 INTERCEPTOR_ATTRIBUTE 55 void *operator new(size_t size, std::nothrow_t const&) { 56 OPERATOR_NEW_BODY(true /*nothrow*/); 57 } 58 INTERCEPTOR_ATTRIBUTE 59 void *operator new[](size_t size, std::nothrow_t const&) { 60 OPERATOR_NEW_BODY(true /*nothrow*/); 61 } 62 INTERCEPTOR_ATTRIBUTE 63 void *operator new(size_t size, std::align_val_t align) 64 { OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/); } 65 INTERCEPTOR_ATTRIBUTE 66 void *operator new[](size_t size, std::align_val_t align) 67 { OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/); } 68 INTERCEPTOR_ATTRIBUTE 69 void *operator new(size_t size, std::align_val_t align, std::nothrow_t const&) 70 { OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/); } 71 INTERCEPTOR_ATTRIBUTE 72 void *operator new[](size_t size, std::align_val_t align, std::nothrow_t const&) 73 { OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/); } 74 75 #define OPERATOR_DELETE_BODY \ 76 GET_MALLOC_STACK_TRACE; \ 77 if (ptr) MsanDeallocate(&stack, ptr) 78 79 INTERCEPTOR_ATTRIBUTE 80 void operator delete(void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; } 81 INTERCEPTOR_ATTRIBUTE 82 void operator delete[](void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; } 83 INTERCEPTOR_ATTRIBUTE 84 void operator delete(void *ptr, std::nothrow_t const&) { OPERATOR_DELETE_BODY; } 85 INTERCEPTOR_ATTRIBUTE 86 void operator delete[](void *ptr, std::nothrow_t const&) { 87 OPERATOR_DELETE_BODY; 88 } 89 INTERCEPTOR_ATTRIBUTE 90 void operator delete(void *ptr, size_t size) NOEXCEPT { OPERATOR_DELETE_BODY; } 91 INTERCEPTOR_ATTRIBUTE 92 void operator delete[](void *ptr, size_t size) NOEXCEPT 93 { OPERATOR_DELETE_BODY; } 94 INTERCEPTOR_ATTRIBUTE 95 void operator delete(void *ptr, std::align_val_t align) NOEXCEPT 96 { OPERATOR_DELETE_BODY; } 97 INTERCEPTOR_ATTRIBUTE 98 void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT 99 { OPERATOR_DELETE_BODY; } 100 INTERCEPTOR_ATTRIBUTE 101 void operator delete(void *ptr, std::align_val_t align, std::nothrow_t const&) 102 { OPERATOR_DELETE_BODY; } 103 INTERCEPTOR_ATTRIBUTE 104 void operator delete[](void *ptr, std::align_val_t align, std::nothrow_t const&) 105 { OPERATOR_DELETE_BODY; } 106 INTERCEPTOR_ATTRIBUTE 107 void operator delete(void *ptr, size_t size, std::align_val_t align) NOEXCEPT 108 { OPERATOR_DELETE_BODY; } 109 INTERCEPTOR_ATTRIBUTE 110 void operator delete[](void *ptr, size_t size, std::align_val_t align) NOEXCEPT 111 { OPERATOR_DELETE_BODY; } 112 113 114 #endif // MSAN_REPLACE_OPERATORS_NEW_AND_DELETE 115