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