1217222abSNico Weber //===-- asan_interceptors.cpp ---------------------------------------------===//
2217222abSNico Weber //
3217222abSNico Weber // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4217222abSNico Weber // See https://llvm.org/LICENSE.txt for license information.
5217222abSNico Weber // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6217222abSNico Weber //
7217222abSNico Weber //===----------------------------------------------------------------------===//
8217222abSNico Weber //
9217222abSNico Weber // This file is a part of AddressSanitizer, an address sanity checker.
10217222abSNico Weber //
11217222abSNico Weber // Interceptors for operators new and delete.
12217222abSNico Weber //===----------------------------------------------------------------------===//
13217222abSNico Weber
14b8919fb0SVitaly Buka #include <stddef.h>
15b8919fb0SVitaly Buka
16217222abSNico Weber #include "asan_allocator.h"
17217222abSNico Weber #include "asan_internal.h"
18217222abSNico Weber #include "asan_report.h"
19217222abSNico Weber #include "asan_stack.h"
20217222abSNico Weber #include "interception/interception.h"
21217222abSNico Weber
22217222abSNico Weber // C++ operators can't have dllexport attributes on Windows. We export them
23217222abSNico Weber // anyway by passing extra -export flags to the linker, which is exactly that
24217222abSNico Weber // dllexport would normally do. We need to export them in order to make the
25217222abSNico Weber // VS2015 dynamic CRT (MD) work.
26217222abSNico Weber #if SANITIZER_WINDOWS && defined(_MSC_VER)
27217222abSNico Weber #define CXX_OPERATOR_ATTRIBUTE
28217222abSNico Weber #define COMMENT_EXPORT(sym) __pragma(comment(linker, "/export:" sym))
29217222abSNico Weber #ifdef _WIN64
30217222abSNico Weber COMMENT_EXPORT("??2@YAPEAX_K@Z") // operator new
31217222abSNico Weber COMMENT_EXPORT("??2@YAPEAX_KAEBUnothrow_t@std@@@Z") // operator new nothrow
32217222abSNico Weber COMMENT_EXPORT("??3@YAXPEAX@Z") // operator delete
33217222abSNico Weber COMMENT_EXPORT("??3@YAXPEAX_K@Z") // sized operator delete
34217222abSNico Weber COMMENT_EXPORT("??_U@YAPEAX_K@Z") // operator new[]
35217222abSNico Weber COMMENT_EXPORT("??_V@YAXPEAX@Z") // operator delete[]
36217222abSNico Weber #else
37217222abSNico Weber COMMENT_EXPORT("??2@YAPAXI@Z") // operator new
38217222abSNico Weber COMMENT_EXPORT("??2@YAPAXIABUnothrow_t@std@@@Z") // operator new nothrow
39217222abSNico Weber COMMENT_EXPORT("??3@YAXPAX@Z") // operator delete
40217222abSNico Weber COMMENT_EXPORT("??3@YAXPAXI@Z") // sized operator delete
41217222abSNico Weber COMMENT_EXPORT("??_U@YAPAXI@Z") // operator new[]
42217222abSNico Weber COMMENT_EXPORT("??_V@YAXPAX@Z") // operator delete[]
43217222abSNico Weber #endif
44217222abSNico Weber #undef COMMENT_EXPORT
45217222abSNico Weber #else
467df30e77SMitch Phillips #define CXX_OPERATOR_ATTRIBUTE INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
47217222abSNico Weber #endif
48217222abSNico Weber
49c0fa6322SVitaly Buka using namespace __asan;
50217222abSNico Weber
51217222abSNico Weber // This code has issues on OSX.
52217222abSNico Weber // See https://github.com/google/sanitizers/issues/131.
53217222abSNico Weber
54217222abSNico Weber // Fake std::nothrow_t and std::align_val_t to avoid including <new>.
55217222abSNico Weber namespace std {
56217222abSNico Weber struct nothrow_t {};
57217222abSNico Weber enum class align_val_t: size_t {};
58217222abSNico Weber } // namespace std
59217222abSNico Weber
60217222abSNico Weber // TODO(alekseyshl): throw std::bad_alloc instead of dying on OOM.
61217222abSNico Weber // For local pool allocation, align to SHADOW_GRANULARITY to match asan
62217222abSNico Weber // allocator behavior.
63217222abSNico Weber #define OPERATOR_NEW_BODY(type, nothrow) \
64217222abSNico Weber GET_STACK_TRACE_MALLOC; \
65217222abSNico Weber void *res = asan_memalign(0, size, &stack, type); \
66217222abSNico Weber if (!nothrow && UNLIKELY(!res)) \
67217222abSNico Weber ReportOutOfMemory(size, &stack); \
68217222abSNico Weber return res;
69217222abSNico Weber #define OPERATOR_NEW_BODY_ALIGN(type, nothrow) \
70217222abSNico Weber GET_STACK_TRACE_MALLOC; \
71217222abSNico Weber void *res = asan_memalign((uptr)align, size, &stack, type); \
72217222abSNico Weber if (!nothrow && UNLIKELY(!res)) \
73217222abSNico Weber ReportOutOfMemory(size, &stack); \
74217222abSNico Weber return res;
75217222abSNico Weber
76217222abSNico Weber // On OS X it's not enough to just provide our own 'operator new' and
77217222abSNico Weber // 'operator delete' implementations, because they're going to be in the
78217222abSNico Weber // runtime dylib, and the main executable will depend on both the runtime
79217222abSNico Weber // dylib and libstdc++, each of those'll have its implementation of new and
80217222abSNico Weber // delete.
81217222abSNico Weber // To make sure that C++ allocation/deallocation operators are overridden on
82217222abSNico Weber // OS X we need to intercept them using their mangled names.
83*8246b2e1SMariusz Borsa #if !SANITIZER_APPLE
84217222abSNico Weber CXX_OPERATOR_ATTRIBUTE
operator new(size_t size)85217222abSNico Weber void *operator new(size_t size)
86217222abSNico Weber { OPERATOR_NEW_BODY(FROM_NEW, false /*nothrow*/); }
87217222abSNico Weber CXX_OPERATOR_ATTRIBUTE
operator new[](size_t size)88217222abSNico Weber void *operator new[](size_t size)
89217222abSNico Weber { OPERATOR_NEW_BODY(FROM_NEW_BR, false /*nothrow*/); }
90217222abSNico Weber CXX_OPERATOR_ATTRIBUTE
operator new(size_t size,std::nothrow_t const &)91217222abSNico Weber void *operator new(size_t size, std::nothrow_t const&)
92217222abSNico Weber { OPERATOR_NEW_BODY(FROM_NEW, true /*nothrow*/); }
93217222abSNico Weber CXX_OPERATOR_ATTRIBUTE
operator new[](size_t size,std::nothrow_t const &)94217222abSNico Weber void *operator new[](size_t size, std::nothrow_t const&)
95217222abSNico Weber { OPERATOR_NEW_BODY(FROM_NEW_BR, true /*nothrow*/); }
96217222abSNico Weber CXX_OPERATOR_ATTRIBUTE
operator new(size_t size,std::align_val_t align)97217222abSNico Weber void *operator new(size_t size, std::align_val_t align)
98217222abSNico Weber { OPERATOR_NEW_BODY_ALIGN(FROM_NEW, false /*nothrow*/); }
99217222abSNico Weber CXX_OPERATOR_ATTRIBUTE
operator new[](size_t size,std::align_val_t align)100217222abSNico Weber void *operator new[](size_t size, std::align_val_t align)
101217222abSNico Weber { OPERATOR_NEW_BODY_ALIGN(FROM_NEW_BR, false /*nothrow*/); }
102217222abSNico Weber CXX_OPERATOR_ATTRIBUTE
operator new(size_t size,std::align_val_t align,std::nothrow_t const &)103217222abSNico Weber void *operator new(size_t size, std::align_val_t align, std::nothrow_t const&)
104217222abSNico Weber { OPERATOR_NEW_BODY_ALIGN(FROM_NEW, true /*nothrow*/); }
105217222abSNico Weber CXX_OPERATOR_ATTRIBUTE
operator new[](size_t size,std::align_val_t align,std::nothrow_t const &)106217222abSNico Weber void *operator new[](size_t size, std::align_val_t align, std::nothrow_t const&)
107217222abSNico Weber { OPERATOR_NEW_BODY_ALIGN(FROM_NEW_BR, true /*nothrow*/); }
108217222abSNico Weber
109*8246b2e1SMariusz Borsa #else // SANITIZER_APPLE
INTERCEPTOR(void *,_Znwm,size_t size)110217222abSNico Weber INTERCEPTOR(void *, _Znwm, size_t size) {
111217222abSNico Weber OPERATOR_NEW_BODY(FROM_NEW, false /*nothrow*/);
112217222abSNico Weber }
INTERCEPTOR(void *,_Znam,size_t size)113217222abSNico Weber INTERCEPTOR(void *, _Znam, size_t size) {
114217222abSNico Weber OPERATOR_NEW_BODY(FROM_NEW_BR, false /*nothrow*/);
115217222abSNico Weber }
INTERCEPTOR(void *,_ZnwmRKSt9nothrow_t,size_t size,std::nothrow_t const &)116217222abSNico Weber INTERCEPTOR(void *, _ZnwmRKSt9nothrow_t, size_t size, std::nothrow_t const&) {
117217222abSNico Weber OPERATOR_NEW_BODY(FROM_NEW, true /*nothrow*/);
118217222abSNico Weber }
INTERCEPTOR(void *,_ZnamRKSt9nothrow_t,size_t size,std::nothrow_t const &)119217222abSNico Weber INTERCEPTOR(void *, _ZnamRKSt9nothrow_t, size_t size, std::nothrow_t const&) {
120217222abSNico Weber OPERATOR_NEW_BODY(FROM_NEW_BR, true /*nothrow*/);
121217222abSNico Weber }
122*8246b2e1SMariusz Borsa #endif // !SANITIZER_APPLE
123217222abSNico Weber
124217222abSNico Weber #define OPERATOR_DELETE_BODY(type) \
125217222abSNico Weber GET_STACK_TRACE_FREE; \
126217222abSNico Weber asan_delete(ptr, 0, 0, &stack, type);
127217222abSNico Weber
128217222abSNico Weber #define OPERATOR_DELETE_BODY_SIZE(type) \
129217222abSNico Weber GET_STACK_TRACE_FREE; \
130217222abSNico Weber asan_delete(ptr, size, 0, &stack, type);
131217222abSNico Weber
132217222abSNico Weber #define OPERATOR_DELETE_BODY_ALIGN(type) \
133217222abSNico Weber GET_STACK_TRACE_FREE; \
134217222abSNico Weber asan_delete(ptr, 0, static_cast<uptr>(align), &stack, type);
135217222abSNico Weber
136217222abSNico Weber #define OPERATOR_DELETE_BODY_SIZE_ALIGN(type) \
137217222abSNico Weber GET_STACK_TRACE_FREE; \
138217222abSNico Weber asan_delete(ptr, size, static_cast<uptr>(align), &stack, type);
139217222abSNico Weber
140*8246b2e1SMariusz Borsa #if !SANITIZER_APPLE
141217222abSNico Weber CXX_OPERATOR_ATTRIBUTE
operator delete(void * ptr)142217222abSNico Weber void operator delete(void *ptr) NOEXCEPT
143217222abSNico Weber { OPERATOR_DELETE_BODY(FROM_NEW); }
144217222abSNico Weber CXX_OPERATOR_ATTRIBUTE
operator delete[](void * ptr)145217222abSNico Weber void operator delete[](void *ptr) NOEXCEPT
146217222abSNico Weber { OPERATOR_DELETE_BODY(FROM_NEW_BR); }
147217222abSNico Weber CXX_OPERATOR_ATTRIBUTE
operator delete(void * ptr,std::nothrow_t const &)148217222abSNico Weber void operator delete(void *ptr, std::nothrow_t const&)
149217222abSNico Weber { OPERATOR_DELETE_BODY(FROM_NEW); }
150217222abSNico Weber CXX_OPERATOR_ATTRIBUTE
operator delete[](void * ptr,std::nothrow_t const &)151217222abSNico Weber void operator delete[](void *ptr, std::nothrow_t const&)
152217222abSNico Weber { OPERATOR_DELETE_BODY(FROM_NEW_BR); }
153217222abSNico Weber CXX_OPERATOR_ATTRIBUTE
operator delete(void * ptr,size_t size)154217222abSNico Weber void operator delete(void *ptr, size_t size) NOEXCEPT
155217222abSNico Weber { OPERATOR_DELETE_BODY_SIZE(FROM_NEW); }
156217222abSNico Weber CXX_OPERATOR_ATTRIBUTE
operator delete[](void * ptr,size_t size)157217222abSNico Weber void operator delete[](void *ptr, size_t size) NOEXCEPT
158217222abSNico Weber { OPERATOR_DELETE_BODY_SIZE(FROM_NEW_BR); }
159217222abSNico Weber CXX_OPERATOR_ATTRIBUTE
operator delete(void * ptr,std::align_val_t align)160217222abSNico Weber void operator delete(void *ptr, std::align_val_t align) NOEXCEPT
161217222abSNico Weber { OPERATOR_DELETE_BODY_ALIGN(FROM_NEW); }
162217222abSNico Weber CXX_OPERATOR_ATTRIBUTE
operator delete[](void * ptr,std::align_val_t align)163217222abSNico Weber void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT
164217222abSNico Weber { OPERATOR_DELETE_BODY_ALIGN(FROM_NEW_BR); }
165217222abSNico Weber CXX_OPERATOR_ATTRIBUTE
operator delete(void * ptr,std::align_val_t align,std::nothrow_t const &)166217222abSNico Weber void operator delete(void *ptr, std::align_val_t align, std::nothrow_t const&)
167217222abSNico Weber { OPERATOR_DELETE_BODY_ALIGN(FROM_NEW); }
168217222abSNico Weber CXX_OPERATOR_ATTRIBUTE
operator delete[](void * ptr,std::align_val_t align,std::nothrow_t const &)169217222abSNico Weber void operator delete[](void *ptr, std::align_val_t align, std::nothrow_t const&)
170217222abSNico Weber { OPERATOR_DELETE_BODY_ALIGN(FROM_NEW_BR); }
171217222abSNico Weber CXX_OPERATOR_ATTRIBUTE
operator delete(void * ptr,size_t size,std::align_val_t align)172217222abSNico Weber void operator delete(void *ptr, size_t size, std::align_val_t align) NOEXCEPT
173217222abSNico Weber { OPERATOR_DELETE_BODY_SIZE_ALIGN(FROM_NEW); }
174217222abSNico Weber CXX_OPERATOR_ATTRIBUTE
operator delete[](void * ptr,size_t size,std::align_val_t align)175217222abSNico Weber void operator delete[](void *ptr, size_t size, std::align_val_t align) NOEXCEPT
176217222abSNico Weber { OPERATOR_DELETE_BODY_SIZE_ALIGN(FROM_NEW_BR); }
177217222abSNico Weber
178*8246b2e1SMariusz Borsa #else // SANITIZER_APPLE
INTERCEPTOR(void,_ZdlPv,void * ptr)179217222abSNico Weber INTERCEPTOR(void, _ZdlPv, void *ptr)
180217222abSNico Weber { OPERATOR_DELETE_BODY(FROM_NEW); }
INTERCEPTOR(void,_ZdaPv,void * ptr)181217222abSNico Weber INTERCEPTOR(void, _ZdaPv, void *ptr)
182217222abSNico Weber { OPERATOR_DELETE_BODY(FROM_NEW_BR); }
INTERCEPTOR(void,_ZdlPvRKSt9nothrow_t,void * ptr,std::nothrow_t const &)183217222abSNico Weber INTERCEPTOR(void, _ZdlPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&)
184217222abSNico Weber { OPERATOR_DELETE_BODY(FROM_NEW); }
INTERCEPTOR(void,_ZdaPvRKSt9nothrow_t,void * ptr,std::nothrow_t const &)185217222abSNico Weber INTERCEPTOR(void, _ZdaPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&)
186217222abSNico Weber { OPERATOR_DELETE_BODY(FROM_NEW_BR); }
187*8246b2e1SMariusz Borsa #endif // !SANITIZER_APPLE
188