1*3cab2bb3Spatrick //===-- msan_new_delete.cpp -----------------------------------------------===//
2*3cab2bb3Spatrick //
3*3cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*3cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information.
5*3cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*3cab2bb3Spatrick //
7*3cab2bb3Spatrick //===----------------------------------------------------------------------===//
8*3cab2bb3Spatrick //
9*3cab2bb3Spatrick // This file is a part of MemorySanitizer.
10*3cab2bb3Spatrick //
11*3cab2bb3Spatrick // Interceptors for operators new and delete.
12*3cab2bb3Spatrick //===----------------------------------------------------------------------===//
13*3cab2bb3Spatrick
14*3cab2bb3Spatrick #include "msan.h"
15*3cab2bb3Spatrick #include "interception/interception.h"
16*3cab2bb3Spatrick #include "sanitizer_common/sanitizer_allocator.h"
17*3cab2bb3Spatrick #include "sanitizer_common/sanitizer_allocator_report.h"
18*3cab2bb3Spatrick
19*3cab2bb3Spatrick #if MSAN_REPLACE_OPERATORS_NEW_AND_DELETE
20*3cab2bb3Spatrick
21*3cab2bb3Spatrick #include <stddef.h>
22*3cab2bb3Spatrick
23*3cab2bb3Spatrick using namespace __msan;
24*3cab2bb3Spatrick
25*3cab2bb3Spatrick // Fake std::nothrow_t and std::align_val_t to avoid including <new>.
26*3cab2bb3Spatrick namespace std {
27*3cab2bb3Spatrick struct nothrow_t {};
28*3cab2bb3Spatrick enum class align_val_t: size_t {};
29*3cab2bb3Spatrick } // namespace std
30*3cab2bb3Spatrick
31*3cab2bb3Spatrick
32*3cab2bb3Spatrick // TODO(alekseys): throw std::bad_alloc instead of dying on OOM.
33*3cab2bb3Spatrick #define OPERATOR_NEW_BODY(nothrow) \
34*3cab2bb3Spatrick GET_MALLOC_STACK_TRACE; \
35*3cab2bb3Spatrick void *res = msan_malloc(size, &stack);\
36*3cab2bb3Spatrick if (!nothrow && UNLIKELY(!res)) ReportOutOfMemory(size, &stack);\
37*3cab2bb3Spatrick return res
38*3cab2bb3Spatrick #define OPERATOR_NEW_BODY_ALIGN(nothrow) \
39*3cab2bb3Spatrick GET_MALLOC_STACK_TRACE;\
40*3cab2bb3Spatrick void *res = msan_memalign((uptr)align, size, &stack);\
41*3cab2bb3Spatrick if (!nothrow && UNLIKELY(!res)) ReportOutOfMemory(size, &stack);\
42*3cab2bb3Spatrick return res;
43*3cab2bb3Spatrick
44*3cab2bb3Spatrick INTERCEPTOR_ATTRIBUTE
operator new(size_t size)45*3cab2bb3Spatrick void *operator new(size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }
46*3cab2bb3Spatrick INTERCEPTOR_ATTRIBUTE
operator new[](size_t size)47*3cab2bb3Spatrick void *operator new[](size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }
48*3cab2bb3Spatrick INTERCEPTOR_ATTRIBUTE
operator new(size_t size,std::nothrow_t const &)49*3cab2bb3Spatrick void *operator new(size_t size, std::nothrow_t const&) {
50*3cab2bb3Spatrick OPERATOR_NEW_BODY(true /*nothrow*/);
51*3cab2bb3Spatrick }
52*3cab2bb3Spatrick INTERCEPTOR_ATTRIBUTE
operator new[](size_t size,std::nothrow_t const &)53*3cab2bb3Spatrick void *operator new[](size_t size, std::nothrow_t const&) {
54*3cab2bb3Spatrick OPERATOR_NEW_BODY(true /*nothrow*/);
55*3cab2bb3Spatrick }
56*3cab2bb3Spatrick INTERCEPTOR_ATTRIBUTE
operator new(size_t size,std::align_val_t align)57*3cab2bb3Spatrick void *operator new(size_t size, std::align_val_t align)
58*3cab2bb3Spatrick { OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/); }
59*3cab2bb3Spatrick INTERCEPTOR_ATTRIBUTE
operator new[](size_t size,std::align_val_t align)60*3cab2bb3Spatrick void *operator new[](size_t size, std::align_val_t align)
61*3cab2bb3Spatrick { OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/); }
62*3cab2bb3Spatrick INTERCEPTOR_ATTRIBUTE
operator new(size_t size,std::align_val_t align,std::nothrow_t const &)63*3cab2bb3Spatrick void *operator new(size_t size, std::align_val_t align, std::nothrow_t const&)
64*3cab2bb3Spatrick { OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/); }
65*3cab2bb3Spatrick INTERCEPTOR_ATTRIBUTE
operator new[](size_t size,std::align_val_t align,std::nothrow_t const &)66*3cab2bb3Spatrick void *operator new[](size_t size, std::align_val_t align, std::nothrow_t const&)
67*3cab2bb3Spatrick { OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/); }
68*3cab2bb3Spatrick
69*3cab2bb3Spatrick #define OPERATOR_DELETE_BODY \
70*3cab2bb3Spatrick GET_MALLOC_STACK_TRACE; \
71*3cab2bb3Spatrick if (ptr) MsanDeallocate(&stack, ptr)
72*3cab2bb3Spatrick
73*3cab2bb3Spatrick INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr)74*3cab2bb3Spatrick void operator delete(void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; }
75*3cab2bb3Spatrick INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr)76*3cab2bb3Spatrick void operator delete[](void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; }
77*3cab2bb3Spatrick INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,std::nothrow_t const &)78*3cab2bb3Spatrick void operator delete(void *ptr, std::nothrow_t const&) { OPERATOR_DELETE_BODY; }
79*3cab2bb3Spatrick INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,std::nothrow_t const &)80*3cab2bb3Spatrick void operator delete[](void *ptr, std::nothrow_t const&) {
81*3cab2bb3Spatrick OPERATOR_DELETE_BODY;
82*3cab2bb3Spatrick }
83*3cab2bb3Spatrick INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,size_t size)84*3cab2bb3Spatrick void operator delete(void *ptr, size_t size) NOEXCEPT { OPERATOR_DELETE_BODY; }
85*3cab2bb3Spatrick INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,size_t size)86*3cab2bb3Spatrick void operator delete[](void *ptr, size_t size) NOEXCEPT
87*3cab2bb3Spatrick { OPERATOR_DELETE_BODY; }
88*3cab2bb3Spatrick INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,std::align_val_t align)89*3cab2bb3Spatrick void operator delete(void *ptr, std::align_val_t align) NOEXCEPT
90*3cab2bb3Spatrick { OPERATOR_DELETE_BODY; }
91*3cab2bb3Spatrick INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,std::align_val_t align)92*3cab2bb3Spatrick void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT
93*3cab2bb3Spatrick { OPERATOR_DELETE_BODY; }
94*3cab2bb3Spatrick INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,std::align_val_t align,std::nothrow_t const &)95*3cab2bb3Spatrick void operator delete(void *ptr, std::align_val_t align, std::nothrow_t const&)
96*3cab2bb3Spatrick { OPERATOR_DELETE_BODY; }
97*3cab2bb3Spatrick INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,std::align_val_t align,std::nothrow_t const &)98*3cab2bb3Spatrick void operator delete[](void *ptr, std::align_val_t align, std::nothrow_t const&)
99*3cab2bb3Spatrick { OPERATOR_DELETE_BODY; }
100*3cab2bb3Spatrick INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,size_t size,std::align_val_t align)101*3cab2bb3Spatrick void operator delete(void *ptr, size_t size, std::align_val_t align) NOEXCEPT
102*3cab2bb3Spatrick { OPERATOR_DELETE_BODY; }
103*3cab2bb3Spatrick INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,size_t size,std::align_val_t align)104*3cab2bb3Spatrick void operator delete[](void *ptr, size_t size, std::align_val_t align) NOEXCEPT
105*3cab2bb3Spatrick { OPERATOR_DELETE_BODY; }
106*3cab2bb3Spatrick
107*3cab2bb3Spatrick
108*3cab2bb3Spatrick #endif // MSAN_REPLACE_OPERATORS_NEW_AND_DELETE
109