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