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