Home | History | Annotate | Line # | Download | only in hwasan
      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))          \
     29       ReportOutOfMemory(size, &stack);       \
     30     return res
     31 #  define OPERATOR_NEW_ALIGN_BODY(nothrow)                               \
     32     GET_MALLOC_STACK_TRACE;                                              \
     33     void *res = hwasan_memalign(static_cast<uptr>(align), size, &stack); \
     34     if (!nothrow && UNLIKELY(!res))                                      \
     35       ReportOutOfMemory(size, &stack);                                   \
     36     return res
     37 
     38 #  define OPERATOR_DELETE_BODY \
     39     GET_MALLOC_STACK_TRACE;    \
     40     if (ptr)                   \
     41     hwasan_free(ptr, &stack)
     42 
     43 #elif defined(__ANDROID__)
     44 
     45 // We don't actually want to intercept operator new and delete on Android, but
     46 // since we previously released a runtime that intercepted these functions,
     47 // removing the interceptors would break ABI. Therefore we simply forward to
     48 // malloc and free.
     49 #  define OPERATOR_NEW_BODY(nothrow) return malloc(size)
     50 #  define OPERATOR_DELETE_BODY free(ptr)
     51 
     52 #endif
     53 
     54 #ifdef OPERATOR_NEW_BODY
     55 
     56 using namespace __hwasan;
     57 
     58 // Fake std::nothrow_t to avoid including <new>.
     59 namespace std {
     60 struct nothrow_t {};
     61 }  // namespace std
     62 
     63 INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new(size_t size) {
     64   OPERATOR_NEW_BODY(false /*nothrow*/);
     65 }
     66 INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new[](
     67     size_t size) {
     68   OPERATOR_NEW_BODY(false /*nothrow*/);
     69 }
     70 INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new(
     71     size_t size, std::nothrow_t const &) {
     72   OPERATOR_NEW_BODY(true /*nothrow*/);
     73 }
     74 INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new[](
     75     size_t size, std::nothrow_t const &) {
     76   OPERATOR_NEW_BODY(true /*nothrow*/);
     77 }
     78 
     79 INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete(
     80     void *ptr) NOEXCEPT {
     81   OPERATOR_DELETE_BODY;
     82 }
     83 INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[](
     84     void *ptr) NOEXCEPT {
     85   OPERATOR_DELETE_BODY;
     86 }
     87 INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete(
     88     void *ptr, std::nothrow_t const &) {
     89   OPERATOR_DELETE_BODY;
     90 }
     91 INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[](
     92     void *ptr, std::nothrow_t const &) {
     93   OPERATOR_DELETE_BODY;
     94 }
     95 INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete(
     96     void *ptr, size_t) NOEXCEPT {
     97   OPERATOR_DELETE_BODY;
     98 }
     99 INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[](
    100     void *ptr, size_t) NOEXCEPT {
    101   OPERATOR_DELETE_BODY;
    102 }
    103 
    104 #endif  // OPERATOR_NEW_BODY
    105 
    106 #ifdef OPERATOR_NEW_ALIGN_BODY
    107 
    108 namespace std {
    109 enum class align_val_t : size_t {};
    110 }  // namespace std
    111 
    112 INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new(
    113     size_t size, std::align_val_t align) {
    114   OPERATOR_NEW_ALIGN_BODY(false /*nothrow*/);
    115 }
    116 INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new[](
    117     size_t size, std::align_val_t align) {
    118   OPERATOR_NEW_ALIGN_BODY(false /*nothrow*/);
    119 }
    120 INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new(
    121     size_t size, std::align_val_t align, std::nothrow_t const &) {
    122   OPERATOR_NEW_ALIGN_BODY(true /*nothrow*/);
    123 }
    124 INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new[](
    125     size_t size, std::align_val_t align, std::nothrow_t const &) {
    126   OPERATOR_NEW_ALIGN_BODY(true /*nothrow*/);
    127 }
    128 
    129 INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete(
    130     void *ptr, std::align_val_t align) NOEXCEPT {
    131   OPERATOR_DELETE_BODY;
    132 }
    133 INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[](
    134     void *ptr, std::align_val_t) NOEXCEPT {
    135   OPERATOR_DELETE_BODY;
    136 }
    137 INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete(
    138     void *ptr, std::align_val_t, std::nothrow_t const &) NOEXCEPT {
    139   OPERATOR_DELETE_BODY;
    140 }
    141 INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[](
    142     void *ptr, std::align_val_t, std::nothrow_t const &) NOEXCEPT {
    143   OPERATOR_DELETE_BODY;
    144 }
    145 INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete(
    146     void *ptr, size_t, std::align_val_t) NOEXCEPT {
    147   OPERATOR_DELETE_BODY;
    148 }
    149 INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[](
    150     void *ptr, size_t, std::align_val_t) NOEXCEPT {
    151   OPERATOR_DELETE_BODY;
    152 }
    153 INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete(
    154     void *ptr, size_t, std::align_val_t, std::nothrow_t const &) NOEXCEPT {
    155   OPERATOR_DELETE_BODY;
    156 }
    157 INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[](
    158     void *ptr, size_t, std::align_val_t, std::nothrow_t const &) NOEXCEPT {
    159   OPERATOR_DELETE_BODY;
    160 }
    161 
    162 #endif  // OPERATOR_NEW_ALIGN_BODY
    163