1 //===-- hwasan_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 HWAddressSanitizer.
10 //
11 // Interceptors for operators new and delete.
12 //===----------------------------------------------------------------------===//
13 
14 #include "hwasan.h"
15 #include "interception/interception.h"
16 #include "sanitizer_common/sanitizer_allocator.h"
17 #include "sanitizer_common/sanitizer_allocator_report.h"
18 
19 #include <stddef.h>
20 #include <stdlib.h>
21 
22 #if HWASAN_REPLACE_OPERATORS_NEW_AND_DELETE
23 
24 // TODO(alekseys): throw std::bad_alloc instead of dying on OOM.
25 #define OPERATOR_NEW_BODY(nothrow) \
26   GET_MALLOC_STACK_TRACE; \
27   void *res = hwasan_malloc(size, &stack);\
28   if (!nothrow && UNLIKELY(!res)) ReportOutOfMemory(size, &stack);\
29   return res
30 #define OPERATOR_NEW_ALIGN_BODY(nothrow)                                    \
31   GET_MALLOC_STACK_TRACE;                                                   \
32   void *res = hwasan_aligned_alloc(static_cast<uptr>(align), size, &stack); \
33   if (!nothrow && UNLIKELY(!res))                                           \
34     ReportOutOfMemory(size, &stack);                                        \
35   return res
36 
37 #define OPERATOR_DELETE_BODY \
38   GET_MALLOC_STACK_TRACE; \
39   if (ptr) hwasan_free(ptr, &stack)
40 
41 #elif defined(__ANDROID__)
42 
43 // We don't actually want to intercept operator new and delete on Android, but
44 // since we previously released a runtime that intercepted these functions,
45 // removing the interceptors would break ABI. Therefore we simply forward to
46 // malloc and free.
47 #define OPERATOR_NEW_BODY(nothrow) return malloc(size)
48 #define OPERATOR_DELETE_BODY free(ptr)
49 
50 #endif
51 
52 #ifdef OPERATOR_NEW_BODY
53 
54 using namespace __hwasan;
55 
56 // Fake std::nothrow_t to avoid including <new>.
57 namespace std {
58   struct nothrow_t {};
59 }  // namespace std
60 
61 
62 
63 INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
64 void *operator new(size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }
65 INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
66 void *operator new[](size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }
67 INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
68 void *operator new(size_t size, std::nothrow_t const&) {
69   OPERATOR_NEW_BODY(true /*nothrow*/);
70 }
71 INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
72 void *operator new[](size_t size, std::nothrow_t const&) {
73   OPERATOR_NEW_BODY(true /*nothrow*/);
74 }
75 
76 INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete(void *ptr)
77     NOEXCEPT {
78   OPERATOR_DELETE_BODY;
79 }
80 INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[](
81     void *ptr) NOEXCEPT {
82   OPERATOR_DELETE_BODY;
83 }
84 INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete(
85     void *ptr, std::nothrow_t const &) {
86   OPERATOR_DELETE_BODY;
87 }
88 INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[](
89     void *ptr, std::nothrow_t const &) {
90   OPERATOR_DELETE_BODY;
91 }
92 
93 #endif  // OPERATOR_NEW_BODY
94 
95 #ifdef OPERATOR_NEW_ALIGN_BODY
96 
97 namespace std {
98 enum class align_val_t : size_t {};
99 }  // namespace std
100 
101 INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new(
102     size_t size, std::align_val_t align) {
103   OPERATOR_NEW_ALIGN_BODY(false /*nothrow*/);
104 }
105 INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new[](
106     size_t size, std::align_val_t align) {
107   OPERATOR_NEW_ALIGN_BODY(false /*nothrow*/);
108 }
109 INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new(
110     size_t size, std::align_val_t align, std::nothrow_t const &) {
111   OPERATOR_NEW_ALIGN_BODY(true /*nothrow*/);
112 }
113 INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new[](
114     size_t size, std::align_val_t align, std::nothrow_t const &) {
115   OPERATOR_NEW_ALIGN_BODY(true /*nothrow*/);
116 }
117 
118 INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete(
119     void *ptr, std::align_val_t align) NOEXCEPT {
120   OPERATOR_DELETE_BODY;
121 }
122 INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[](
123     void *ptr, std::align_val_t) NOEXCEPT {
124   OPERATOR_DELETE_BODY;
125 }
126 INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete(
127     void *ptr, std::align_val_t, std::nothrow_t const &) NOEXCEPT {
128   OPERATOR_DELETE_BODY;
129 }
130 INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[](
131     void *ptr, std::align_val_t, std::nothrow_t const &) NOEXCEPT {
132   OPERATOR_DELETE_BODY;
133 }
134 
135 #endif  // OPERATOR_NEW_ALIGN_BODY
136