127 lines · cpp
1//===-- nsan_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-exception6//7//===----------------------------------------------------------------------===//8//9// This file is a part of MemorySanitizer.10//11// Interceptors for operators new and delete.12//===----------------------------------------------------------------------===//13 14#include "interception/interception.h"15#include "nsan.h"16#include "nsan_allocator.h"17#include "sanitizer_common/sanitizer_allocator.h"18#include "sanitizer_common/sanitizer_allocator_report.h"19 20#include <stddef.h>21 22using namespace __nsan;23 24// Fake std::nothrow_t and std::align_val_t to avoid including <new>.25namespace std {26struct nothrow_t {};27enum class align_val_t : size_t {};28} // namespace std29 30#define OPERATOR_NEW_BODY(nothrow) \31 void *res = nsan_malloc(size); \32 if (!nothrow && UNLIKELY(!res)) { \33 BufferedStackTrace stack; \34 GET_FATAL_STACK_TRACE_IF_EMPTY(&stack); \35 ReportOutOfMemory(size, &stack); \36 } \37 return res38#define OPERATOR_NEW_BODY_ALIGN(nothrow) \39 void *res = nsan_memalign((uptr)align, size); \40 if (!nothrow && UNLIKELY(!res)) { \41 BufferedStackTrace stack; \42 GET_FATAL_STACK_TRACE_IF_EMPTY(&stack); \43 ReportOutOfMemory(size, &stack); \44 } \45 return res;46 47INTERCEPTOR_ATTRIBUTE48void *operator new(size_t size) { OPERATOR_NEW_BODY(/*nothrow=*/false); }49INTERCEPTOR_ATTRIBUTE50void *operator new[](size_t size) { OPERATOR_NEW_BODY(/*nothrow=*/false); }51INTERCEPTOR_ATTRIBUTE52void *operator new(size_t size, std::nothrow_t const &) {53 OPERATOR_NEW_BODY(/*nothrow=*/true);54}55INTERCEPTOR_ATTRIBUTE56void *operator new[](size_t size, std::nothrow_t const &) {57 OPERATOR_NEW_BODY(/*nothrow=*/true);58}59INTERCEPTOR_ATTRIBUTE60void *operator new(size_t size, std::align_val_t align) {61 OPERATOR_NEW_BODY_ALIGN(/*nothrow=*/false);62}63INTERCEPTOR_ATTRIBUTE64void *operator new[](size_t size, std::align_val_t align) {65 OPERATOR_NEW_BODY_ALIGN(/*nothrow=*/false);66}67INTERCEPTOR_ATTRIBUTE68void *operator new(size_t size, std::align_val_t align,69 std::nothrow_t const &) {70 OPERATOR_NEW_BODY_ALIGN(/*nothrow=*/true);71}72INTERCEPTOR_ATTRIBUTE73void *operator new[](size_t size, std::align_val_t align,74 std::nothrow_t const &) {75 OPERATOR_NEW_BODY_ALIGN(/*nothrow=*/true);76}77 78#define OPERATOR_DELETE_BODY \79 if (ptr) \80 NsanDeallocate(ptr)81 82INTERCEPTOR_ATTRIBUTE83void operator delete(void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; }84INTERCEPTOR_ATTRIBUTE85void operator delete[](void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; }86INTERCEPTOR_ATTRIBUTE87void operator delete(void *ptr, std::nothrow_t const &) {88 OPERATOR_DELETE_BODY;89}90INTERCEPTOR_ATTRIBUTE91void operator delete[](void *ptr, std::nothrow_t const &) {92 OPERATOR_DELETE_BODY;93}94INTERCEPTOR_ATTRIBUTE95void operator delete(void *ptr, size_t size) NOEXCEPT { OPERATOR_DELETE_BODY; }96INTERCEPTOR_ATTRIBUTE97void operator delete[](void *ptr, size_t size) NOEXCEPT {98 OPERATOR_DELETE_BODY;99}100INTERCEPTOR_ATTRIBUTE101void operator delete(void *ptr, std::align_val_t align) NOEXCEPT {102 OPERATOR_DELETE_BODY;103}104INTERCEPTOR_ATTRIBUTE105void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT {106 OPERATOR_DELETE_BODY;107}108INTERCEPTOR_ATTRIBUTE109void operator delete(void *ptr, std::align_val_t align,110 std::nothrow_t const &) {111 OPERATOR_DELETE_BODY;112}113INTERCEPTOR_ATTRIBUTE114void operator delete[](void *ptr, std::align_val_t align,115 std::nothrow_t const &) {116 OPERATOR_DELETE_BODY;117}118INTERCEPTOR_ATTRIBUTE119void operator delete(void *ptr, size_t size, std::align_val_t align) NOEXCEPT {120 OPERATOR_DELETE_BODY;121}122INTERCEPTOR_ATTRIBUTE123void operator delete[](void *ptr, size_t size,124 std::align_val_t align) NOEXCEPT {125 OPERATOR_DELETE_BODY;126}127