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 |
46 | void *operator new(size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); } |
47 | INTERCEPTOR_ATTRIBUTE |
48 | void *operator new[](size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); } |
49 | INTERCEPTOR_ATTRIBUTE |
50 | void *operator new(size_t size, std::nothrow_t const &) { |
51 | OPERATOR_NEW_BODY(true /*nothrow*/); |
52 | } |
53 | INTERCEPTOR_ATTRIBUTE |
54 | void *operator new[](size_t size, std::nothrow_t const &) { |
55 | OPERATOR_NEW_BODY(true /*nothrow*/); |
56 | } |
57 | INTERCEPTOR_ATTRIBUTE |
58 | void *operator new(size_t size, std::align_val_t align) { |
59 | OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/); |
60 | } |
61 | INTERCEPTOR_ATTRIBUTE |
62 | void *operator new[](size_t size, std::align_val_t align) { |
63 | OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/); |
64 | } |
65 | INTERCEPTOR_ATTRIBUTE |
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 |
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 |
81 | void operator delete(void *ptr)NOEXCEPT { OPERATOR_DELETE_BODY; } |
82 | INTERCEPTOR_ATTRIBUTE |
83 | void operator delete[](void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; } |
84 | INTERCEPTOR_ATTRIBUTE |
85 | void operator delete(void *ptr, std::nothrow_t const &) { |
86 | OPERATOR_DELETE_BODY; |
87 | } |
88 | INTERCEPTOR_ATTRIBUTE |
89 | void operator delete[](void *ptr, std::nothrow_t const &) { |
90 | OPERATOR_DELETE_BODY; |
91 | } |
92 | INTERCEPTOR_ATTRIBUTE |
93 | void operator delete(void *ptr, size_t size)NOEXCEPT { OPERATOR_DELETE_BODY; } |
94 | INTERCEPTOR_ATTRIBUTE |
95 | void operator delete[](void *ptr, size_t size) NOEXCEPT { |
96 | OPERATOR_DELETE_BODY; |
97 | } |
98 | INTERCEPTOR_ATTRIBUTE |
99 | void operator delete(void *ptr, std::align_val_t align)NOEXCEPT { |
100 | OPERATOR_DELETE_BODY; |
101 | } |
102 | INTERCEPTOR_ATTRIBUTE |
103 | void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT { |
104 | OPERATOR_DELETE_BODY; |
105 | } |
106 | INTERCEPTOR_ATTRIBUTE |
107 | void operator delete(void *ptr, std::align_val_t align, |
108 | std::nothrow_t const &) { |
109 | OPERATOR_DELETE_BODY; |
110 | } |
111 | INTERCEPTOR_ATTRIBUTE |
112 | void operator delete[](void *ptr, std::align_val_t align, |
113 | std::nothrow_t const &) { |
114 | OPERATOR_DELETE_BODY; |
115 | } |
116 | INTERCEPTOR_ATTRIBUTE |
117 | void operator delete(void *ptr, size_t size, std::align_val_t align)NOEXCEPT { |
118 | OPERATOR_DELETE_BODY; |
119 | } |
120 | INTERCEPTOR_ATTRIBUTE |
121 | void operator delete[](void *ptr, size_t size, |
122 | std::align_val_t align) NOEXCEPT { |
123 | OPERATOR_DELETE_BODY; |
124 | } |
125 | |