xref: /openbsd-src/gnu/llvm/compiler-rt/lib/dfsan/dfsan_new_delete.cpp (revision d89ec533011f513df1010f142a111086a0785f09)
1*d89ec533Spatrick //===-- dfsan_new_delete.cpp ----------------------------------------------===//
2*d89ec533Spatrick //
3*d89ec533Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*d89ec533Spatrick // See https://llvm.org/LICENSE.txt for license information.
5*d89ec533Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*d89ec533Spatrick //
7*d89ec533Spatrick //===----------------------------------------------------------------------===//
8*d89ec533Spatrick //
9*d89ec533Spatrick // This file is a part of DataflowSanitizer.
10*d89ec533Spatrick //
11*d89ec533Spatrick // Interceptors for operators new and delete.
12*d89ec533Spatrick //===----------------------------------------------------------------------===//
13*d89ec533Spatrick 
14*d89ec533Spatrick #include <stddef.h>
15*d89ec533Spatrick 
16*d89ec533Spatrick #include "dfsan.h"
17*d89ec533Spatrick #include "interception/interception.h"
18*d89ec533Spatrick #include "sanitizer_common/sanitizer_allocator.h"
19*d89ec533Spatrick #include "sanitizer_common/sanitizer_allocator_report.h"
20*d89ec533Spatrick 
21*d89ec533Spatrick using namespace __dfsan;
22*d89ec533Spatrick 
23*d89ec533Spatrick // Fake std::nothrow_t and std::align_val_t to avoid including <new>.
24*d89ec533Spatrick namespace std {
25*d89ec533Spatrick struct nothrow_t {};
26*d89ec533Spatrick enum class align_val_t : size_t {};
27*d89ec533Spatrick }  // namespace std
28*d89ec533Spatrick 
29*d89ec533Spatrick // TODO(alekseys): throw std::bad_alloc instead of dying on OOM.
30*d89ec533Spatrick #define OPERATOR_NEW_BODY(nothrow)   \
31*d89ec533Spatrick   void *res = dfsan_malloc(size);    \
32*d89ec533Spatrick   if (!nothrow && UNLIKELY(!res)) {  \
33*d89ec533Spatrick     BufferedStackTrace stack;        \
34*d89ec533Spatrick     ReportOutOfMemory(size, &stack); \
35*d89ec533Spatrick   }                                  \
36*d89ec533Spatrick   return res
37*d89ec533Spatrick #define OPERATOR_NEW_BODY_ALIGN(nothrow)         \
38*d89ec533Spatrick   void *res = dfsan_memalign((uptr)align, size); \
39*d89ec533Spatrick   if (!nothrow && UNLIKELY(!res)) {              \
40*d89ec533Spatrick     BufferedStackTrace stack;                    \
41*d89ec533Spatrick     ReportOutOfMemory(size, &stack);             \
42*d89ec533Spatrick   }                                              \
43*d89ec533Spatrick   return res;
44*d89ec533Spatrick 
45*d89ec533Spatrick INTERCEPTOR_ATTRIBUTE
operator new(size_t size)46*d89ec533Spatrick void *operator new(size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }
47*d89ec533Spatrick INTERCEPTOR_ATTRIBUTE
operator new[](size_t size)48*d89ec533Spatrick void *operator new[](size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }
49*d89ec533Spatrick INTERCEPTOR_ATTRIBUTE
operator new(size_t size,std::nothrow_t const &)50*d89ec533Spatrick void *operator new(size_t size, std::nothrow_t const &) {
51*d89ec533Spatrick   OPERATOR_NEW_BODY(true /*nothrow*/);
52*d89ec533Spatrick }
53*d89ec533Spatrick INTERCEPTOR_ATTRIBUTE
operator new[](size_t size,std::nothrow_t const &)54*d89ec533Spatrick void *operator new[](size_t size, std::nothrow_t const &) {
55*d89ec533Spatrick   OPERATOR_NEW_BODY(true /*nothrow*/);
56*d89ec533Spatrick }
57*d89ec533Spatrick INTERCEPTOR_ATTRIBUTE
operator new(size_t size,std::align_val_t align)58*d89ec533Spatrick void *operator new(size_t size, std::align_val_t align) {
59*d89ec533Spatrick   OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/);
60*d89ec533Spatrick }
61*d89ec533Spatrick INTERCEPTOR_ATTRIBUTE
operator new[](size_t size,std::align_val_t align)62*d89ec533Spatrick void *operator new[](size_t size, std::align_val_t align) {
63*d89ec533Spatrick   OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/);
64*d89ec533Spatrick }
65*d89ec533Spatrick INTERCEPTOR_ATTRIBUTE
operator new(size_t size,std::align_val_t align,std::nothrow_t const &)66*d89ec533Spatrick void *operator new(size_t size, std::align_val_t align,
67*d89ec533Spatrick                    std::nothrow_t const &) {
68*d89ec533Spatrick   OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/);
69*d89ec533Spatrick }
70*d89ec533Spatrick INTERCEPTOR_ATTRIBUTE
operator new[](size_t size,std::align_val_t align,std::nothrow_t const &)71*d89ec533Spatrick void *operator new[](size_t size, std::align_val_t align,
72*d89ec533Spatrick                      std::nothrow_t const &) {
73*d89ec533Spatrick   OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/);
74*d89ec533Spatrick }
75*d89ec533Spatrick 
76*d89ec533Spatrick #define OPERATOR_DELETE_BODY \
77*d89ec533Spatrick   if (ptr)                   \
78*d89ec533Spatrick   dfsan_deallocate(ptr)
79*d89ec533Spatrick 
80*d89ec533Spatrick INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr)81*d89ec533Spatrick void operator delete(void *ptr)NOEXCEPT { OPERATOR_DELETE_BODY; }
82*d89ec533Spatrick INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr)83*d89ec533Spatrick void operator delete[](void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; }
84*d89ec533Spatrick INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,std::nothrow_t const &)85*d89ec533Spatrick void operator delete(void *ptr, std::nothrow_t const &) {
86*d89ec533Spatrick   OPERATOR_DELETE_BODY;
87*d89ec533Spatrick }
88*d89ec533Spatrick INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,std::nothrow_t const &)89*d89ec533Spatrick void operator delete[](void *ptr, std::nothrow_t const &) {
90*d89ec533Spatrick   OPERATOR_DELETE_BODY;
91*d89ec533Spatrick }
92*d89ec533Spatrick INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,size_t size)93*d89ec533Spatrick void operator delete(void *ptr, size_t size)NOEXCEPT { OPERATOR_DELETE_BODY; }
94*d89ec533Spatrick INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,size_t size)95*d89ec533Spatrick void operator delete[](void *ptr, size_t size) NOEXCEPT {
96*d89ec533Spatrick   OPERATOR_DELETE_BODY;
97*d89ec533Spatrick }
98*d89ec533Spatrick INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,std::align_val_t align)99*d89ec533Spatrick void operator delete(void *ptr, std::align_val_t align)NOEXCEPT {
100*d89ec533Spatrick   OPERATOR_DELETE_BODY;
101*d89ec533Spatrick }
102*d89ec533Spatrick INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,std::align_val_t align)103*d89ec533Spatrick void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT {
104*d89ec533Spatrick   OPERATOR_DELETE_BODY;
105*d89ec533Spatrick }
106*d89ec533Spatrick INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,std::align_val_t align,std::nothrow_t const &)107*d89ec533Spatrick void operator delete(void *ptr, std::align_val_t align,
108*d89ec533Spatrick                      std::nothrow_t const &) {
109*d89ec533Spatrick   OPERATOR_DELETE_BODY;
110*d89ec533Spatrick }
111*d89ec533Spatrick INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,std::align_val_t align,std::nothrow_t const &)112*d89ec533Spatrick void operator delete[](void *ptr, std::align_val_t align,
113*d89ec533Spatrick                        std::nothrow_t const &) {
114*d89ec533Spatrick   OPERATOR_DELETE_BODY;
115*d89ec533Spatrick }
116*d89ec533Spatrick INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,size_t size,std::align_val_t align)117*d89ec533Spatrick void operator delete(void *ptr, size_t size, std::align_val_t align)NOEXCEPT {
118*d89ec533Spatrick   OPERATOR_DELETE_BODY;
119*d89ec533Spatrick }
120*d89ec533Spatrick INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,size_t size,std::align_val_t align)121*d89ec533Spatrick void operator delete[](void *ptr, size_t size,
122*d89ec533Spatrick                        std::align_val_t align) NOEXCEPT {
123*d89ec533Spatrick   OPERATOR_DELETE_BODY;
124*d89ec533Spatrick }
125