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