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