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