1e5f5895bda30f374b0b51412fd4d837fa59aed66Alexey Samsonov//===-- asan_malloc_win.cc ------------------------------------------------===// 2938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany// 3938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany// The LLVM Compiler Infrastructure 4938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany// 5938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany// This file is distributed under the University of Illinois Open Source 6938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany// License. See LICENSE.TXT for details. 7938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany// 8938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany//===----------------------------------------------------------------------===// 9938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany// 10938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany// This file is a part of AddressSanitizer, an address sanity checker. 11938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany// 12938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany// Windows-specific malloc interception. 13938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany//===----------------------------------------------------------------------===// 1424e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov 1524e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#include "sanitizer_common/sanitizer_platform.h" 1630e110edf92303237d471f1cb8e3ad07954fb145Evgeniy Stepanov#if SANITIZER_WINDOWS 17938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany 18938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany#include "asan_allocator.h" 19938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany#include "asan_interceptors.h" 20938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany#include "asan_internal.h" 21938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany#include "asan_stack.h" 226d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#include "interception/interception.h" 23938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany 24b46941a1d23012491a7a8a52718cacbde3c19ba1Alexey Samsonov#include <stddef.h> 25b46941a1d23012491a7a8a52718cacbde3c19ba1Alexey Samsonov 26938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryanyusing namespace __asan; // NOLINT 27938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany 286d1862363c88c183b0ed7740fca876342cf0474bStephen Hines// MT: Simply defining functions with the same signature in *.obj 296d1862363c88c183b0ed7740fca876342cf0474bStephen Hines// files overrides the standard functions in the CRT. 306d1862363c88c183b0ed7740fca876342cf0474bStephen Hines// MD: Memory allocation functions are defined in the CRT .dll, 316d1862363c88c183b0ed7740fca876342cf0474bStephen Hines// so we have to intercept them before they are called for the first time. 326d1862363c88c183b0ed7740fca876342cf0474bStephen Hines 336d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if ASAN_DYNAMIC 346d1862363c88c183b0ed7740fca876342cf0474bStephen Hines# define ALLOCATION_FUNCTION_ATTRIBUTE 356d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#else 366d1862363c88c183b0ed7740fca876342cf0474bStephen Hines# define ALLOCATION_FUNCTION_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE 376d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif 38938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany 39938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryanyextern "C" { 406d1862363c88c183b0ed7740fca876342cf0474bStephen HinesALLOCATION_FUNCTION_ATTRIBUTE 41938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryanyvoid free(void *ptr) { 42a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany GET_STACK_TRACE_FREE; 43fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany return asan_free(ptr, &stack, FROM_MALLOC); 44938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany} 45938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany 466d1862363c88c183b0ed7740fca876342cf0474bStephen HinesALLOCATION_FUNCTION_ATTRIBUTE 476d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesvoid _free_dbg(void *ptr, int) { 481bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov free(ptr); 491bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov} 501bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov 516d1862363c88c183b0ed7740fca876342cf0474bStephen HinesALLOCATION_FUNCTION_ATTRIBUTE 521bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanovvoid cfree(void *ptr) { 536d1862363c88c183b0ed7740fca876342cf0474bStephen Hines CHECK(!"cfree() should not be used on Windows"); 541bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov} 551bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov 566d1862363c88c183b0ed7740fca876342cf0474bStephen HinesALLOCATION_FUNCTION_ATTRIBUTE 57938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryanyvoid *malloc(size_t size) { 58a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany GET_STACK_TRACE_MALLOC; 59938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany return asan_malloc(size, &stack); 60938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany} 61938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany 626d1862363c88c183b0ed7740fca876342cf0474bStephen HinesALLOCATION_FUNCTION_ATTRIBUTE 636d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesvoid *_malloc_dbg(size_t size, int, const char *, int) { 641bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov return malloc(size); 651bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov} 661bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov 676d1862363c88c183b0ed7740fca876342cf0474bStephen HinesALLOCATION_FUNCTION_ATTRIBUTE 68938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryanyvoid *calloc(size_t nmemb, size_t size) { 69a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany GET_STACK_TRACE_MALLOC; 70938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany return asan_calloc(nmemb, size, &stack); 71938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany} 72938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany 736d1862363c88c183b0ed7740fca876342cf0474bStephen HinesALLOCATION_FUNCTION_ATTRIBUTE 746d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesvoid *_calloc_dbg(size_t nmemb, size_t size, int, const char *, int) { 756d1862363c88c183b0ed7740fca876342cf0474bStephen Hines return calloc(nmemb, size); 761bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov} 771bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov 786d1862363c88c183b0ed7740fca876342cf0474bStephen HinesALLOCATION_FUNCTION_ATTRIBUTE 792716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanovvoid *_calloc_impl(size_t nmemb, size_t size, int *errno_tmp) { 801bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov return calloc(nmemb, size); 812716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanov} 822716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanov 836d1862363c88c183b0ed7740fca876342cf0474bStephen HinesALLOCATION_FUNCTION_ATTRIBUTE 84938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryanyvoid *realloc(void *ptr, size_t size) { 85a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany GET_STACK_TRACE_MALLOC; 86938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany return asan_realloc(ptr, size, &stack); 87938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany} 88cf13eb28b24109c0523275a62973412b702cbb43Timur Iskhodzhanov 896d1862363c88c183b0ed7740fca876342cf0474bStephen HinesALLOCATION_FUNCTION_ATTRIBUTE 901bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanovvoid *_realloc_dbg(void *ptr, size_t size, int) { 911bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov CHECK(!"_realloc_dbg should not exist!"); 923f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany return 0; 931bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov} 941bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov 956d1862363c88c183b0ed7740fca876342cf0474bStephen HinesALLOCATION_FUNCTION_ATTRIBUTE 966d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesvoid *_recalloc(void *p, size_t n, size_t elem_size) { 971bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov if (!p) 981bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov return calloc(n, elem_size); 991bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov const size_t size = n * elem_size; 1001bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov if (elem_size != 0 && size / elem_size != n) 1013f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany return 0; 1021bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov return realloc(p, size); 1031bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov} 1041bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov 1056d1862363c88c183b0ed7740fca876342cf0474bStephen HinesALLOCATION_FUNCTION_ATTRIBUTE 106cf13eb28b24109c0523275a62973412b702cbb43Timur Iskhodzhanovsize_t _msize(void *ptr) { 1071b17f5b79d58c5aff291dde05727ad0b215b81c6Alexey Samsonov GET_CURRENT_PC_BP_SP; 1081b17f5b79d58c5aff291dde05727ad0b215b81c6Alexey Samsonov (void)sp; 1091b17f5b79d58c5aff291dde05727ad0b215b81c6Alexey Samsonov return asan_malloc_usable_size(ptr, pc, bp); 110cf13eb28b24109c0523275a62973412b702cbb43Timur Iskhodzhanov} 1111bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov 1126d1862363c88c183b0ed7740fca876342cf0474bStephen HinesALLOCATION_FUNCTION_ATTRIBUTE 1132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid *_expand(void *memblock, size_t size) { 1142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // _expand is used in realloc-like functions to resize the buffer if possible. 1152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // We don't want memory to stand still while resizing buffers, so return 0. 1162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return 0; 1172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 1182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1196d1862363c88c183b0ed7740fca876342cf0474bStephen HinesALLOCATION_FUNCTION_ATTRIBUTE 1202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid *_expand_dbg(void *memblock, size_t size) { 1216d1862363c88c183b0ed7740fca876342cf0474bStephen Hines return _expand(memblock, size); 1222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 1232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// TODO(timurrrr): Might want to add support for _aligned_* allocation 1252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// functions to detect a bit more bugs. Those functions seem to wrap malloc(). 1262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1271bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanovint _CrtDbgReport(int, const char*, int, 1281bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov const char*, const char*, ...) { 1291bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov ShowStatsAndAbort(); 1301bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov} 1311bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov 1321bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanovint _CrtDbgReportW(int reportType, const wchar_t*, int, 1331bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov const wchar_t*, const wchar_t*, ...) { 1341bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov ShowStatsAndAbort(); 1351bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov} 1361bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov 1371bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanovint _CrtSetReportMode(int, int) { 1381bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov return 0; 1391bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov} 140938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany} // extern "C" 141938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany 142d9a88ccecbd7af0d11dae4d23d85706479470fdfTimur Iskhodzhanovnamespace __asan { 143d9a88ccecbd7af0d11dae4d23d85706479470fdfTimur Iskhodzhanovvoid ReplaceSystemMalloc() { 1446d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if defined(ASAN_DYNAMIC) 1456d1862363c88c183b0ed7740fca876342cf0474bStephen Hines // We don't check the result because CRT might not be used in the process. 1466d1862363c88c183b0ed7740fca876342cf0474bStephen Hines __interception::OverrideFunction("free", (uptr)free); 1476d1862363c88c183b0ed7740fca876342cf0474bStephen Hines __interception::OverrideFunction("malloc", (uptr)malloc); 1486d1862363c88c183b0ed7740fca876342cf0474bStephen Hines __interception::OverrideFunction("_malloc_crt", (uptr)malloc); 1496d1862363c88c183b0ed7740fca876342cf0474bStephen Hines __interception::OverrideFunction("calloc", (uptr)calloc); 1506d1862363c88c183b0ed7740fca876342cf0474bStephen Hines __interception::OverrideFunction("_calloc_crt", (uptr)calloc); 1516d1862363c88c183b0ed7740fca876342cf0474bStephen Hines __interception::OverrideFunction("realloc", (uptr)realloc); 1526d1862363c88c183b0ed7740fca876342cf0474bStephen Hines __interception::OverrideFunction("_realloc_crt", (uptr)realloc); 1536d1862363c88c183b0ed7740fca876342cf0474bStephen Hines __interception::OverrideFunction("_recalloc", (uptr)_recalloc); 1546d1862363c88c183b0ed7740fca876342cf0474bStephen Hines __interception::OverrideFunction("_recalloc_crt", (uptr)_recalloc); 1556d1862363c88c183b0ed7740fca876342cf0474bStephen Hines __interception::OverrideFunction("_msize", (uptr)_msize); 1566d1862363c88c183b0ed7740fca876342cf0474bStephen Hines __interception::OverrideFunction("_expand", (uptr)_expand); 1576d1862363c88c183b0ed7740fca876342cf0474bStephen Hines 1586d1862363c88c183b0ed7740fca876342cf0474bStephen Hines // Override different versions of 'operator new' and 'operator delete'. 1596d1862363c88c183b0ed7740fca876342cf0474bStephen Hines // No need to override the nothrow versions as they just wrap the throw 1606d1862363c88c183b0ed7740fca876342cf0474bStephen Hines // versions. 1616d1862363c88c183b0ed7740fca876342cf0474bStephen Hines // FIXME: Unfortunately, MSVC miscompiles the statements that take the 1626d1862363c88c183b0ed7740fca876342cf0474bStephen Hines // addresses of the array versions of these operators, 1636d1862363c88c183b0ed7740fca876342cf0474bStephen Hines // see https://connect.microsoft.com/VisualStudio/feedbackdetail/view/946992 1646d1862363c88c183b0ed7740fca876342cf0474bStephen Hines // We might want to try to work around this by [inline] assembly or compiling 1656d1862363c88c183b0ed7740fca876342cf0474bStephen Hines // parts of the RTL with Clang. 1666d1862363c88c183b0ed7740fca876342cf0474bStephen Hines void *(*op_new)(size_t sz) = operator new; 1676d1862363c88c183b0ed7740fca876342cf0474bStephen Hines void (*op_delete)(void *p) = operator delete; 1686d1862363c88c183b0ed7740fca876342cf0474bStephen Hines void *(*op_array_new)(size_t sz) = operator new[]; 1696d1862363c88c183b0ed7740fca876342cf0474bStephen Hines void (*op_array_delete)(void *p) = operator delete[]; 1706d1862363c88c183b0ed7740fca876342cf0474bStephen Hines __interception::OverrideFunction("??2@YAPAXI@Z", (uptr)op_new); 1716d1862363c88c183b0ed7740fca876342cf0474bStephen Hines __interception::OverrideFunction("??3@YAXPAX@Z", (uptr)op_delete); 1726d1862363c88c183b0ed7740fca876342cf0474bStephen Hines __interception::OverrideFunction("??_U@YAPAXI@Z", (uptr)op_array_new); 1736d1862363c88c183b0ed7740fca876342cf0474bStephen Hines __interception::OverrideFunction("??_V@YAXPAX@Z", (uptr)op_array_delete); 1742716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanov#endif 175d9a88ccecbd7af0d11dae4d23d85706479470fdfTimur Iskhodzhanov} 176d9a88ccecbd7af0d11dae4d23d85706479470fdfTimur Iskhodzhanov} // namespace __asan 177d9a88ccecbd7af0d11dae4d23d85706479470fdfTimur Iskhodzhanov 178938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany#endif // _WIN32 179