221 lines · cpp
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-exception6//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_DELETE23 24// TODO(alekseys): throw std::bad_alloc instead of dying on OOM.25# define OPERATOR_NEW_BODY \26 GET_MALLOC_STACK_TRACE; \27 void *res = hwasan_malloc(size, &stack); \28 if (UNLIKELY(!res)) \29 ReportOutOfMemory(size, &stack); \30 return res31# define OPERATOR_NEW_BODY_NOTHROW \32 GET_MALLOC_STACK_TRACE; \33 return hwasan_malloc(size, &stack)34# define OPERATOR_NEW_BODY_ARRAY \35 GET_MALLOC_STACK_TRACE; \36 void *res = hwasan_malloc(size, &stack); \37 if (UNLIKELY(!res)) \38 ReportOutOfMemory(size, &stack); \39 return res40# define OPERATOR_NEW_BODY_ARRAY_NOTHROW \41 GET_MALLOC_STACK_TRACE; \42 return hwasan_malloc(size, &stack)43# define OPERATOR_NEW_BODY_ALIGN \44 GET_MALLOC_STACK_TRACE; \45 void *res = hwasan_memalign(static_cast<uptr>(align), size, &stack); \46 if (UNLIKELY(!res)) \47 ReportOutOfMemory(size, &stack); \48 return res49# define OPERATOR_NEW_BODY_ALIGN_NOTHROW \50 GET_MALLOC_STACK_TRACE; \51 return hwasan_memalign(static_cast<uptr>(align), size, &stack)52# define OPERATOR_NEW_BODY_ALIGN_ARRAY \53 GET_MALLOC_STACK_TRACE; \54 void *res = hwasan_memalign(static_cast<uptr>(align), size, &stack); \55 if (UNLIKELY(!res)) \56 ReportOutOfMemory(size, &stack); \57 return res58# define OPERATOR_NEW_BODY_ALIGN_ARRAY_NOTHROW \59 GET_MALLOC_STACK_TRACE; \60 return hwasan_memalign(static_cast<uptr>(align), size, &stack)61 62# define OPERATOR_DELETE_BODY \63 GET_MALLOC_STACK_TRACE; \64 if (ptr) \65 hwasan_free(ptr, &stack)66# define OPERATOR_DELETE_BODY_ARRAY \67 GET_MALLOC_STACK_TRACE; \68 if (ptr) \69 hwasan_free(ptr, &stack)70# define OPERATOR_DELETE_BODY_ALIGN \71 GET_MALLOC_STACK_TRACE; \72 if (ptr) \73 hwasan_free(ptr, &stack)74# define OPERATOR_DELETE_BODY_ALIGN_ARRAY \75 GET_MALLOC_STACK_TRACE; \76 if (ptr) \77 hwasan_free(ptr, &stack)78# define OPERATOR_DELETE_BODY_SIZE \79 GET_MALLOC_STACK_TRACE; \80 if (ptr) \81 hwasan_free(ptr, &stack)82# define OPERATOR_DELETE_BODY_SIZE_ARRAY \83 GET_MALLOC_STACK_TRACE; \84 if (ptr) \85 hwasan_free(ptr, &stack)86# define OPERATOR_DELETE_BODY_SIZE_ALIGN \87 GET_MALLOC_STACK_TRACE; \88 if (ptr) \89 hwasan_free(ptr, &stack)90# define OPERATOR_DELETE_BODY_SIZE_ALIGN_ARRAY \91 GET_MALLOC_STACK_TRACE; \92 if (ptr) \93 hwasan_free(ptr, &stack)94 95#elif defined(__ANDROID__)96 97// We don't actually want to intercept operator new and delete on Android, but98// since we previously released a runtime that intercepted these functions,99// removing the interceptors would break ABI. Therefore we simply forward to100// malloc and free.101# define OPERATOR_NEW_BODY return malloc(size)102# define OPERATOR_NEW_BODY_NOTHROW return malloc(size)103# define OPERATOR_NEW_BODY_ARRAY return malloc(size)104# define OPERATOR_NEW_BODY_ARRAY_NOTHROW return malloc(size)105# define OPERATOR_DELETE_BODY free(ptr)106# define OPERATOR_DELETE_BODY_ARRAY free(ptr)107# define OPERATOR_DELETE_BODY_SIZE free(ptr)108# define OPERATOR_DELETE_BODY_SIZE_ARRAY free(ptr)109 110#endif111 112#ifdef OPERATOR_NEW_BODY113 114using namespace __hwasan;115 116// Fake std::nothrow_t to avoid including <new>.117namespace std {118struct nothrow_t {};119} // namespace std120 121INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new(size_t size) {122 OPERATOR_NEW_BODY;123}124INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new[](125 size_t size) {126 OPERATOR_NEW_BODY_ARRAY;127}128INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new(129 size_t size, std::nothrow_t const &) {130 OPERATOR_NEW_BODY_NOTHROW;131}132INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new[](133 size_t size, std::nothrow_t const &) {134 OPERATOR_NEW_BODY_ARRAY_NOTHROW;135}136 137INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete(138 void *ptr) NOEXCEPT {139 OPERATOR_DELETE_BODY;140}141INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[](142 void *ptr) NOEXCEPT {143 OPERATOR_DELETE_BODY_ARRAY;144}145INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete(146 void *ptr, std::nothrow_t const &) {147 OPERATOR_DELETE_BODY;148}149INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[](150 void *ptr, std::nothrow_t const &) {151 OPERATOR_DELETE_BODY_ARRAY;152}153INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete(154 void *ptr, size_t) NOEXCEPT {155 OPERATOR_DELETE_BODY_SIZE;156}157INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[](158 void *ptr, size_t) NOEXCEPT {159 OPERATOR_DELETE_BODY_SIZE_ARRAY;160}161 162#endif // OPERATOR_NEW_BODY163 164#ifdef OPERATOR_NEW_BODY_ALIGN165 166namespace std {167enum class align_val_t : size_t {};168} // namespace std169 170INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new(171 size_t size, std::align_val_t align) {172 OPERATOR_NEW_BODY_ALIGN;173}174INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new[](175 size_t size, std::align_val_t align) {176 OPERATOR_NEW_BODY_ALIGN_ARRAY;177}178INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new(179 size_t size, std::align_val_t align, std::nothrow_t const &) {180 OPERATOR_NEW_BODY_ALIGN_NOTHROW;181}182INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new[](183 size_t size, std::align_val_t align, std::nothrow_t const &) {184 OPERATOR_NEW_BODY_ALIGN_ARRAY_NOTHROW;185}186 187INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete(188 void *ptr, std::align_val_t align) NOEXCEPT {189 OPERATOR_DELETE_BODY_ALIGN;190}191INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[](192 void *ptr, std::align_val_t) NOEXCEPT {193 OPERATOR_DELETE_BODY_ALIGN_ARRAY;194}195INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete(196 void *ptr, std::align_val_t, std::nothrow_t const &) NOEXCEPT {197 OPERATOR_DELETE_BODY_ALIGN;198}199INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[](200 void *ptr, std::align_val_t, std::nothrow_t const &) NOEXCEPT {201 OPERATOR_DELETE_BODY_ALIGN_ARRAY;202}203INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete(204 void *ptr, size_t, std::align_val_t) NOEXCEPT {205 OPERATOR_DELETE_BODY_SIZE_ALIGN;206}207INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[](208 void *ptr, size_t, std::align_val_t) NOEXCEPT {209 OPERATOR_DELETE_BODY_SIZE_ALIGN_ARRAY;210}211INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete(212 void *ptr, size_t, std::align_val_t, std::nothrow_t const &) NOEXCEPT {213 OPERATOR_DELETE_BODY_SIZE_ALIGN;214}215INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[](216 void *ptr, size_t, std::align_val_t, std::nothrow_t const &) NOEXCEPT {217 OPERATOR_DELETE_BODY_SIZE_ALIGN_ARRAY;218}219 220#endif // OPERATOR_NEW_BODY_ALIGN221