13cab2bb3Spatrick //===-- hwasan_new_delete.cpp ---------------------------------------------===//
23cab2bb3Spatrick //
33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information.
53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63cab2bb3Spatrick //
73cab2bb3Spatrick //===----------------------------------------------------------------------===//
83cab2bb3Spatrick //
93cab2bb3Spatrick // This file is a part of HWAddressSanitizer.
103cab2bb3Spatrick //
113cab2bb3Spatrick // Interceptors for operators new and delete.
123cab2bb3Spatrick //===----------------------------------------------------------------------===//
133cab2bb3Spatrick
143cab2bb3Spatrick #include "hwasan.h"
153cab2bb3Spatrick #include "interception/interception.h"
163cab2bb3Spatrick #include "sanitizer_common/sanitizer_allocator.h"
173cab2bb3Spatrick #include "sanitizer_common/sanitizer_allocator_report.h"
183cab2bb3Spatrick
19d89ec533Spatrick #include <stddef.h>
20d89ec533Spatrick #include <stdlib.h>
21d89ec533Spatrick
223cab2bb3Spatrick #if HWASAN_REPLACE_OPERATORS_NEW_AND_DELETE
233cab2bb3Spatrick
24d89ec533Spatrick // TODO(alekseys): throw std::bad_alloc instead of dying on OOM.
25d89ec533Spatrick # define OPERATOR_NEW_BODY(nothrow) \
26d89ec533Spatrick GET_MALLOC_STACK_TRACE; \
27d89ec533Spatrick void *res = hwasan_malloc(size, &stack); \
28*810390e3Srobert if (!nothrow && UNLIKELY(!res)) \
29*810390e3Srobert ReportOutOfMemory(size, &stack); \
30d89ec533Spatrick return res
31d89ec533Spatrick # define OPERATOR_NEW_ALIGN_BODY(nothrow) \
32d89ec533Spatrick GET_MALLOC_STACK_TRACE; \
33*810390e3Srobert void *res = hwasan_memalign(static_cast<uptr>(align), size, &stack); \
34d89ec533Spatrick if (!nothrow && UNLIKELY(!res)) \
35d89ec533Spatrick ReportOutOfMemory(size, &stack); \
36d89ec533Spatrick return res
37d89ec533Spatrick
38d89ec533Spatrick # define OPERATOR_DELETE_BODY \
39d89ec533Spatrick GET_MALLOC_STACK_TRACE; \
40*810390e3Srobert if (ptr) \
41*810390e3Srobert hwasan_free(ptr, &stack)
42d89ec533Spatrick
43d89ec533Spatrick #elif defined(__ANDROID__)
44d89ec533Spatrick
45d89ec533Spatrick // We don't actually want to intercept operator new and delete on Android, but
46d89ec533Spatrick // since we previously released a runtime that intercepted these functions,
47d89ec533Spatrick // removing the interceptors would break ABI. Therefore we simply forward to
48d89ec533Spatrick // malloc and free.
49d89ec533Spatrick # define OPERATOR_NEW_BODY(nothrow) return malloc(size)
50d89ec533Spatrick # define OPERATOR_DELETE_BODY free(ptr)
51d89ec533Spatrick
52d89ec533Spatrick #endif
53d89ec533Spatrick
54d89ec533Spatrick #ifdef OPERATOR_NEW_BODY
553cab2bb3Spatrick
563cab2bb3Spatrick using namespace __hwasan;
573cab2bb3Spatrick
583cab2bb3Spatrick // Fake std::nothrow_t to avoid including <new>.
593cab2bb3Spatrick namespace std {
603cab2bb3Spatrick struct nothrow_t {};
613cab2bb3Spatrick } // namespace std
623cab2bb3Spatrick
operator new(size_t size)63*810390e3Srobert INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new(size_t size) {
64*810390e3Srobert OPERATOR_NEW_BODY(false /*nothrow*/);
65*810390e3Srobert }
operator new[](size_t size)66*810390e3Srobert INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new[](
67*810390e3Srobert size_t size) {
68*810390e3Srobert OPERATOR_NEW_BODY(false /*nothrow*/);
69*810390e3Srobert }
operator new(size_t size,std::nothrow_t const &)70*810390e3Srobert INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new(
71*810390e3Srobert size_t size, std::nothrow_t const &) {
723cab2bb3Spatrick OPERATOR_NEW_BODY(true /*nothrow*/);
733cab2bb3Spatrick }
operator new[](size_t size,std::nothrow_t const &)74*810390e3Srobert INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new[](
75*810390e3Srobert size_t size, std::nothrow_t const &) {
763cab2bb3Spatrick OPERATOR_NEW_BODY(true /*nothrow*/);
773cab2bb3Spatrick }
783cab2bb3Spatrick
operator delete(void * ptr)79*810390e3Srobert INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete(
80*810390e3Srobert void *ptr) NOEXCEPT {
81d89ec533Spatrick OPERATOR_DELETE_BODY;
82d89ec533Spatrick }
operator delete[](void * ptr)83d89ec533Spatrick INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[](
84d89ec533Spatrick void *ptr) NOEXCEPT {
85d89ec533Spatrick OPERATOR_DELETE_BODY;
86d89ec533Spatrick }
operator delete(void * ptr,std::nothrow_t const &)87d89ec533Spatrick INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete(
88d89ec533Spatrick void *ptr, std::nothrow_t const &) {
89d89ec533Spatrick OPERATOR_DELETE_BODY;
90d89ec533Spatrick }
operator delete[](void * ptr,std::nothrow_t const &)91d89ec533Spatrick INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[](
92d89ec533Spatrick void *ptr, std::nothrow_t const &) {
933cab2bb3Spatrick OPERATOR_DELETE_BODY;
943cab2bb3Spatrick }
953cab2bb3Spatrick
96d89ec533Spatrick #endif // OPERATOR_NEW_BODY
97d89ec533Spatrick
98d89ec533Spatrick #ifdef OPERATOR_NEW_ALIGN_BODY
99d89ec533Spatrick
100d89ec533Spatrick namespace std {
101d89ec533Spatrick enum class align_val_t : size_t {};
102d89ec533Spatrick } // namespace std
103d89ec533Spatrick
operator new(size_t size,std::align_val_t align)104d89ec533Spatrick INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new(
105d89ec533Spatrick size_t size, std::align_val_t align) {
106d89ec533Spatrick OPERATOR_NEW_ALIGN_BODY(false /*nothrow*/);
107d89ec533Spatrick }
operator new[](size_t size,std::align_val_t align)108d89ec533Spatrick INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new[](
109d89ec533Spatrick size_t size, std::align_val_t align) {
110d89ec533Spatrick OPERATOR_NEW_ALIGN_BODY(false /*nothrow*/);
111d89ec533Spatrick }
operator new(size_t size,std::align_val_t align,std::nothrow_t const &)112d89ec533Spatrick INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new(
113d89ec533Spatrick size_t size, std::align_val_t align, std::nothrow_t const &) {
114d89ec533Spatrick OPERATOR_NEW_ALIGN_BODY(true /*nothrow*/);
115d89ec533Spatrick }
operator new[](size_t size,std::align_val_t align,std::nothrow_t const &)116d89ec533Spatrick INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new[](
117d89ec533Spatrick size_t size, std::align_val_t align, std::nothrow_t const &) {
118d89ec533Spatrick OPERATOR_NEW_ALIGN_BODY(true /*nothrow*/);
119d89ec533Spatrick }
120d89ec533Spatrick
operator delete(void * ptr,std::align_val_t align)121d89ec533Spatrick INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete(
122d89ec533Spatrick void *ptr, std::align_val_t align) NOEXCEPT {
123d89ec533Spatrick OPERATOR_DELETE_BODY;
124d89ec533Spatrick }
operator delete[](void * ptr,std::align_val_t)125d89ec533Spatrick INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[](
126d89ec533Spatrick void *ptr, std::align_val_t) NOEXCEPT {
127d89ec533Spatrick OPERATOR_DELETE_BODY;
128d89ec533Spatrick }
operator delete(void * ptr,std::align_val_t,std::nothrow_t const &)129d89ec533Spatrick INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete(
130d89ec533Spatrick void *ptr, std::align_val_t, std::nothrow_t const &) NOEXCEPT {
131d89ec533Spatrick OPERATOR_DELETE_BODY;
132d89ec533Spatrick }
operator delete[](void * ptr,std::align_val_t,std::nothrow_t const &)133d89ec533Spatrick INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[](
134d89ec533Spatrick void *ptr, std::align_val_t, std::nothrow_t const &) NOEXCEPT {
135d89ec533Spatrick OPERATOR_DELETE_BODY;
136d89ec533Spatrick }
137d89ec533Spatrick
138d89ec533Spatrick #endif // OPERATOR_NEW_ALIGN_BODY
139