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