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