1 //===-- dfsan_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 DataflowSanitizer.
10 //
11 // Interceptors for operators new and delete.
12 //===----------------------------------------------------------------------===//
13
14 #include <stddef.h>
15
16 #include "dfsan.h"
17 #include "interception/interception.h"
18 #include "sanitizer_common/sanitizer_allocator.h"
19 #include "sanitizer_common/sanitizer_allocator_report.h"
20
21 using namespace __dfsan;
22
23 // Fake std::nothrow_t and std::align_val_t to avoid including <new>.
24 namespace std {
25 struct nothrow_t {};
26 enum class align_val_t : size_t {};
27 } // namespace std
28
29 // TODO(alekseys): throw std::bad_alloc instead of dying on OOM.
30 #define OPERATOR_NEW_BODY(nothrow) \
31 void *res = dfsan_malloc(size); \
32 if (!nothrow && UNLIKELY(!res)) { \
33 BufferedStackTrace stack; \
34 ReportOutOfMemory(size, &stack); \
35 } \
36 return res
37 #define OPERATOR_NEW_BODY_ALIGN(nothrow) \
38 void *res = dfsan_memalign((uptr)align, size); \
39 if (!nothrow && UNLIKELY(!res)) { \
40 BufferedStackTrace stack; \
41 ReportOutOfMemory(size, &stack); \
42 } \
43 return res;
44
45 INTERCEPTOR_ATTRIBUTE
operator new(size_t size)46 void *operator new(size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }
47 INTERCEPTOR_ATTRIBUTE
operator new[](size_t size)48 void *operator new[](size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }
49 INTERCEPTOR_ATTRIBUTE
operator new(size_t size,std::nothrow_t const &)50 void *operator new(size_t size, std::nothrow_t const &) {
51 OPERATOR_NEW_BODY(true /*nothrow*/);
52 }
53 INTERCEPTOR_ATTRIBUTE
operator new[](size_t size,std::nothrow_t const &)54 void *operator new[](size_t size, std::nothrow_t const &) {
55 OPERATOR_NEW_BODY(true /*nothrow*/);
56 }
57 INTERCEPTOR_ATTRIBUTE
operator new(size_t size,std::align_val_t align)58 void *operator new(size_t size, std::align_val_t align) {
59 OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/);
60 }
61 INTERCEPTOR_ATTRIBUTE
operator new[](size_t size,std::align_val_t align)62 void *operator new[](size_t size, std::align_val_t align) {
63 OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/);
64 }
65 INTERCEPTOR_ATTRIBUTE
operator new(size_t size,std::align_val_t align,std::nothrow_t const &)66 void *operator new(size_t size, std::align_val_t align,
67 std::nothrow_t const &) {
68 OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/);
69 }
70 INTERCEPTOR_ATTRIBUTE
operator new[](size_t size,std::align_val_t align,std::nothrow_t const &)71 void *operator new[](size_t size, std::align_val_t align,
72 std::nothrow_t const &) {
73 OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/);
74 }
75
76 #define OPERATOR_DELETE_BODY \
77 if (ptr) \
78 dfsan_deallocate(ptr)
79
80 INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr)81 void operator delete(void *ptr)NOEXCEPT { OPERATOR_DELETE_BODY; }
82 INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr)83 void operator delete[](void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; }
84 INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,std::nothrow_t const &)85 void operator delete(void *ptr, std::nothrow_t const &) {
86 OPERATOR_DELETE_BODY;
87 }
88 INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,std::nothrow_t const &)89 void operator delete[](void *ptr, std::nothrow_t const &) {
90 OPERATOR_DELETE_BODY;
91 }
92 INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,size_t size)93 void operator delete(void *ptr, size_t size)NOEXCEPT { OPERATOR_DELETE_BODY; }
94 INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,size_t size)95 void operator delete[](void *ptr, size_t size) NOEXCEPT {
96 OPERATOR_DELETE_BODY;
97 }
98 INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,std::align_val_t align)99 void operator delete(void *ptr, std::align_val_t align)NOEXCEPT {
100 OPERATOR_DELETE_BODY;
101 }
102 INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,std::align_val_t align)103 void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT {
104 OPERATOR_DELETE_BODY;
105 }
106 INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,std::align_val_t align,std::nothrow_t const &)107 void operator delete(void *ptr, std::align_val_t align,
108 std::nothrow_t const &) {
109 OPERATOR_DELETE_BODY;
110 }
111 INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,std::align_val_t align,std::nothrow_t const &)112 void operator delete[](void *ptr, std::align_val_t align,
113 std::nothrow_t const &) {
114 OPERATOR_DELETE_BODY;
115 }
116 INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,size_t size,std::align_val_t align)117 void operator delete(void *ptr, size_t size, std::align_val_t align)NOEXCEPT {
118 OPERATOR_DELETE_BODY;
119 }
120 INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,size_t size,std::align_val_t align)121 void operator delete[](void *ptr, size_t size,
122 std::align_val_t align) NOEXCEPT {
123 OPERATOR_DELETE_BODY;
124 }
125