1 //===-- nsan_new_delete.cpp -----------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file is a part of MemorySanitizer.
11 // Interceptors for operators new and delete.
12 //===----------------------------------------------------------------------===//
14 #include "interception/interception.h"
16 #include "nsan_allocator.h"
17 #include "sanitizer_common/sanitizer_allocator.h"
18 #include "sanitizer_common/sanitizer_allocator_report.h"
22 using namespace __nsan
;
24 // Fake std::nothrow_t and std::align_val_t to avoid including <new>.
27 enum class align_val_t
: size_t {};
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); \
38 #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); \
48 void *operator new(size_t size
) { OPERATOR_NEW_BODY(/*nothrow=*/false); }
50 void *operator new[](size_t size
) { OPERATOR_NEW_BODY(/*nothrow=*/false); }
52 void *operator new(size_t size
, std::nothrow_t
const &) {
53 OPERATOR_NEW_BODY(/*nothrow=*/true);
56 void *operator new[](size_t size
, std::nothrow_t
const &) {
57 OPERATOR_NEW_BODY(/*nothrow=*/true);
60 void *operator new(size_t size
, std::align_val_t align
) {
61 OPERATOR_NEW_BODY_ALIGN(/*nothrow=*/false);
64 void *operator new[](size_t size
, std::align_val_t align
) {
65 OPERATOR_NEW_BODY_ALIGN(/*nothrow=*/false);
68 void *operator new(size_t size
, std::align_val_t align
,
69 std::nothrow_t
const &) {
70 OPERATOR_NEW_BODY_ALIGN(/*nothrow=*/true);
73 void *operator new[](size_t size
, std::align_val_t align
,
74 std::nothrow_t
const &) {
75 OPERATOR_NEW_BODY_ALIGN(/*nothrow=*/true);
78 #define OPERATOR_DELETE_BODY \
83 void operator delete(void *ptr
) NOEXCEPT
{ OPERATOR_DELETE_BODY
; }
85 void operator delete[](void *ptr
) NOEXCEPT
{ OPERATOR_DELETE_BODY
; }
87 void operator delete(void *ptr
, std::nothrow_t
const &) {
91 void operator delete[](void *ptr
, std::nothrow_t
const &) {
95 void operator delete(void *ptr
, size_t size
) NOEXCEPT
{ OPERATOR_DELETE_BODY
; }
97 void operator delete[](void *ptr
, size_t size
) NOEXCEPT
{
100 INTERCEPTOR_ATTRIBUTE
101 void operator delete(void *ptr
, std::align_val_t align
) NOEXCEPT
{
102 OPERATOR_DELETE_BODY
;
104 INTERCEPTOR_ATTRIBUTE
105 void operator delete[](void *ptr
, std::align_val_t align
) NOEXCEPT
{
106 OPERATOR_DELETE_BODY
;
108 INTERCEPTOR_ATTRIBUTE
109 void operator delete(void *ptr
, std::align_val_t align
,
110 std::nothrow_t
const &) {
111 OPERATOR_DELETE_BODY
;
113 INTERCEPTOR_ATTRIBUTE
114 void operator delete[](void *ptr
, std::align_val_t align
,
115 std::nothrow_t
const &) {
116 OPERATOR_DELETE_BODY
;
118 INTERCEPTOR_ATTRIBUTE
119 void operator delete(void *ptr
, size_t size
, std::align_val_t align
) NOEXCEPT
{
120 OPERATOR_DELETE_BODY
;
122 INTERCEPTOR_ATTRIBUTE
123 void operator delete[](void *ptr
, size_t size
,
124 std::align_val_t align
) NOEXCEPT
{
125 OPERATOR_DELETE_BODY
;