| //===-- 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 |