160c66db4SNico Weber //===-- msan_new_delete.cpp -----------------------------------------------===//
260c66db4SNico Weber //
360c66db4SNico Weber // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
460c66db4SNico Weber // See https://llvm.org/LICENSE.txt for license information.
560c66db4SNico Weber // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
660c66db4SNico Weber //
760c66db4SNico Weber //===----------------------------------------------------------------------===//
860c66db4SNico Weber //
960c66db4SNico Weber // This file is a part of MemorySanitizer.
1060c66db4SNico Weber //
1160c66db4SNico Weber // Interceptors for operators new and delete.
1260c66db4SNico Weber //===----------------------------------------------------------------------===//
1360c66db4SNico Weber
1460c66db4SNico Weber #include "msan.h"
1560c66db4SNico Weber #include "interception/interception.h"
1660c66db4SNico Weber #include "sanitizer_common/sanitizer_allocator.h"
1760c66db4SNico Weber #include "sanitizer_common/sanitizer_allocator_report.h"
1860c66db4SNico Weber
1960c66db4SNico Weber #if MSAN_REPLACE_OPERATORS_NEW_AND_DELETE
2060c66db4SNico Weber
2160c66db4SNico Weber #include <stddef.h>
2260c66db4SNico Weber
23c0fa6322SVitaly Buka using namespace __msan;
2460c66db4SNico Weber
2560c66db4SNico Weber // Fake std::nothrow_t and std::align_val_t to avoid including <new>.
2660c66db4SNico Weber namespace std {
2760c66db4SNico Weber struct nothrow_t {};
2860c66db4SNico Weber enum class align_val_t: size_t {};
2960c66db4SNico Weber } // namespace std
3060c66db4SNico Weber
3160c66db4SNico Weber
3260c66db4SNico Weber // TODO(alekseys): throw std::bad_alloc instead of dying on OOM.
3360c66db4SNico Weber # define OPERATOR_NEW_BODY(nothrow) \
3460c66db4SNico Weber GET_MALLOC_STACK_TRACE; \
3560c66db4SNico Weber void *res = msan_malloc(size, &stack); \
36*89809363SVitaly Buka if (!nothrow && UNLIKELY(!res)) { \
37*89809363SVitaly Buka GET_FATAL_STACK_TRACE_IF_EMPTY(&stack); \
38*89809363SVitaly Buka ReportOutOfMemory(size, &stack); \
39*89809363SVitaly Buka } \
4060c66db4SNico Weber return res
4160c66db4SNico Weber # define OPERATOR_NEW_BODY_ALIGN(nothrow) \
4260c66db4SNico Weber GET_MALLOC_STACK_TRACE; \
4360c66db4SNico Weber void *res = msan_memalign((uptr)align, size, &stack); \
44*89809363SVitaly Buka if (!nothrow && UNLIKELY(!res)) { \
45*89809363SVitaly Buka GET_FATAL_STACK_TRACE_IF_EMPTY(&stack); \
46*89809363SVitaly Buka ReportOutOfMemory(size, &stack); \
47*89809363SVitaly Buka } \
4860c66db4SNico Weber return res;
4960c66db4SNico Weber
5060c66db4SNico Weber INTERCEPTOR_ATTRIBUTE
operator new(size_t size)5160c66db4SNico Weber void *operator new(size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }
5260c66db4SNico Weber INTERCEPTOR_ATTRIBUTE
operator new[](size_t size)5360c66db4SNico Weber void *operator new[](size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }
5460c66db4SNico Weber INTERCEPTOR_ATTRIBUTE
operator new(size_t size,std::nothrow_t const &)5560c66db4SNico Weber void *operator new(size_t size, std::nothrow_t const&) {
5660c66db4SNico Weber OPERATOR_NEW_BODY(true /*nothrow*/);
5760c66db4SNico Weber }
5860c66db4SNico Weber INTERCEPTOR_ATTRIBUTE
operator new[](size_t size,std::nothrow_t const &)5960c66db4SNico Weber void *operator new[](size_t size, std::nothrow_t const&) {
6060c66db4SNico Weber OPERATOR_NEW_BODY(true /*nothrow*/);
6160c66db4SNico Weber }
6260c66db4SNico Weber INTERCEPTOR_ATTRIBUTE
operator new(size_t size,std::align_val_t align)6360c66db4SNico Weber void *operator new(size_t size, std::align_val_t align)
6460c66db4SNico Weber { OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/); }
6560c66db4SNico Weber INTERCEPTOR_ATTRIBUTE
operator new[](size_t size,std::align_val_t align)6660c66db4SNico Weber void *operator new[](size_t size, std::align_val_t align)
6760c66db4SNico Weber { OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/); }
6860c66db4SNico Weber INTERCEPTOR_ATTRIBUTE
operator new(size_t size,std::align_val_t align,std::nothrow_t const &)6960c66db4SNico Weber void *operator new(size_t size, std::align_val_t align, std::nothrow_t const&)
7060c66db4SNico Weber { OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/); }
7160c66db4SNico Weber INTERCEPTOR_ATTRIBUTE
operator new[](size_t size,std::align_val_t align,std::nothrow_t const &)7260c66db4SNico Weber void *operator new[](size_t size, std::align_val_t align, std::nothrow_t const&)
7360c66db4SNico Weber { OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/); }
7460c66db4SNico Weber
7560c66db4SNico Weber #define OPERATOR_DELETE_BODY \
7660c66db4SNico Weber GET_MALLOC_STACK_TRACE; \
7760c66db4SNico Weber if (ptr) MsanDeallocate(&stack, ptr)
7860c66db4SNico Weber
7960c66db4SNico Weber INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr)8060c66db4SNico Weber void operator delete(void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; }
8160c66db4SNico Weber INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr)8260c66db4SNico Weber void operator delete[](void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; }
8360c66db4SNico Weber INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,std::nothrow_t const &)8460c66db4SNico Weber void operator delete(void *ptr, std::nothrow_t const&) { OPERATOR_DELETE_BODY; }
8560c66db4SNico Weber INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,std::nothrow_t const &)8660c66db4SNico Weber void operator delete[](void *ptr, std::nothrow_t const&) {
8760c66db4SNico Weber OPERATOR_DELETE_BODY;
8860c66db4SNico Weber }
8960c66db4SNico Weber INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,size_t size)9060c66db4SNico Weber void operator delete(void *ptr, size_t size) NOEXCEPT { OPERATOR_DELETE_BODY; }
9160c66db4SNico Weber INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,size_t size)9260c66db4SNico Weber void operator delete[](void *ptr, size_t size) NOEXCEPT
9360c66db4SNico Weber { OPERATOR_DELETE_BODY; }
9460c66db4SNico Weber INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,std::align_val_t align)9560c66db4SNico Weber void operator delete(void *ptr, std::align_val_t align) NOEXCEPT
9660c66db4SNico Weber { OPERATOR_DELETE_BODY; }
9760c66db4SNico Weber INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,std::align_val_t align)9860c66db4SNico Weber void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT
9960c66db4SNico Weber { OPERATOR_DELETE_BODY; }
10060c66db4SNico Weber INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,std::align_val_t align,std::nothrow_t const &)10160c66db4SNico Weber void operator delete(void *ptr, std::align_val_t align, std::nothrow_t const&)
10260c66db4SNico Weber { OPERATOR_DELETE_BODY; }
10360c66db4SNico Weber INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,std::align_val_t align,std::nothrow_t const &)10460c66db4SNico Weber void operator delete[](void *ptr, std::align_val_t align, std::nothrow_t const&)
10560c66db4SNico Weber { OPERATOR_DELETE_BODY; }
10660c66db4SNico Weber INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,size_t size,std::align_val_t align)10760c66db4SNico Weber void operator delete(void *ptr, size_t size, std::align_val_t align) NOEXCEPT
10860c66db4SNico Weber { OPERATOR_DELETE_BODY; }
10960c66db4SNico Weber INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,size_t size,std::align_val_t align)11060c66db4SNico Weber void operator delete[](void *ptr, size_t size, std::align_val_t align) NOEXCEPT
11160c66db4SNico Weber { OPERATOR_DELETE_BODY; }
11260c66db4SNico Weber
11360c66db4SNico Weber
11460c66db4SNico Weber #endif // MSAN_REPLACE_OPERATORS_NEW_AND_DELETE
115