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