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