10b57cec5SDimitry Andric //===-- hwasan_new_delete.cpp ---------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file is a part of HWAddressSanitizer.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric // Interceptors for operators new and delete.
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric #include "hwasan.h"
150b57cec5SDimitry Andric #include "interception/interception.h"
160b57cec5SDimitry Andric #include "sanitizer_common/sanitizer_allocator.h"
170b57cec5SDimitry Andric #include "sanitizer_common/sanitizer_allocator_report.h"
180b57cec5SDimitry Andric
19e8d8bef9SDimitry Andric #include <stddef.h>
20e8d8bef9SDimitry Andric #include <stdlib.h>
21e8d8bef9SDimitry Andric
220b57cec5SDimitry Andric #if HWASAN_REPLACE_OPERATORS_NEW_AND_DELETE
230b57cec5SDimitry Andric
24e8d8bef9SDimitry Andric // TODO(alekseys): throw std::bad_alloc instead of dying on OOM.
25e8d8bef9SDimitry Andric # define OPERATOR_NEW_BODY(nothrow) \
26e8d8bef9SDimitry Andric GET_MALLOC_STACK_TRACE; \
27e8d8bef9SDimitry Andric void *res = hwasan_malloc(size, &stack); \
2881ad6265SDimitry Andric if (!nothrow && UNLIKELY(!res)) \
2981ad6265SDimitry Andric ReportOutOfMemory(size, &stack); \
30e8d8bef9SDimitry Andric return res
31fe6060f1SDimitry Andric # define OPERATOR_NEW_ALIGN_BODY(nothrow) \
32fe6060f1SDimitry Andric GET_MALLOC_STACK_TRACE; \
3381ad6265SDimitry Andric void *res = hwasan_memalign(static_cast<uptr>(align), size, &stack); \
34fe6060f1SDimitry Andric if (!nothrow && UNLIKELY(!res)) \
35fe6060f1SDimitry Andric ReportOutOfMemory(size, &stack); \
36fe6060f1SDimitry Andric return res
37e8d8bef9SDimitry Andric
38e8d8bef9SDimitry Andric # define OPERATOR_DELETE_BODY \
39e8d8bef9SDimitry Andric GET_MALLOC_STACK_TRACE; \
4081ad6265SDimitry Andric if (ptr) \
4181ad6265SDimitry Andric hwasan_free(ptr, &stack)
42e8d8bef9SDimitry Andric
43e8d8bef9SDimitry Andric #elif defined(__ANDROID__)
44e8d8bef9SDimitry Andric
45e8d8bef9SDimitry Andric // We don't actually want to intercept operator new and delete on Android, but
46e8d8bef9SDimitry Andric // since we previously released a runtime that intercepted these functions,
47e8d8bef9SDimitry Andric // removing the interceptors would break ABI. Therefore we simply forward to
48e8d8bef9SDimitry Andric // malloc and free.
49e8d8bef9SDimitry Andric # define OPERATOR_NEW_BODY(nothrow) return malloc(size)
50e8d8bef9SDimitry Andric # define OPERATOR_DELETE_BODY free(ptr)
51e8d8bef9SDimitry Andric
52e8d8bef9SDimitry Andric #endif
53e8d8bef9SDimitry Andric
54e8d8bef9SDimitry Andric #ifdef OPERATOR_NEW_BODY
550b57cec5SDimitry Andric
5668d75effSDimitry Andric using namespace __hwasan;
570b57cec5SDimitry Andric
580b57cec5SDimitry Andric // Fake std::nothrow_t to avoid including <new>.
590b57cec5SDimitry Andric namespace std {
600b57cec5SDimitry Andric struct nothrow_t {};
610b57cec5SDimitry Andric } // namespace std
620b57cec5SDimitry Andric
operator new(size_t size)6381ad6265SDimitry Andric INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new(size_t size) {
6481ad6265SDimitry Andric OPERATOR_NEW_BODY(false /*nothrow*/);
6581ad6265SDimitry Andric }
operator new[](size_t size)6681ad6265SDimitry Andric INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new[](
6781ad6265SDimitry Andric size_t size) {
6881ad6265SDimitry Andric OPERATOR_NEW_BODY(false /*nothrow*/);
6981ad6265SDimitry Andric }
operator new(size_t size,std::nothrow_t const &)7081ad6265SDimitry Andric INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new(
7181ad6265SDimitry Andric size_t size, std::nothrow_t const &) {
720b57cec5SDimitry Andric OPERATOR_NEW_BODY(true /*nothrow*/);
730b57cec5SDimitry Andric }
operator new[](size_t size,std::nothrow_t const &)7481ad6265SDimitry Andric INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new[](
7581ad6265SDimitry Andric size_t size, std::nothrow_t const &) {
760b57cec5SDimitry Andric OPERATOR_NEW_BODY(true /*nothrow*/);
770b57cec5SDimitry Andric }
780b57cec5SDimitry Andric
operator delete(void * ptr)7981ad6265SDimitry Andric INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete(
8081ad6265SDimitry Andric void *ptr) NOEXCEPT {
81fe6060f1SDimitry Andric OPERATOR_DELETE_BODY;
82fe6060f1SDimitry Andric }
operator delete[](void * ptr)83fe6060f1SDimitry Andric INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[](
84fe6060f1SDimitry Andric void *ptr) NOEXCEPT {
85fe6060f1SDimitry Andric OPERATOR_DELETE_BODY;
86fe6060f1SDimitry Andric }
operator delete(void * ptr,std::nothrow_t const &)87fe6060f1SDimitry Andric INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete(
88fe6060f1SDimitry Andric void *ptr, std::nothrow_t const &) {
89fe6060f1SDimitry Andric OPERATOR_DELETE_BODY;
90fe6060f1SDimitry Andric }
operator delete[](void * ptr,std::nothrow_t const &)91fe6060f1SDimitry Andric INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[](
92fe6060f1SDimitry Andric void *ptr, std::nothrow_t const &) {
930b57cec5SDimitry Andric OPERATOR_DELETE_BODY;
940b57cec5SDimitry Andric }
operator delete(void * ptr,size_t)95*06c3fb27SDimitry Andric INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete(
96*06c3fb27SDimitry Andric void *ptr, size_t) NOEXCEPT {
97*06c3fb27SDimitry Andric OPERATOR_DELETE_BODY;
98*06c3fb27SDimitry Andric }
operator delete[](void * ptr,size_t)99*06c3fb27SDimitry Andric INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[](
100*06c3fb27SDimitry Andric void *ptr, size_t) NOEXCEPT {
101*06c3fb27SDimitry Andric OPERATOR_DELETE_BODY;
102*06c3fb27SDimitry Andric }
1030b57cec5SDimitry Andric
104e8d8bef9SDimitry Andric #endif // OPERATOR_NEW_BODY
105fe6060f1SDimitry Andric
106fe6060f1SDimitry Andric #ifdef OPERATOR_NEW_ALIGN_BODY
107fe6060f1SDimitry Andric
108fe6060f1SDimitry Andric namespace std {
109fe6060f1SDimitry Andric enum class align_val_t : size_t {};
110fe6060f1SDimitry Andric } // namespace std
111fe6060f1SDimitry Andric
operator new(size_t size,std::align_val_t align)112fe6060f1SDimitry Andric INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new(
113fe6060f1SDimitry Andric size_t size, std::align_val_t align) {
114fe6060f1SDimitry Andric OPERATOR_NEW_ALIGN_BODY(false /*nothrow*/);
115fe6060f1SDimitry Andric }
operator new[](size_t size,std::align_val_t align)116fe6060f1SDimitry Andric INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new[](
117fe6060f1SDimitry Andric size_t size, std::align_val_t align) {
118fe6060f1SDimitry Andric OPERATOR_NEW_ALIGN_BODY(false /*nothrow*/);
119fe6060f1SDimitry Andric }
operator new(size_t size,std::align_val_t align,std::nothrow_t const &)120fe6060f1SDimitry Andric INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new(
121fe6060f1SDimitry Andric size_t size, std::align_val_t align, std::nothrow_t const &) {
122fe6060f1SDimitry Andric OPERATOR_NEW_ALIGN_BODY(true /*nothrow*/);
123fe6060f1SDimitry Andric }
operator new[](size_t size,std::align_val_t align,std::nothrow_t const &)124fe6060f1SDimitry Andric INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new[](
125fe6060f1SDimitry Andric size_t size, std::align_val_t align, std::nothrow_t const &) {
126fe6060f1SDimitry Andric OPERATOR_NEW_ALIGN_BODY(true /*nothrow*/);
127fe6060f1SDimitry Andric }
128fe6060f1SDimitry Andric
operator delete(void * ptr,std::align_val_t align)129fe6060f1SDimitry Andric INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete(
130fe6060f1SDimitry Andric void *ptr, std::align_val_t align) NOEXCEPT {
131fe6060f1SDimitry Andric OPERATOR_DELETE_BODY;
132fe6060f1SDimitry Andric }
operator delete[](void * ptr,std::align_val_t)133fe6060f1SDimitry Andric INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[](
134fe6060f1SDimitry Andric void *ptr, std::align_val_t) NOEXCEPT {
135fe6060f1SDimitry Andric OPERATOR_DELETE_BODY;
136fe6060f1SDimitry Andric }
operator delete(void * ptr,std::align_val_t,std::nothrow_t const &)137fe6060f1SDimitry Andric INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete(
138fe6060f1SDimitry Andric void *ptr, std::align_val_t, std::nothrow_t const &) NOEXCEPT {
139fe6060f1SDimitry Andric OPERATOR_DELETE_BODY;
140fe6060f1SDimitry Andric }
operator delete[](void * ptr,std::align_val_t,std::nothrow_t const &)141fe6060f1SDimitry Andric INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[](
142fe6060f1SDimitry Andric void *ptr, std::align_val_t, std::nothrow_t const &) NOEXCEPT {
143fe6060f1SDimitry Andric OPERATOR_DELETE_BODY;
144fe6060f1SDimitry Andric }
operator delete(void * ptr,size_t,std::align_val_t)145*06c3fb27SDimitry Andric INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete(
146*06c3fb27SDimitry Andric void *ptr, size_t, std::align_val_t) NOEXCEPT {
147*06c3fb27SDimitry Andric OPERATOR_DELETE_BODY;
148*06c3fb27SDimitry Andric }
operator delete[](void * ptr,size_t,std::align_val_t)149*06c3fb27SDimitry Andric INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[](
150*06c3fb27SDimitry Andric void *ptr, size_t, std::align_val_t) NOEXCEPT {
151*06c3fb27SDimitry Andric OPERATOR_DELETE_BODY;
152*06c3fb27SDimitry Andric }
operator delete(void * ptr,size_t,std::align_val_t,std::nothrow_t const &)153*06c3fb27SDimitry Andric INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete(
154*06c3fb27SDimitry Andric void *ptr, size_t, std::align_val_t, std::nothrow_t const &) NOEXCEPT {
155*06c3fb27SDimitry Andric OPERATOR_DELETE_BODY;
156*06c3fb27SDimitry Andric }
operator delete[](void * ptr,size_t,std::align_val_t,std::nothrow_t const &)157*06c3fb27SDimitry Andric INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[](
158*06c3fb27SDimitry Andric void *ptr, size_t, std::align_val_t, std::nothrow_t const &) NOEXCEPT {
159*06c3fb27SDimitry Andric OPERATOR_DELETE_BODY;
160*06c3fb27SDimitry Andric }
161fe6060f1SDimitry Andric
162fe6060f1SDimitry Andric #endif // OPERATOR_NEW_ALIGN_BODY
163