1 //===-- asan_malloc_win_thunk.cpp
2 //-----------------------------------------------===//
3 //
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file is a part of AddressSanitizer, an address sanity checker.
11 //
12 // Windows-specific malloc interception.
13 // This is included statically for projects statically linking
14 // with the C Runtime (/MT, /MTd) in order to provide ASAN-aware
15 // versions of the C allocation functions.
16 //===----------------------------------------------------------------------===//
17
18 #ifdef SANITIZER_STATIC_RUNTIME_THUNK
19 # include "..\sanitizer_common\sanitizer_allocator_interface.h"
20 // #include "asan_win_thunk_common.h"
21
22 // Preserve stack traces with noinline.
23 # define STATIC_MALLOC_INTERFACE __declspec(noinline)
24
25 extern "C" {
26 __declspec(dllimport) size_t __cdecl __asan_msize(void *ptr);
27 __declspec(dllimport) void __cdecl __asan_free(void *const ptr);
28 __declspec(dllimport) void *__cdecl __asan_malloc(const size_t size);
29 __declspec(dllimport) void *__cdecl __asan_calloc(const size_t nmemb,
30 const size_t size);
31 __declspec(dllimport) void *__cdecl __asan_realloc(void *const ptr,
32 const size_t size);
33 __declspec(dllimport) void *__cdecl __asan_recalloc(void *const ptr,
34 const size_t nmemb,
35 const size_t size);
36
37 // Avoid tailcall optimization to preserve stack frames.
38 # pragma optimize("", off)
39
40 // _msize
_msize(void * ptr)41 STATIC_MALLOC_INTERFACE size_t _msize(void *ptr) { return __asan_msize(ptr); }
42
_msize_base(void * ptr)43 STATIC_MALLOC_INTERFACE size_t _msize_base(void *ptr) {
44 return __asan_msize(ptr);
45 }
46
_msize_dbg(void * ptr)47 STATIC_MALLOC_INTERFACE size_t _msize_dbg(void *ptr) {
48 return __asan_msize(ptr);
49 }
50
51 // free
free(void * const ptr)52 STATIC_MALLOC_INTERFACE void free(void *const ptr) { return __asan_free(ptr); }
53
_free_base(void * const ptr)54 STATIC_MALLOC_INTERFACE void _free_base(void *const ptr) {
55 return __asan_free(ptr);
56 }
57
_free_dbg(void * const ptr)58 STATIC_MALLOC_INTERFACE void _free_dbg(void *const ptr) {
59 return __asan_free(ptr);
60 }
61
62 // malloc
malloc(const size_t size)63 STATIC_MALLOC_INTERFACE void *malloc(const size_t size) {
64 return __asan_malloc(size);
65 }
66
_malloc_base(const size_t size)67 STATIC_MALLOC_INTERFACE void *_malloc_base(const size_t size) {
68 return __asan_malloc(size);
69 }
70
_malloc_dbg(const size_t size)71 STATIC_MALLOC_INTERFACE void *_malloc_dbg(const size_t size) {
72 return __asan_malloc(size);
73 }
74
75 // calloc
calloc(const size_t nmemb,const size_t size)76 STATIC_MALLOC_INTERFACE void *calloc(const size_t nmemb, const size_t size) {
77 return __asan_calloc(nmemb, size);
78 }
79
_calloc_base(const size_t nmemb,const size_t size)80 STATIC_MALLOC_INTERFACE void *_calloc_base(const size_t nmemb,
81 const size_t size) {
82 return __asan_calloc(nmemb, size);
83 }
84
_calloc_impl(const size_t nmemb,const size_t size,int * const errno_tmp)85 STATIC_MALLOC_INTERFACE void *_calloc_impl(const size_t nmemb,
86 const size_t size,
87 int *const errno_tmp) {
88 // Provided by legacy msvcrt.
89 (void)errno_tmp;
90
91 return __asan_calloc(nmemb, size);
92 }
93
_calloc_dbg(const size_t nmemb,const size_t size,int,const char *,int)94 STATIC_MALLOC_INTERFACE void *_calloc_dbg(const size_t nmemb, const size_t size,
95 int, const char *, int) {
96 return __asan_calloc(nmemb, size);
97 }
98
99 // realloc
realloc(void * const ptr,const size_t size)100 STATIC_MALLOC_INTERFACE void *realloc(void *const ptr, const size_t size) {
101 return __asan_realloc(ptr, size);
102 }
103
_realloc_base(void * const ptr,const size_t size)104 STATIC_MALLOC_INTERFACE void *_realloc_base(void *const ptr,
105 const size_t size) {
106 return __asan_realloc(ptr, size);
107 }
108
_realloc_dbg(void * const ptr,const size_t size,int,const char *,int)109 STATIC_MALLOC_INTERFACE void *_realloc_dbg(void *const ptr, const size_t size,
110 int, const char *, int) {
111 return __asan_realloc(ptr, size);
112 }
113
114 // recalloc
_recalloc(void * const ptr,const size_t nmemb,const size_t size)115 STATIC_MALLOC_INTERFACE void *_recalloc(void *const ptr, const size_t nmemb,
116 const size_t size) {
117 return __asan_recalloc(ptr, nmemb, size);
118 }
119
_recalloc_base(void * const ptr,const size_t nmemb,const size_t size)120 STATIC_MALLOC_INTERFACE void *_recalloc_base(void *const ptr,
121 const size_t nmemb,
122 const size_t size) {
123 return __asan_recalloc(ptr, nmemb, size);
124 }
125
_recalloc_dbg(void * const ptr,const size_t nmemb,const size_t size,int,const char *,int)126 STATIC_MALLOC_INTERFACE void *_recalloc_dbg(void *const ptr, const size_t nmemb,
127 const size_t size, int,
128 const char *, int) {
129 return __asan_recalloc(ptr, nmemb, size);
130 }
131
132 // expand
_expand(void *,size_t)133 STATIC_MALLOC_INTERFACE void *_expand(void *, size_t) {
134 // _expand is used in realloc-like functions to resize the buffer if possible.
135 // We don't want memory to stand still while resizing buffers, so return 0.
136 return nullptr;
137 }
138
_expand_dbg(void *,size_t,int,const char *,int)139 STATIC_MALLOC_INTERFACE void *_expand_dbg(void *, size_t, int, const char *,
140 int) {
141 return nullptr;
142 }
143
144 // We need to provide symbols for all the debug CRT functions if we decide to
145 // provide any. Most of these functions make no sense under ASan and so we
146 // make them no-ops.
_CrtSetBreakAlloc(long const)147 long _CrtSetBreakAlloc(long const) { return ~0; }
148
_CrtSetDbgBlockType(void * const,int const)149 void _CrtSetDbgBlockType(void *const, int const) { return; }
150
151 typedef int(__cdecl *CRT_ALLOC_HOOK)(int, void *, size_t, int, long,
152 const unsigned char *, int);
153
_CrtGetAllocHook()154 CRT_ALLOC_HOOK _CrtGetAllocHook() { return nullptr; }
155
_CrtSetAllocHook(CRT_ALLOC_HOOK const hook)156 CRT_ALLOC_HOOK _CrtSetAllocHook(CRT_ALLOC_HOOK const hook) { return hook; }
157
_CrtCheckMemory()158 int _CrtCheckMemory() { return 1; }
159
_CrtSetDbgFlag(int const new_bits)160 int _CrtSetDbgFlag(int const new_bits) { return new_bits; }
161
162 typedef void (*CrtDoForAllClientObjectsCallback)(void *, void *);
163
_CrtDoForAllClientObjects(CrtDoForAllClientObjectsCallback const,void * const)164 void _CrtDoForAllClientObjects(CrtDoForAllClientObjectsCallback const,
165 void *const) {
166 return;
167 }
168
_CrtIsValidPointer(void const * const p,unsigned int const,int const)169 int _CrtIsValidPointer(void const *const p, unsigned int const, int const) {
170 return p != nullptr;
171 }
172
_CrtIsValidHeapPointer(void const * const block)173 int _CrtIsValidHeapPointer(void const *const block) {
174 if (!block) {
175 return 0;
176 }
177
178 return __sanitizer_get_ownership(block);
179 }
180
_CrtIsMemoryBlock(void const * const,unsigned const,long * const,char ** const,int * const)181 int _CrtIsMemoryBlock(void const *const, unsigned const, long *const,
182 char **const, int *const) {
183 return 0;
184 }
185
_CrtReportBlockType(void const * const)186 int _CrtReportBlockType(void const *const) { return -1; }
187
188 typedef void(__cdecl *CRT_DUMP_CLIENT)(void *, size_t);
189
_CrtGetDumpClient()190 CRT_DUMP_CLIENT _CrtGetDumpClient() { return nullptr; }
191
_CrtSetDumpClient(CRT_DUMP_CLIENT new_client)192 CRT_DUMP_CLIENT _CrtSetDumpClient(CRT_DUMP_CLIENT new_client) {
193 return new_client;
194 }
195
_CrtMemCheckpoint(void * const)196 void _CrtMemCheckpoint(void *const) { return; }
197
_CrtMemDifference(void * const,void const * const,void const * const)198 int _CrtMemDifference(void *const, void const *const, void const *const) {
199 return 0;
200 }
201
_CrtMemDumpAllObjectsSince(void const * const)202 void _CrtMemDumpAllObjectsSince(void const *const) { return; }
203
_CrtDumpMemoryLeaks()204 int _CrtDumpMemoryLeaks() { return 0; }
205
_CrtMemDumpStatistics(void const * const)206 void _CrtMemDumpStatistics(void const *const) { return; }
207
208 int _crtDbgFlag{0};
209 long _crtBreakAlloc{-1};
210 CRT_DUMP_CLIENT _pfnDumpClient{nullptr};
211
__p__crtDbgFlag()212 int *__p__crtDbgFlag() { return &_crtDbgFlag; }
213
__p__crtBreakAlloc()214 long *__p__crtBreakAlloc() { return &_crtBreakAlloc; }
215
216 // TODO: These were added upstream but conflict with definitions in ucrtbased.
217 // int _CrtDbgReport(int, const char *, int, const char *, const char *, ...) {
218 // ShowStatsAndAbort();
219 // }
220 //
221 // int _CrtDbgReportW(int reportType, const wchar_t *, int, const wchar_t *,
222 // const wchar_t *, ...) {
223 // ShowStatsAndAbort();
224 // }
225 //
226 // int _CrtSetReportMode(int, int) { return 0; }
227
228 } // extern "C"
229 #endif // SANITIZER_STATIC_RUNTIME_THUNK
230