xref: /freebsd/contrib/llvm-project/compiler-rt/lib/nsan/nsan_new_delete.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1*700637cbSDimitry Andric //===-- nsan_new_delete.cpp -----------------------------------------------===//
2*700637cbSDimitry Andric //
3*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*700637cbSDimitry Andric //
7*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
8*700637cbSDimitry Andric //
9*700637cbSDimitry Andric // This file is a part of MemorySanitizer.
10*700637cbSDimitry Andric //
11*700637cbSDimitry Andric // Interceptors for operators new and delete.
12*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
13*700637cbSDimitry Andric 
14*700637cbSDimitry Andric #include "interception/interception.h"
15*700637cbSDimitry Andric #include "nsan.h"
16*700637cbSDimitry Andric #include "nsan_allocator.h"
17*700637cbSDimitry Andric #include "sanitizer_common/sanitizer_allocator.h"
18*700637cbSDimitry Andric #include "sanitizer_common/sanitizer_allocator_report.h"
19*700637cbSDimitry Andric 
20*700637cbSDimitry Andric #include <stddef.h>
21*700637cbSDimitry Andric 
22*700637cbSDimitry Andric using namespace __nsan;
23*700637cbSDimitry Andric 
24*700637cbSDimitry Andric // Fake std::nothrow_t and std::align_val_t to avoid including <new>.
25*700637cbSDimitry Andric namespace std {
26*700637cbSDimitry Andric struct nothrow_t {};
27*700637cbSDimitry Andric enum class align_val_t : size_t {};
28*700637cbSDimitry Andric } // namespace std
29*700637cbSDimitry Andric 
30*700637cbSDimitry Andric #define OPERATOR_NEW_BODY(nothrow)                                             \
31*700637cbSDimitry Andric   void *res = nsan_malloc(size);                                               \
32*700637cbSDimitry Andric   if (!nothrow && UNLIKELY(!res)) {                                            \
33*700637cbSDimitry Andric     BufferedStackTrace stack;                                                  \
34*700637cbSDimitry Andric     GET_FATAL_STACK_TRACE_IF_EMPTY(&stack);                                    \
35*700637cbSDimitry Andric     ReportOutOfMemory(size, &stack);                                           \
36*700637cbSDimitry Andric   }                                                                            \
37*700637cbSDimitry Andric   return res
38*700637cbSDimitry Andric #define OPERATOR_NEW_BODY_ALIGN(nothrow)                                       \
39*700637cbSDimitry Andric   void *res = nsan_memalign((uptr)align, size);                                \
40*700637cbSDimitry Andric   if (!nothrow && UNLIKELY(!res)) {                                            \
41*700637cbSDimitry Andric     BufferedStackTrace stack;                                                  \
42*700637cbSDimitry Andric     GET_FATAL_STACK_TRACE_IF_EMPTY(&stack);                                    \
43*700637cbSDimitry Andric     ReportOutOfMemory(size, &stack);                                           \
44*700637cbSDimitry Andric   }                                                                            \
45*700637cbSDimitry Andric   return res;
46*700637cbSDimitry Andric 
47*700637cbSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator new(size_t size)48*700637cbSDimitry Andric void *operator new(size_t size) { OPERATOR_NEW_BODY(/*nothrow=*/false); }
49*700637cbSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator new[](size_t size)50*700637cbSDimitry Andric void *operator new[](size_t size) { OPERATOR_NEW_BODY(/*nothrow=*/false); }
51*700637cbSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator new(size_t size,std::nothrow_t const &)52*700637cbSDimitry Andric void *operator new(size_t size, std::nothrow_t const &) {
53*700637cbSDimitry Andric   OPERATOR_NEW_BODY(/*nothrow=*/true);
54*700637cbSDimitry Andric }
55*700637cbSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator new[](size_t size,std::nothrow_t const &)56*700637cbSDimitry Andric void *operator new[](size_t size, std::nothrow_t const &) {
57*700637cbSDimitry Andric   OPERATOR_NEW_BODY(/*nothrow=*/true);
58*700637cbSDimitry Andric }
59*700637cbSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator new(size_t size,std::align_val_t align)60*700637cbSDimitry Andric void *operator new(size_t size, std::align_val_t align) {
61*700637cbSDimitry Andric   OPERATOR_NEW_BODY_ALIGN(/*nothrow=*/false);
62*700637cbSDimitry Andric }
63*700637cbSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator new[](size_t size,std::align_val_t align)64*700637cbSDimitry Andric void *operator new[](size_t size, std::align_val_t align) {
65*700637cbSDimitry Andric   OPERATOR_NEW_BODY_ALIGN(/*nothrow=*/false);
66*700637cbSDimitry Andric }
67*700637cbSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator new(size_t size,std::align_val_t align,std::nothrow_t const &)68*700637cbSDimitry Andric void *operator new(size_t size, std::align_val_t align,
69*700637cbSDimitry Andric                    std::nothrow_t const &) {
70*700637cbSDimitry Andric   OPERATOR_NEW_BODY_ALIGN(/*nothrow=*/true);
71*700637cbSDimitry Andric }
72*700637cbSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator new[](size_t size,std::align_val_t align,std::nothrow_t const &)73*700637cbSDimitry Andric void *operator new[](size_t size, std::align_val_t align,
74*700637cbSDimitry Andric                      std::nothrow_t const &) {
75*700637cbSDimitry Andric   OPERATOR_NEW_BODY_ALIGN(/*nothrow=*/true);
76*700637cbSDimitry Andric }
77*700637cbSDimitry Andric 
78*700637cbSDimitry Andric #define OPERATOR_DELETE_BODY                                                   \
79*700637cbSDimitry Andric   if (ptr)                                                                     \
80*700637cbSDimitry Andric   NsanDeallocate(ptr)
81*700637cbSDimitry Andric 
82*700637cbSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr)83*700637cbSDimitry Andric void operator delete(void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; }
84*700637cbSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr)85*700637cbSDimitry Andric void operator delete[](void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; }
86*700637cbSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,std::nothrow_t const &)87*700637cbSDimitry Andric void operator delete(void *ptr, std::nothrow_t const &) {
88*700637cbSDimitry Andric   OPERATOR_DELETE_BODY;
89*700637cbSDimitry Andric }
90*700637cbSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,std::nothrow_t const &)91*700637cbSDimitry Andric void operator delete[](void *ptr, std::nothrow_t const &) {
92*700637cbSDimitry Andric   OPERATOR_DELETE_BODY;
93*700637cbSDimitry Andric }
94*700637cbSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,size_t size)95*700637cbSDimitry Andric void operator delete(void *ptr, size_t size) NOEXCEPT { OPERATOR_DELETE_BODY; }
96*700637cbSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,size_t size)97*700637cbSDimitry Andric void operator delete[](void *ptr, size_t size) NOEXCEPT {
98*700637cbSDimitry Andric   OPERATOR_DELETE_BODY;
99*700637cbSDimitry Andric }
100*700637cbSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,std::align_val_t align)101*700637cbSDimitry Andric void operator delete(void *ptr, std::align_val_t align) NOEXCEPT {
102*700637cbSDimitry Andric   OPERATOR_DELETE_BODY;
103*700637cbSDimitry Andric }
104*700637cbSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,std::align_val_t align)105*700637cbSDimitry Andric void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT {
106*700637cbSDimitry Andric   OPERATOR_DELETE_BODY;
107*700637cbSDimitry Andric }
108*700637cbSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,std::align_val_t align,std::nothrow_t const &)109*700637cbSDimitry Andric void operator delete(void *ptr, std::align_val_t align,
110*700637cbSDimitry Andric                      std::nothrow_t const &) {
111*700637cbSDimitry Andric   OPERATOR_DELETE_BODY;
112*700637cbSDimitry Andric }
113*700637cbSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,std::align_val_t align,std::nothrow_t const &)114*700637cbSDimitry Andric void operator delete[](void *ptr, std::align_val_t align,
115*700637cbSDimitry Andric                        std::nothrow_t const &) {
116*700637cbSDimitry Andric   OPERATOR_DELETE_BODY;
117*700637cbSDimitry Andric }
118*700637cbSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,size_t size,std::align_val_t align)119*700637cbSDimitry Andric void operator delete(void *ptr, size_t size, std::align_val_t align) NOEXCEPT {
120*700637cbSDimitry Andric   OPERATOR_DELETE_BODY;
121*700637cbSDimitry Andric }
122*700637cbSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,size_t size,std::align_val_t align)123*700637cbSDimitry Andric void operator delete[](void *ptr, size_t size,
124*700637cbSDimitry Andric                        std::align_val_t align) NOEXCEPT {
125*700637cbSDimitry Andric   OPERATOR_DELETE_BODY;
126*700637cbSDimitry Andric }
127