Home | History | Annotate | Download | only in asan
      1 //===-- asan_interceptors.cc ----------------------------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file is a part of AddressSanitizer, an address sanity checker.
     11 //
     12 // Interceptors for operators new and delete.
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "asan_allocator.h"
     16 #include "asan_internal.h"
     17 #include "asan_stack.h"
     18 
     19 #include "interception/interception.h"
     20 
     21 #include <stddef.h>
     22 
     23 // C++ operators can't have dllexport attributes on Windows. We export them
     24 // anyway by passing extra -export flags to the linker, which is exactly that
     25 // dllexport would normally do. We need to export them in order to make the
     26 // VS2015 dynamic CRT (MD) work.
     27 #if SANITIZER_WINDOWS
     28 # define CXX_OPERATOR_ATTRIBUTE
     29 # ifdef _WIN64
     30 #  pragma comment(linker, "/export:??2@YAPEAX_K@Z")   // operator new
     31 #  pragma comment(linker, "/export:??3@YAXPEAX@Z")    // operator delete
     32 #  pragma comment(linker, "/export:??3@YAXPEAX_K@Z")  // sized operator delete
     33 #  pragma comment(linker, "/export:??_U@YAPEAX_K@Z")  // operator new[]
     34 #  pragma comment(linker, "/export:??_V@YAXPEAX@Z")   // operator delete[]
     35 # else
     36 #  pragma comment(linker, "/export:??2@YAPAXI@Z")   // operator new
     37 #  pragma comment(linker, "/export:??3@YAXPAX@Z")   // operator delete
     38 #  pragma comment(linker, "/export:??3@YAXPAXI@Z")  // sized operator delete
     39 #  pragma comment(linker, "/export:??_U@YAPAXI@Z")  // operator new[]
     40 #  pragma comment(linker, "/export:??_V@YAXPAX@Z")  // operator delete[]
     41 # endif
     42 #else
     43 # define CXX_OPERATOR_ATTRIBUTE INTERCEPTOR_ATTRIBUTE
     44 #endif
     45 
     46 using namespace __asan;  // NOLINT
     47 
     48 // This code has issues on OSX.
     49 // See https://github.com/google/sanitizers/issues/131.
     50 
     51 // Fake std::nothrow_t to avoid including <new>.
     52 namespace std {
     53 struct nothrow_t {};
     54 }  // namespace std
     55 
     56 #define OPERATOR_NEW_BODY(type) \
     57   GET_STACK_TRACE_MALLOC;\
     58   return asan_memalign(0, size, &stack, type);
     59 
     60 // On OS X it's not enough to just provide our own 'operator new' and
     61 // 'operator delete' implementations, because they're going to be in the
     62 // runtime dylib, and the main executable will depend on both the runtime
     63 // dylib and libstdc++, each of those'll have its implementation of new and
     64 // delete.
     65 // To make sure that C++ allocation/deallocation operators are overridden on
     66 // OS X we need to intercept them using their mangled names.
     67 #if !SANITIZER_MAC
     68 // FreeBSD prior v9.2 have wrong definition of 'size_t'.
     69 // http://svnweb.freebsd.org/base?view=revision&revision=232261
     70 #if SANITIZER_FREEBSD && SANITIZER_WORDSIZE == 32
     71 #include <sys/param.h>
     72 #if __FreeBSD_version <= 902001  // v9.2
     73 #define size_t unsigned
     74 #endif  // __FreeBSD_version
     75 #endif  // SANITIZER_FREEBSD && SANITIZER_WORDSIZE == 32
     76 
     77 CXX_OPERATOR_ATTRIBUTE
     78 void *operator new(size_t size) { OPERATOR_NEW_BODY(FROM_NEW); }
     79 CXX_OPERATOR_ATTRIBUTE
     80 void *operator new[](size_t size) { OPERATOR_NEW_BODY(FROM_NEW_BR); }
     81 CXX_OPERATOR_ATTRIBUTE
     82 void *operator new(size_t size, std::nothrow_t const&)
     83 { OPERATOR_NEW_BODY(FROM_NEW); }
     84 CXX_OPERATOR_ATTRIBUTE
     85 void *operator new[](size_t size, std::nothrow_t const&)
     86 { OPERATOR_NEW_BODY(FROM_NEW_BR); }
     87 
     88 #else  // SANITIZER_MAC
     89 INTERCEPTOR(void *, _Znwm, size_t size) {
     90   OPERATOR_NEW_BODY(FROM_NEW);
     91 }
     92 INTERCEPTOR(void *, _Znam, size_t size) {
     93   OPERATOR_NEW_BODY(FROM_NEW_BR);
     94 }
     95 INTERCEPTOR(void *, _ZnwmRKSt9nothrow_t, size_t size, std::nothrow_t const&) {
     96   OPERATOR_NEW_BODY(FROM_NEW);
     97 }
     98 INTERCEPTOR(void *, _ZnamRKSt9nothrow_t, size_t size, std::nothrow_t const&) {
     99   OPERATOR_NEW_BODY(FROM_NEW_BR);
    100 }
    101 #endif
    102 
    103 #define OPERATOR_DELETE_BODY(type) \
    104   GET_STACK_TRACE_FREE;\
    105   asan_free(ptr, &stack, type);
    106 
    107 #if !SANITIZER_MAC
    108 CXX_OPERATOR_ATTRIBUTE
    109 void operator delete(void *ptr) NOEXCEPT {
    110   OPERATOR_DELETE_BODY(FROM_NEW);
    111 }
    112 CXX_OPERATOR_ATTRIBUTE
    113 void operator delete[](void *ptr) NOEXCEPT {
    114   OPERATOR_DELETE_BODY(FROM_NEW_BR);
    115 }
    116 CXX_OPERATOR_ATTRIBUTE
    117 void operator delete(void *ptr, std::nothrow_t const&) {
    118   OPERATOR_DELETE_BODY(FROM_NEW);
    119 }
    120 CXX_OPERATOR_ATTRIBUTE
    121 void operator delete[](void *ptr, std::nothrow_t const&) {
    122   OPERATOR_DELETE_BODY(FROM_NEW_BR);
    123 }
    124 CXX_OPERATOR_ATTRIBUTE
    125 void operator delete(void *ptr, size_t size) NOEXCEPT {
    126   GET_STACK_TRACE_FREE;
    127   asan_sized_free(ptr, size, &stack, FROM_NEW);
    128 }
    129 CXX_OPERATOR_ATTRIBUTE
    130 void operator delete[](void *ptr, size_t size) NOEXCEPT {
    131   GET_STACK_TRACE_FREE;
    132   asan_sized_free(ptr, size, &stack, FROM_NEW_BR);
    133 }
    134 
    135 #else  // SANITIZER_MAC
    136 INTERCEPTOR(void, _ZdlPv, void *ptr) {
    137   OPERATOR_DELETE_BODY(FROM_NEW);
    138 }
    139 INTERCEPTOR(void, _ZdaPv, void *ptr) {
    140   OPERATOR_DELETE_BODY(FROM_NEW_BR);
    141 }
    142 INTERCEPTOR(void, _ZdlPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&) {
    143   OPERATOR_DELETE_BODY(FROM_NEW);
    144 }
    145 INTERCEPTOR(void, _ZdaPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&) {
    146   OPERATOR_DELETE_BODY(FROM_NEW_BR);
    147 }
    148 #endif
    149