1//===-- scudo_new_delete.cpp ------------------------------------*- C++ -*-===//
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/// Interceptors for operators new and delete.
10///
11//===----------------------------------------------------------------------===//
12
13#include "scudo_allocator.h"
14#include "scudo_errors.h"
15
16#include "interception/interception.h"
17
18#include <stddef.h>
19
20using namespace __scudo;
21
22#define CXX_OPERATOR_ATTRIBUTE INTERCEPTOR_ATTRIBUTE
23
24// Fake std::nothrow_t to avoid including <new>.
25namespace std {
26struct nothrow_t {};
27enum class align_val_t: size_t {};
28}  // namespace std
29
30// TODO(alekseys): throw std::bad_alloc instead of dying on OOM.
31#define OPERATOR_NEW_BODY_ALIGN(Type, Align, NoThrow)              \
32  void *Ptr = scudoAllocate(size, static_cast<uptr>(Align), Type); \
33  if (!NoThrow && UNLIKELY(!Ptr)) reportOutOfMemory(size);         \
34  return Ptr;
35#define OPERATOR_NEW_BODY(Type, NoThrow) \
36  OPERATOR_NEW_BODY_ALIGN(Type, 0, NoThrow)
37
38CXX_OPERATOR_ATTRIBUTE
39void *operator new(size_t size)
40{ OPERATOR_NEW_BODY(FromNew, /*NoThrow=*/false); }
41CXX_OPERATOR_ATTRIBUTE
42void *operator new[](size_t size)
43{ OPERATOR_NEW_BODY(FromNewArray, /*NoThrow=*/false); }
44CXX_OPERATOR_ATTRIBUTE
45void *operator new(size_t size, std::nothrow_t const&)
46{ OPERATOR_NEW_BODY(FromNew, /*NoThrow=*/true); }
47CXX_OPERATOR_ATTRIBUTE
48void *operator new[](size_t size, std::nothrow_t const&)
49{ OPERATOR_NEW_BODY(FromNewArray, /*NoThrow=*/true); }
50CXX_OPERATOR_ATTRIBUTE
51void *operator new(size_t size, std::align_val_t align)
52{ OPERATOR_NEW_BODY_ALIGN(FromNew, align, /*NoThrow=*/false); }
53CXX_OPERATOR_ATTRIBUTE
54void *operator new[](size_t size, std::align_val_t align)
55{ OPERATOR_NEW_BODY_ALIGN(FromNewArray, align, /*NoThrow=*/false); }
56CXX_OPERATOR_ATTRIBUTE
57void *operator new(size_t size, std::align_val_t align, std::nothrow_t const&)
58{ OPERATOR_NEW_BODY_ALIGN(FromNew, align, /*NoThrow=*/true); }
59CXX_OPERATOR_ATTRIBUTE
60void *operator new[](size_t size, std::align_val_t align, std::nothrow_t const&)
61{ OPERATOR_NEW_BODY_ALIGN(FromNewArray, align, /*NoThrow=*/true); }
62
63#define OPERATOR_DELETE_BODY(Type) \
64  scudoDeallocate(ptr, 0, 0, Type);
65#define OPERATOR_DELETE_BODY_SIZE(Type) \
66  scudoDeallocate(ptr, size, 0, Type);
67#define OPERATOR_DELETE_BODY_ALIGN(Type) \
68  scudoDeallocate(ptr, 0, static_cast<uptr>(align), Type);
69#define OPERATOR_DELETE_BODY_SIZE_ALIGN(Type) \
70  scudoDeallocate(ptr, size, static_cast<uptr>(align), Type);
71
72CXX_OPERATOR_ATTRIBUTE
73void operator delete(void *ptr) NOEXCEPT
74{ OPERATOR_DELETE_BODY(FromNew); }
75CXX_OPERATOR_ATTRIBUTE
76void operator delete[](void *ptr) NOEXCEPT
77{ OPERATOR_DELETE_BODY(FromNewArray); }
78CXX_OPERATOR_ATTRIBUTE
79void operator delete(void *ptr, std::nothrow_t const&)
80{ OPERATOR_DELETE_BODY(FromNew); }
81CXX_OPERATOR_ATTRIBUTE
82void operator delete[](void *ptr, std::nothrow_t const&)
83{ OPERATOR_DELETE_BODY(FromNewArray); }
84CXX_OPERATOR_ATTRIBUTE
85void operator delete(void *ptr, size_t size) NOEXCEPT
86{ OPERATOR_DELETE_BODY_SIZE(FromNew); }
87CXX_OPERATOR_ATTRIBUTE
88void operator delete[](void *ptr, size_t size) NOEXCEPT
89{ OPERATOR_DELETE_BODY_SIZE(FromNewArray); }
90CXX_OPERATOR_ATTRIBUTE
91void operator delete(void *ptr, std::align_val_t align) NOEXCEPT
92{ OPERATOR_DELETE_BODY_ALIGN(FromNew); }
93CXX_OPERATOR_ATTRIBUTE
94void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT
95{ OPERATOR_DELETE_BODY_ALIGN(FromNewArray); }
96CXX_OPERATOR_ATTRIBUTE
97void operator delete(void *ptr, std::align_val_t align, std::nothrow_t const&)
98{ OPERATOR_DELETE_BODY_ALIGN(FromNew); }
99CXX_OPERATOR_ATTRIBUTE
100void operator delete[](void *ptr, std::align_val_t align, std::nothrow_t const&)
101{ OPERATOR_DELETE_BODY_ALIGN(FromNewArray); }
102CXX_OPERATOR_ATTRIBUTE
103void operator delete(void *ptr, size_t size, std::align_val_t align) NOEXCEPT
104{ OPERATOR_DELETE_BODY_SIZE_ALIGN(FromNew); }
105CXX_OPERATOR_ATTRIBUTE
106void operator delete[](void *ptr, size_t size, std::align_val_t align) NOEXCEPT
107{ OPERATOR_DELETE_BODY_SIZE_ALIGN(FromNewArray); }
108