xref: /freebsd/contrib/llvm-project/compiler-rt/lib/nsan/nsan_new_delete.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===-- nsan_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 "interception/interception.h"
15 #include "nsan.h"
16 #include "nsan_allocator.h"
17 #include "sanitizer_common/sanitizer_allocator.h"
18 #include "sanitizer_common/sanitizer_allocator_report.h"
19 
20 #include <stddef.h>
21 
22 using namespace __nsan;
23 
24 // Fake std::nothrow_t and std::align_val_t to avoid including <new>.
25 namespace std {
26 struct nothrow_t {};
27 enum class align_val_t : size_t {};
28 } // namespace std
29 
30 #define OPERATOR_NEW_BODY(nothrow)                                             \
31   void *res = nsan_malloc(size);                                               \
32   if (!nothrow && UNLIKELY(!res)) {                                            \
33     BufferedStackTrace stack;                                                  \
34     GET_FATAL_STACK_TRACE_IF_EMPTY(&stack);                                    \
35     ReportOutOfMemory(size, &stack);                                           \
36   }                                                                            \
37   return res
38 #define OPERATOR_NEW_BODY_ALIGN(nothrow)                                       \
39   void *res = nsan_memalign((uptr)align, size);                                \
40   if (!nothrow && UNLIKELY(!res)) {                                            \
41     BufferedStackTrace stack;                                                  \
42     GET_FATAL_STACK_TRACE_IF_EMPTY(&stack);                                    \
43     ReportOutOfMemory(size, &stack);                                           \
44   }                                                                            \
45   return res;
46 
47 INTERCEPTOR_ATTRIBUTE
operator new(size_t size)48 void *operator new(size_t size) { OPERATOR_NEW_BODY(/*nothrow=*/false); }
49 INTERCEPTOR_ATTRIBUTE
operator new[](size_t size)50 void *operator new[](size_t size) { OPERATOR_NEW_BODY(/*nothrow=*/false); }
51 INTERCEPTOR_ATTRIBUTE
operator new(size_t size,std::nothrow_t const &)52 void *operator new(size_t size, std::nothrow_t const &) {
53   OPERATOR_NEW_BODY(/*nothrow=*/true);
54 }
55 INTERCEPTOR_ATTRIBUTE
operator new[](size_t size,std::nothrow_t const &)56 void *operator new[](size_t size, std::nothrow_t const &) {
57   OPERATOR_NEW_BODY(/*nothrow=*/true);
58 }
59 INTERCEPTOR_ATTRIBUTE
operator new(size_t size,std::align_val_t align)60 void *operator new(size_t size, std::align_val_t align) {
61   OPERATOR_NEW_BODY_ALIGN(/*nothrow=*/false);
62 }
63 INTERCEPTOR_ATTRIBUTE
operator new[](size_t size,std::align_val_t align)64 void *operator new[](size_t size, std::align_val_t align) {
65   OPERATOR_NEW_BODY_ALIGN(/*nothrow=*/false);
66 }
67 INTERCEPTOR_ATTRIBUTE
operator new(size_t size,std::align_val_t align,std::nothrow_t const &)68 void *operator new(size_t size, std::align_val_t align,
69                    std::nothrow_t const &) {
70   OPERATOR_NEW_BODY_ALIGN(/*nothrow=*/true);
71 }
72 INTERCEPTOR_ATTRIBUTE
operator new[](size_t size,std::align_val_t align,std::nothrow_t const &)73 void *operator new[](size_t size, std::align_val_t align,
74                      std::nothrow_t const &) {
75   OPERATOR_NEW_BODY_ALIGN(/*nothrow=*/true);
76 }
77 
78 #define OPERATOR_DELETE_BODY                                                   \
79   if (ptr)                                                                     \
80   NsanDeallocate(ptr)
81 
82 INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr)83 void operator delete(void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; }
84 INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr)85 void operator delete[](void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; }
86 INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,std::nothrow_t const &)87 void operator delete(void *ptr, std::nothrow_t const &) {
88   OPERATOR_DELETE_BODY;
89 }
90 INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,std::nothrow_t const &)91 void operator delete[](void *ptr, std::nothrow_t const &) {
92   OPERATOR_DELETE_BODY;
93 }
94 INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,size_t size)95 void operator delete(void *ptr, size_t size) NOEXCEPT { OPERATOR_DELETE_BODY; }
96 INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,size_t size)97 void operator delete[](void *ptr, size_t size) NOEXCEPT {
98   OPERATOR_DELETE_BODY;
99 }
100 INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,std::align_val_t align)101 void operator delete(void *ptr, std::align_val_t align) NOEXCEPT {
102   OPERATOR_DELETE_BODY;
103 }
104 INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,std::align_val_t align)105 void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT {
106   OPERATOR_DELETE_BODY;
107 }
108 INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,std::align_val_t align,std::nothrow_t const &)109 void operator delete(void *ptr, std::align_val_t align,
110                      std::nothrow_t const &) {
111   OPERATOR_DELETE_BODY;
112 }
113 INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,std::align_val_t align,std::nothrow_t const &)114 void operator delete[](void *ptr, std::align_val_t align,
115                        std::nothrow_t const &) {
116   OPERATOR_DELETE_BODY;
117 }
118 INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,size_t size,std::align_val_t align)119 void operator delete(void *ptr, size_t size, std::align_val_t align) NOEXCEPT {
120   OPERATOR_DELETE_BODY;
121 }
122 INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,size_t size,std::align_val_t align)123 void operator delete[](void *ptr, size_t size,
124                        std::align_val_t align) NOEXCEPT {
125   OPERATOR_DELETE_BODY;
126 }
127