1*68d75effSDimitry Andric //===-- tsan_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 ThreadSanitizer (TSan), a race detector.
10*68d75effSDimitry Andric //
11*68d75effSDimitry Andric // Interceptors for operators new and delete.
12*68d75effSDimitry Andric //===----------------------------------------------------------------------===//
13*68d75effSDimitry Andric #include "interception/interception.h"
14*68d75effSDimitry Andric #include "sanitizer_common/sanitizer_allocator.h"
15*68d75effSDimitry Andric #include "sanitizer_common/sanitizer_allocator_report.h"
16*68d75effSDimitry Andric #include "sanitizer_common/sanitizer_internal_defs.h"
17*68d75effSDimitry Andric #include "tsan_interceptors.h"
18*68d75effSDimitry Andric #include "tsan_rtl.h"
19*68d75effSDimitry Andric
20*68d75effSDimitry Andric using namespace __tsan;
21*68d75effSDimitry Andric
22*68d75effSDimitry Andric namespace std {
23*68d75effSDimitry Andric struct nothrow_t {};
24*68d75effSDimitry Andric enum class align_val_t: __sanitizer::uptr {};
25*68d75effSDimitry Andric } // namespace std
26*68d75effSDimitry Andric
27*68d75effSDimitry Andric DECLARE_REAL(void *, malloc, uptr size)
28*68d75effSDimitry Andric DECLARE_REAL(void, free, void *ptr)
29*68d75effSDimitry Andric
30*68d75effSDimitry Andric // TODO(alekseys): throw std::bad_alloc instead of dying on OOM.
31*68d75effSDimitry Andric #define OPERATOR_NEW_BODY(mangled_name, nothrow) \
32*68d75effSDimitry Andric if (in_symbolizer()) \
33*68d75effSDimitry Andric return InternalAlloc(size); \
34*68d75effSDimitry Andric void *p = 0; \
35*68d75effSDimitry Andric { \
36*68d75effSDimitry Andric SCOPED_INTERCEPTOR_RAW(mangled_name, size); \
37*68d75effSDimitry Andric p = user_alloc(thr, pc, size); \
38*68d75effSDimitry Andric if (!nothrow && UNLIKELY(!p)) { \
39*68d75effSDimitry Andric GET_STACK_TRACE_FATAL(thr, pc); \
40*68d75effSDimitry Andric ReportOutOfMemory(size, &stack); \
41*68d75effSDimitry Andric } \
42*68d75effSDimitry Andric } \
43*68d75effSDimitry Andric invoke_malloc_hook(p, size); \
44*68d75effSDimitry Andric return p;
45*68d75effSDimitry Andric
46*68d75effSDimitry Andric #define OPERATOR_NEW_BODY_ALIGN(mangled_name, nothrow) \
47*68d75effSDimitry Andric if (in_symbolizer()) \
48*68d75effSDimitry Andric return InternalAlloc(size, nullptr, (uptr)align); \
49*68d75effSDimitry Andric void *p = 0; \
50*68d75effSDimitry Andric { \
51*68d75effSDimitry Andric SCOPED_INTERCEPTOR_RAW(mangled_name, size); \
52*68d75effSDimitry Andric p = user_memalign(thr, pc, (uptr)align, size); \
53*68d75effSDimitry Andric if (!nothrow && UNLIKELY(!p)) { \
54*68d75effSDimitry Andric GET_STACK_TRACE_FATAL(thr, pc); \
55*68d75effSDimitry Andric ReportOutOfMemory(size, &stack); \
56*68d75effSDimitry Andric } \
57*68d75effSDimitry Andric } \
58*68d75effSDimitry Andric invoke_malloc_hook(p, size); \
59*68d75effSDimitry Andric return p;
60*68d75effSDimitry Andric
61*68d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
62*68d75effSDimitry Andric void *operator new(__sanitizer::uptr size);
operator new(__sanitizer::uptr size)63*68d75effSDimitry Andric void *operator new(__sanitizer::uptr size) {
64*68d75effSDimitry Andric OPERATOR_NEW_BODY(_Znwm, false /*nothrow*/);
65*68d75effSDimitry Andric }
66*68d75effSDimitry Andric
67*68d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
68*68d75effSDimitry Andric void *operator new[](__sanitizer::uptr size);
operator new[](__sanitizer::uptr size)69*68d75effSDimitry Andric void *operator new[](__sanitizer::uptr size) {
70*68d75effSDimitry Andric OPERATOR_NEW_BODY(_Znam, false /*nothrow*/);
71*68d75effSDimitry Andric }
72*68d75effSDimitry Andric
73*68d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
74*68d75effSDimitry Andric void *operator new(__sanitizer::uptr size, std::nothrow_t const&);
operator new(__sanitizer::uptr size,std::nothrow_t const &)75*68d75effSDimitry Andric void *operator new(__sanitizer::uptr size, std::nothrow_t const&) {
76*68d75effSDimitry Andric OPERATOR_NEW_BODY(_ZnwmRKSt9nothrow_t, true /*nothrow*/);
77*68d75effSDimitry Andric }
78*68d75effSDimitry Andric
79*68d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
80*68d75effSDimitry Andric void *operator new[](__sanitizer::uptr size, std::nothrow_t const&);
operator new[](__sanitizer::uptr size,std::nothrow_t const &)81*68d75effSDimitry Andric void *operator new[](__sanitizer::uptr size, std::nothrow_t const&) {
82*68d75effSDimitry Andric OPERATOR_NEW_BODY(_ZnamRKSt9nothrow_t, true /*nothrow*/);
83*68d75effSDimitry Andric }
84*68d75effSDimitry Andric
85*68d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
86*68d75effSDimitry Andric void *operator new(__sanitizer::uptr size, std::align_val_t align);
operator new(__sanitizer::uptr size,std::align_val_t align)87*68d75effSDimitry Andric void *operator new(__sanitizer::uptr size, std::align_val_t align) {
88*68d75effSDimitry Andric OPERATOR_NEW_BODY_ALIGN(_ZnwmSt11align_val_t, false /*nothrow*/);
89*68d75effSDimitry Andric }
90*68d75effSDimitry Andric
91*68d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
92*68d75effSDimitry Andric void *operator new[](__sanitizer::uptr size, std::align_val_t align);
operator new[](__sanitizer::uptr size,std::align_val_t align)93*68d75effSDimitry Andric void *operator new[](__sanitizer::uptr size, std::align_val_t align) {
94*68d75effSDimitry Andric OPERATOR_NEW_BODY_ALIGN(_ZnamSt11align_val_t, false /*nothrow*/);
95*68d75effSDimitry Andric }
96*68d75effSDimitry Andric
97*68d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
98*68d75effSDimitry Andric void *operator new(__sanitizer::uptr size, std::align_val_t align,
99*68d75effSDimitry Andric std::nothrow_t const&);
operator new(__sanitizer::uptr size,std::align_val_t align,std::nothrow_t const &)100*68d75effSDimitry Andric void *operator new(__sanitizer::uptr size, std::align_val_t align,
101*68d75effSDimitry Andric std::nothrow_t const&) {
102*68d75effSDimitry Andric OPERATOR_NEW_BODY_ALIGN(_ZnwmSt11align_val_tRKSt9nothrow_t,
103*68d75effSDimitry Andric true /*nothrow*/);
104*68d75effSDimitry Andric }
105*68d75effSDimitry Andric
106*68d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
107*68d75effSDimitry Andric void *operator new[](__sanitizer::uptr size, std::align_val_t align,
108*68d75effSDimitry Andric std::nothrow_t const&);
operator new[](__sanitizer::uptr size,std::align_val_t align,std::nothrow_t const &)109*68d75effSDimitry Andric void *operator new[](__sanitizer::uptr size, std::align_val_t align,
110*68d75effSDimitry Andric std::nothrow_t const&) {
111*68d75effSDimitry Andric OPERATOR_NEW_BODY_ALIGN(_ZnamSt11align_val_tRKSt9nothrow_t,
112*68d75effSDimitry Andric true /*nothrow*/);
113*68d75effSDimitry Andric }
114*68d75effSDimitry Andric
115*68d75effSDimitry Andric #define OPERATOR_DELETE_BODY(mangled_name) \
116*68d75effSDimitry Andric if (ptr == 0) return; \
117*68d75effSDimitry Andric if (in_symbolizer()) \
118*68d75effSDimitry Andric return InternalFree(ptr); \
119*68d75effSDimitry Andric invoke_free_hook(ptr); \
120*68d75effSDimitry Andric SCOPED_INTERCEPTOR_RAW(mangled_name, ptr); \
121*68d75effSDimitry Andric user_free(thr, pc, ptr);
122*68d75effSDimitry Andric
123*68d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
124*68d75effSDimitry Andric void operator delete(void *ptr) NOEXCEPT;
operator delete(void * ptr)125*68d75effSDimitry Andric void operator delete(void *ptr) NOEXCEPT {
126*68d75effSDimitry Andric OPERATOR_DELETE_BODY(_ZdlPv);
127*68d75effSDimitry Andric }
128*68d75effSDimitry Andric
129*68d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
130*68d75effSDimitry Andric void operator delete[](void *ptr) NOEXCEPT;
operator delete[](void * ptr)131*68d75effSDimitry Andric void operator delete[](void *ptr) NOEXCEPT {
132*68d75effSDimitry Andric OPERATOR_DELETE_BODY(_ZdaPv);
133*68d75effSDimitry Andric }
134*68d75effSDimitry Andric
135*68d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
136*68d75effSDimitry Andric void operator delete(void *ptr, std::nothrow_t const&);
operator delete(void * ptr,std::nothrow_t const &)137*68d75effSDimitry Andric void operator delete(void *ptr, std::nothrow_t const&) {
138*68d75effSDimitry Andric OPERATOR_DELETE_BODY(_ZdlPvRKSt9nothrow_t);
139*68d75effSDimitry Andric }
140*68d75effSDimitry Andric
141*68d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
142*68d75effSDimitry Andric void operator delete[](void *ptr, std::nothrow_t const&);
operator delete[](void * ptr,std::nothrow_t const &)143*68d75effSDimitry Andric void operator delete[](void *ptr, std::nothrow_t const&) {
144*68d75effSDimitry Andric OPERATOR_DELETE_BODY(_ZdaPvRKSt9nothrow_t);
145*68d75effSDimitry Andric }
146*68d75effSDimitry Andric
147*68d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
148*68d75effSDimitry Andric void operator delete(void *ptr, __sanitizer::uptr size) NOEXCEPT;
operator delete(void * ptr,__sanitizer::uptr size)149*68d75effSDimitry Andric void operator delete(void *ptr, __sanitizer::uptr size) NOEXCEPT {
150*68d75effSDimitry Andric OPERATOR_DELETE_BODY(_ZdlPvm);
151*68d75effSDimitry Andric }
152*68d75effSDimitry Andric
153*68d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
154*68d75effSDimitry Andric void operator delete[](void *ptr, __sanitizer::uptr size) NOEXCEPT;
operator delete[](void * ptr,__sanitizer::uptr size)155*68d75effSDimitry Andric void operator delete[](void *ptr, __sanitizer::uptr size) NOEXCEPT {
156*68d75effSDimitry Andric OPERATOR_DELETE_BODY(_ZdaPvm);
157*68d75effSDimitry Andric }
158*68d75effSDimitry Andric
159*68d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
160*68d75effSDimitry Andric void operator delete(void *ptr, std::align_val_t align) NOEXCEPT;
operator delete(void * ptr,std::align_val_t align)161*68d75effSDimitry Andric void operator delete(void *ptr, std::align_val_t align) NOEXCEPT {
162*68d75effSDimitry Andric OPERATOR_DELETE_BODY(_ZdlPvSt11align_val_t);
163*68d75effSDimitry Andric }
164*68d75effSDimitry Andric
165*68d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
166*68d75effSDimitry Andric void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT;
operator delete[](void * ptr,std::align_val_t align)167*68d75effSDimitry Andric void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT {
168*68d75effSDimitry Andric OPERATOR_DELETE_BODY(_ZdaPvSt11align_val_t);
169*68d75effSDimitry Andric }
170*68d75effSDimitry Andric
171*68d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
172*68d75effSDimitry Andric void operator delete(void *ptr, std::align_val_t align, std::nothrow_t const&);
operator delete(void * ptr,std::align_val_t align,std::nothrow_t const &)173*68d75effSDimitry Andric void operator delete(void *ptr, std::align_val_t align, std::nothrow_t const&) {
174*68d75effSDimitry Andric OPERATOR_DELETE_BODY(_ZdlPvSt11align_val_tRKSt9nothrow_t);
175*68d75effSDimitry Andric }
176*68d75effSDimitry Andric
177*68d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
178*68d75effSDimitry Andric void operator delete[](void *ptr, std::align_val_t align,
179*68d75effSDimitry Andric std::nothrow_t const&);
operator delete[](void * ptr,std::align_val_t align,std::nothrow_t const &)180*68d75effSDimitry Andric void operator delete[](void *ptr, std::align_val_t align,
181*68d75effSDimitry Andric std::nothrow_t const&) {
182*68d75effSDimitry Andric OPERATOR_DELETE_BODY(_ZdaPvSt11align_val_tRKSt9nothrow_t);
183*68d75effSDimitry Andric }
184*68d75effSDimitry Andric
185*68d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
186*68d75effSDimitry Andric void operator delete(void *ptr, __sanitizer::uptr size,
187*68d75effSDimitry Andric std::align_val_t align) NOEXCEPT;
operator delete(void * ptr,__sanitizer::uptr size,std::align_val_t align)188*68d75effSDimitry Andric void operator delete(void *ptr, __sanitizer::uptr size,
189*68d75effSDimitry Andric std::align_val_t align) NOEXCEPT {
190*68d75effSDimitry Andric OPERATOR_DELETE_BODY(_ZdlPvmSt11align_val_t);
191*68d75effSDimitry Andric }
192*68d75effSDimitry Andric
193*68d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
194*68d75effSDimitry Andric void operator delete[](void *ptr, __sanitizer::uptr size,
195*68d75effSDimitry Andric std::align_val_t align) NOEXCEPT;
operator delete[](void * ptr,__sanitizer::uptr size,std::align_val_t align)196*68d75effSDimitry Andric void operator delete[](void *ptr, __sanitizer::uptr size,
197*68d75effSDimitry Andric std::align_val_t align) NOEXCEPT {
198*68d75effSDimitry Andric OPERATOR_DELETE_BODY(_ZdaPvmSt11align_val_t);
199*68d75effSDimitry Andric }
200