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