xref: /freebsd-src/contrib/llvm-project/compiler-rt/lib/msan/msan_new_delete.cpp (revision 1db9f3b21e39176dd5b67cf8ac378633b172463e)
168d75effSDimitry Andric //===-- msan_new_delete.cpp -----------------------------------------------===//
268d75effSDimitry Andric //
368d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
468d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
568d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
668d75effSDimitry Andric //
768d75effSDimitry Andric //===----------------------------------------------------------------------===//
868d75effSDimitry Andric //
968d75effSDimitry Andric // This file is a part of MemorySanitizer.
1068d75effSDimitry Andric //
1168d75effSDimitry Andric // Interceptors for operators new and delete.
1268d75effSDimitry Andric //===----------------------------------------------------------------------===//
1368d75effSDimitry Andric 
1468d75effSDimitry Andric #include "msan.h"
1568d75effSDimitry Andric #include "interception/interception.h"
1668d75effSDimitry Andric #include "sanitizer_common/sanitizer_allocator.h"
1768d75effSDimitry Andric #include "sanitizer_common/sanitizer_allocator_report.h"
1868d75effSDimitry Andric 
1968d75effSDimitry Andric #if MSAN_REPLACE_OPERATORS_NEW_AND_DELETE
2068d75effSDimitry Andric 
2168d75effSDimitry Andric #include <stddef.h>
2268d75effSDimitry Andric 
2368d75effSDimitry Andric using namespace __msan;
2468d75effSDimitry Andric 
2568d75effSDimitry Andric // Fake std::nothrow_t and std::align_val_t to avoid including <new>.
2668d75effSDimitry Andric namespace std {
2768d75effSDimitry Andric   struct nothrow_t {};
2868d75effSDimitry Andric   enum class align_val_t: size_t {};
2968d75effSDimitry Andric }  // namespace std
3068d75effSDimitry Andric 
3168d75effSDimitry Andric 
3268d75effSDimitry Andric // TODO(alekseys): throw std::bad_alloc instead of dying on OOM.
3368d75effSDimitry Andric #  define OPERATOR_NEW_BODY(nothrow)          \
3468d75effSDimitry Andric     GET_MALLOC_STACK_TRACE;                   \
3568d75effSDimitry Andric     void *res = msan_malloc(size, &stack);    \
36*1db9f3b2SDimitry Andric     if (!nothrow && UNLIKELY(!res)) {         \
37*1db9f3b2SDimitry Andric       GET_FATAL_STACK_TRACE_IF_EMPTY(&stack); \
38*1db9f3b2SDimitry Andric       ReportOutOfMemory(size, &stack);        \
39*1db9f3b2SDimitry Andric     }                                         \
4068d75effSDimitry Andric     return res
4168d75effSDimitry Andric #  define OPERATOR_NEW_BODY_ALIGN(nothrow)                \
4268d75effSDimitry Andric     GET_MALLOC_STACK_TRACE;                               \
4368d75effSDimitry Andric     void *res = msan_memalign((uptr)align, size, &stack); \
44*1db9f3b2SDimitry Andric     if (!nothrow && UNLIKELY(!res)) {                     \
45*1db9f3b2SDimitry Andric       GET_FATAL_STACK_TRACE_IF_EMPTY(&stack);             \
46*1db9f3b2SDimitry Andric       ReportOutOfMemory(size, &stack);                    \
47*1db9f3b2SDimitry Andric     }                                                     \
4868d75effSDimitry Andric     return res;
4968d75effSDimitry Andric 
5068d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator new(size_t size)5168d75effSDimitry Andric void *operator new(size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }
5268d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator new[](size_t size)5368d75effSDimitry Andric void *operator new[](size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }
5468d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator new(size_t size,std::nothrow_t const &)5568d75effSDimitry Andric void *operator new(size_t size, std::nothrow_t const&) {
5668d75effSDimitry Andric   OPERATOR_NEW_BODY(true /*nothrow*/);
5768d75effSDimitry Andric }
5868d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator new[](size_t size,std::nothrow_t const &)5968d75effSDimitry Andric void *operator new[](size_t size, std::nothrow_t const&) {
6068d75effSDimitry Andric   OPERATOR_NEW_BODY(true /*nothrow*/);
6168d75effSDimitry Andric }
6268d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator new(size_t size,std::align_val_t align)6368d75effSDimitry Andric void *operator new(size_t size, std::align_val_t align)
6468d75effSDimitry Andric { OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/); }
6568d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator new[](size_t size,std::align_val_t align)6668d75effSDimitry Andric void *operator new[](size_t size, std::align_val_t align)
6768d75effSDimitry Andric { OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/); }
6868d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator new(size_t size,std::align_val_t align,std::nothrow_t const &)6968d75effSDimitry Andric void *operator new(size_t size, std::align_val_t align, std::nothrow_t const&)
7068d75effSDimitry Andric { OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/); }
7168d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator new[](size_t size,std::align_val_t align,std::nothrow_t const &)7268d75effSDimitry Andric void *operator new[](size_t size, std::align_val_t align, std::nothrow_t const&)
7368d75effSDimitry Andric { OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/); }
7468d75effSDimitry Andric 
7568d75effSDimitry Andric #define OPERATOR_DELETE_BODY \
7668d75effSDimitry Andric   GET_MALLOC_STACK_TRACE; \
7768d75effSDimitry Andric   if (ptr) MsanDeallocate(&stack, ptr)
7868d75effSDimitry Andric 
7968d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr)8068d75effSDimitry Andric void operator delete(void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; }
8168d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr)8268d75effSDimitry Andric void operator delete[](void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; }
8368d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,std::nothrow_t const &)8468d75effSDimitry Andric void operator delete(void *ptr, std::nothrow_t const&) { OPERATOR_DELETE_BODY; }
8568d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,std::nothrow_t const &)8668d75effSDimitry Andric void operator delete[](void *ptr, std::nothrow_t const&) {
8768d75effSDimitry Andric   OPERATOR_DELETE_BODY;
8868d75effSDimitry Andric }
8968d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,size_t size)9068d75effSDimitry Andric void operator delete(void *ptr, size_t size) NOEXCEPT { OPERATOR_DELETE_BODY; }
9168d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,size_t size)9268d75effSDimitry Andric void operator delete[](void *ptr, size_t size) NOEXCEPT
9368d75effSDimitry Andric { OPERATOR_DELETE_BODY; }
9468d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,std::align_val_t align)9568d75effSDimitry Andric void operator delete(void *ptr, std::align_val_t align) NOEXCEPT
9668d75effSDimitry Andric { OPERATOR_DELETE_BODY; }
9768d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,std::align_val_t align)9868d75effSDimitry Andric void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT
9968d75effSDimitry Andric { OPERATOR_DELETE_BODY; }
10068d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,std::align_val_t align,std::nothrow_t const &)10168d75effSDimitry Andric void operator delete(void *ptr, std::align_val_t align, std::nothrow_t const&)
10268d75effSDimitry Andric { OPERATOR_DELETE_BODY; }
10368d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,std::align_val_t align,std::nothrow_t const &)10468d75effSDimitry Andric void operator delete[](void *ptr, std::align_val_t align, std::nothrow_t const&)
10568d75effSDimitry Andric { OPERATOR_DELETE_BODY; }
10668d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,size_t size,std::align_val_t align)10768d75effSDimitry Andric void operator delete(void *ptr, size_t size, std::align_val_t align) NOEXCEPT
10868d75effSDimitry Andric { OPERATOR_DELETE_BODY; }
10968d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,size_t size,std::align_val_t align)11068d75effSDimitry Andric void operator delete[](void *ptr, size_t size, std::align_val_t align) NOEXCEPT
11168d75effSDimitry Andric { OPERATOR_DELETE_BODY; }
11268d75effSDimitry Andric 
11368d75effSDimitry Andric 
11468d75effSDimitry Andric #endif // MSAN_REPLACE_OPERATORS_NEW_AND_DELETE
115