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 5168d75effSDimitry Andric void *operator new(size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); } 5268d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 5368d75effSDimitry Andric void *operator new[](size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); } 5468d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 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 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 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 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 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 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 8068d75effSDimitry Andric void operator delete(void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; } 8168d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 8268d75effSDimitry Andric void operator delete[](void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; } 8368d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 8468d75effSDimitry Andric void operator delete(void *ptr, std::nothrow_t const&) { OPERATOR_DELETE_BODY; } 8568d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 8668d75effSDimitry Andric void operator delete[](void *ptr, std::nothrow_t const&) { 8768d75effSDimitry Andric OPERATOR_DELETE_BODY; 8868d75effSDimitry Andric } 8968d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 9068d75effSDimitry Andric void operator delete(void *ptr, size_t size) NOEXCEPT { OPERATOR_DELETE_BODY; } 9168d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 9268d75effSDimitry Andric void operator delete[](void *ptr, size_t size) NOEXCEPT 9368d75effSDimitry Andric { OPERATOR_DELETE_BODY; } 9468d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 9568d75effSDimitry Andric void operator delete(void *ptr, std::align_val_t align) NOEXCEPT 9668d75effSDimitry Andric { OPERATOR_DELETE_BODY; } 9768d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 9868d75effSDimitry Andric void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT 9968d75effSDimitry Andric { OPERATOR_DELETE_BODY; } 10068d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 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 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 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 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