//===-- asan_malloc_win_thunk.cpp | |
//-----------------------------------------------===// | |
// | |
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
// See https://llvm.org/LICENSE.txt for license information. | |
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
// | |
//===----------------------------------------------------------------------===// | |
// | |
// This file is a part of AddressSanitizer, an address sanity checker. | |
// | |
// Windows-specific malloc interception. | |
// This is included statically for projects statically linking | |
// with the C Runtime (/MT, /MTd) in order to provide ASAN-aware | |
// versions of the C allocation functions. | |
//===----------------------------------------------------------------------===// | |
#ifdef SANITIZER_STATIC_RUNTIME_THUNK | |
# include "..\sanitizer_common\sanitizer_allocator_interface.h" | |
// #include "asan_win_thunk_common.h" | |
// Preserve stack traces with noinline. | |
# define STATIC_MALLOC_INTERFACE __declspec(noinline) | |
extern "C" { | |
__declspec(dllimport) size_t __cdecl __asan_msize(void *ptr); | |
__declspec(dllimport) void __cdecl __asan_free(void *const ptr); | |
__declspec(dllimport) void *__cdecl __asan_malloc(const size_t size); | |
__declspec(dllimport) void *__cdecl __asan_calloc(const size_t nmemb, | |
const size_t size); | |
__declspec(dllimport) void *__cdecl __asan_realloc(void *const ptr, | |
const size_t size); | |
__declspec(dllimport) void *__cdecl __asan_recalloc(void *const ptr, | |
const size_t nmemb, | |
const size_t size); | |
// Avoid tailcall optimization to preserve stack frames. | |
# pragma optimize("", off) | |
// _msize | |
STATIC_MALLOC_INTERFACE size_t _msize(void *ptr) { return __asan_msize(ptr); } | |
STATIC_MALLOC_INTERFACE size_t _msize_base(void *ptr) { | |
return __asan_msize(ptr); | |
} | |
STATIC_MALLOC_INTERFACE size_t _msize_dbg(void *ptr) { | |
return __asan_msize(ptr); | |
} | |
// free | |
STATIC_MALLOC_INTERFACE void free(void *const ptr) { return __asan_free(ptr); } | |
STATIC_MALLOC_INTERFACE void _free_base(void *const ptr) { | |
return __asan_free(ptr); | |
} | |
STATIC_MALLOC_INTERFACE void _free_dbg(void *const ptr) { | |
return __asan_free(ptr); | |
} | |
// malloc | |
STATIC_MALLOC_INTERFACE void *malloc(const size_t size) { | |
return __asan_malloc(size); | |
} | |
STATIC_MALLOC_INTERFACE void *_malloc_base(const size_t size) { | |
return __asan_malloc(size); | |
} | |
STATIC_MALLOC_INTERFACE void *_malloc_dbg(const size_t size) { | |
return __asan_malloc(size); | |
} | |
// calloc | |
STATIC_MALLOC_INTERFACE void *calloc(const size_t nmemb, const size_t size) { | |
return __asan_calloc(nmemb, size); | |
} | |
STATIC_MALLOC_INTERFACE void *_calloc_base(const size_t nmemb, | |
const size_t size) { | |
return __asan_calloc(nmemb, size); | |
} | |
STATIC_MALLOC_INTERFACE void *_calloc_impl(const size_t nmemb, | |
const size_t size, | |
int *const errno_tmp) { | |
// Provided by legacy msvcrt. | |
(void)errno_tmp; | |
return __asan_calloc(nmemb, size); | |
} | |
STATIC_MALLOC_INTERFACE void *_calloc_dbg(const size_t nmemb, const size_t size, | |
int, const char *, int) { | |
return __asan_calloc(nmemb, size); | |
} | |
// realloc | |
STATIC_MALLOC_INTERFACE void *realloc(void *const ptr, const size_t size) { | |
return __asan_realloc(ptr, size); | |
} | |
STATIC_MALLOC_INTERFACE void *_realloc_base(void *const ptr, | |
const size_t size) { | |
return __asan_realloc(ptr, size); | |
} | |
STATIC_MALLOC_INTERFACE void *_realloc_dbg(void *const ptr, const size_t size, | |
int, const char *, int) { | |
return __asan_realloc(ptr, size); | |
} | |
// recalloc | |
STATIC_MALLOC_INTERFACE void *_recalloc(void *const ptr, const size_t nmemb, | |
const size_t size) { | |
return __asan_recalloc(ptr, nmemb, size); | |
} | |
STATIC_MALLOC_INTERFACE void *_recalloc_base(void *const ptr, | |
const size_t nmemb, | |
const size_t size) { | |
return __asan_recalloc(ptr, nmemb, size); | |
} | |
STATIC_MALLOC_INTERFACE void *_recalloc_dbg(void *const ptr, const size_t nmemb, | |
const size_t size, int, | |
const char *, int) { | |
return __asan_recalloc(ptr, nmemb, size); | |
} | |
// expand | |
STATIC_MALLOC_INTERFACE void *_expand(void *, size_t) { | |
// _expand is used in realloc-like functions to resize the buffer if possible. | |
// We don't want memory to stand still while resizing buffers, so return 0. | |
return nullptr; | |
} | |
STATIC_MALLOC_INTERFACE void *_expand_dbg(void *, size_t, int, const char *, | |
int) { | |
return nullptr; | |
} | |
// We need to provide symbols for all the debug CRT functions if we decide to | |
// provide any. Most of these functions make no sense under ASan and so we | |
// make them no-ops. | |
long _CrtSetBreakAlloc(long const) { return ~0; } | |
void _CrtSetDbgBlockType(void *const, int const) { return; } | |
typedef int(__cdecl *CRT_ALLOC_HOOK)(int, void *, size_t, int, long, | |
const unsigned char *, int); | |
CRT_ALLOC_HOOK _CrtGetAllocHook() { return nullptr; } | |
CRT_ALLOC_HOOK _CrtSetAllocHook(CRT_ALLOC_HOOK const hook) { return hook; } | |
int _CrtCheckMemory() { return 1; } | |
int _CrtSetDbgFlag(int const new_bits) { return new_bits; } | |
typedef void (*CrtDoForAllClientObjectsCallback)(void *, void *); | |
void _CrtDoForAllClientObjects(CrtDoForAllClientObjectsCallback const, | |
void *const) { | |
return; | |
} | |
int _CrtIsValidPointer(void const *const p, unsigned int const, int const) { | |
return p != nullptr; | |
} | |
int _CrtIsValidHeapPointer(void const *const block) { | |
if (!block) { | |
return 0; | |
} | |
return __sanitizer_get_ownership(block); | |
} | |
int _CrtIsMemoryBlock(void const *const, unsigned const, long *const, | |
char **const, int *const) { | |
return 0; | |
} | |
int _CrtReportBlockType(void const *const) { return -1; } | |
typedef void(__cdecl *CRT_DUMP_CLIENT)(void *, size_t); | |
CRT_DUMP_CLIENT _CrtGetDumpClient() { return nullptr; } | |
CRT_DUMP_CLIENT _CrtSetDumpClient(CRT_DUMP_CLIENT new_client) { | |
return new_client; | |
} | |
void _CrtMemCheckpoint(void *const) { return; } | |
int _CrtMemDifference(void *const, void const *const, void const *const) { | |
return 0; | |
} | |
void _CrtMemDumpAllObjectsSince(void const *const) { return; } | |
int _CrtDumpMemoryLeaks() { return 0; } | |
void _CrtMemDumpStatistics(void const *const) { return; } | |
int _crtDbgFlag{0}; | |
long _crtBreakAlloc{-1}; | |
CRT_DUMP_CLIENT _pfnDumpClient{nullptr}; | |
int *__p__crtDbgFlag() { return &_crtDbgFlag; } | |
long *__p__crtBreakAlloc() { return &_crtBreakAlloc; } | |
// TODO: These were added upstream but conflict with definitions in ucrtbased. | |
// int _CrtDbgReport(int, const char *, int, const char *, const char *, ...) { | |
// ShowStatsAndAbort(); | |
// } | |
// | |
// int _CrtDbgReportW(int reportType, const wchar_t *, int, const wchar_t *, | |
// const wchar_t *, ...) { | |
// ShowStatsAndAbort(); | |
// } | |
// | |
// int _CrtSetReportMode(int, int) { return 0; } | |
} // extern "C" | |
#endif // SANITIZER_STATIC_RUNTIME_THUNK |