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//===----------------------------------------------------------------------===// 14938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany#ifdef _WIN32 15938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany 16938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany#include "asan_allocator.h" 17938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany#include "asan_interceptors.h" 18938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany#include "asan_internal.h" 19938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany#include "asan_stack.h" 20938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany 21d9a88ccecbd7af0d11dae4d23d85706479470fdfTimur Iskhodzhanov#include "interception/interception.h" 22938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany 23938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany// ---------------------- Replacement functions ---------------- {{{1 24938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryanyusing namespace __asan; // NOLINT 25938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany 26938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany// FIXME: Simply defining functions with the same signature in *.obj 27938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany// files overrides the standard functions in *.lib 28938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany// This works well for simple helloworld-like tests but might need to be 29938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany// revisited in the future. 30938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany 31938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryanyextern "C" { 32938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryanyvoid free(void *ptr) { 33938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany GET_STACK_TRACE_HERE_FOR_FREE(ptr); 34938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany return asan_free(ptr, &stack); 35938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany} 36938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany 371bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanovvoid _free_dbg(void* ptr, int) { 381bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov free(ptr); 391bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov} 401bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov 411bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanovvoid cfree(void *ptr) { 421bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov CHECK(!"cfree() should not be used on Windows?"); 431bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov} 441bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov 45938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryanyvoid *malloc(size_t size) { 46938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany GET_STACK_TRACE_HERE_FOR_MALLOC; 47938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany return asan_malloc(size, &stack); 48938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany} 49938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany 501bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanovvoid* _malloc_dbg(size_t size, int , const char*, int) { 511bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov return malloc(size); 521bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov} 531bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov 54938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryanyvoid *calloc(size_t nmemb, size_t size) { 55938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany GET_STACK_TRACE_HERE_FOR_MALLOC; 56938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany return asan_calloc(nmemb, size, &stack); 57938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany} 58938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany 591bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanovvoid* _calloc_dbg(size_t n, size_t size, int, const char*, int) { 601bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov return calloc(n, size); 611bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov} 621bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov 632716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanovvoid *_calloc_impl(size_t nmemb, size_t size, int *errno_tmp) { 641bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov return calloc(nmemb, size); 652716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanov} 662716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanov 67938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryanyvoid *realloc(void *ptr, size_t size) { 68938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany GET_STACK_TRACE_HERE_FOR_MALLOC; 69938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany return asan_realloc(ptr, size, &stack); 70938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany} 71cf13eb28b24109c0523275a62973412b702cbb43Timur Iskhodzhanov 721bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanovvoid *_realloc_dbg(void *ptr, size_t size, int) { 731bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov CHECK(!"_realloc_dbg should not exist!"); 743f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany return 0; 751bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov} 761bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov 771bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanovvoid* _recalloc(void* p, size_t n, size_t elem_size) { 781bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov if (!p) 791bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov return calloc(n, elem_size); 801bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov const size_t size = n * elem_size; 811bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov if (elem_size != 0 && size / elem_size != n) 823f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany return 0; 831bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov return realloc(p, size); 841bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov} 851bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov 86cf13eb28b24109c0523275a62973412b702cbb43Timur Iskhodzhanovsize_t _msize(void *ptr) { 87cf13eb28b24109c0523275a62973412b702cbb43Timur Iskhodzhanov GET_STACK_TRACE_HERE_FOR_MALLOC; 88cf13eb28b24109c0523275a62973412b702cbb43Timur Iskhodzhanov return asan_malloc_usable_size(ptr, &stack); 89cf13eb28b24109c0523275a62973412b702cbb43Timur Iskhodzhanov} 901bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov 911bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanovint _CrtDbgReport(int, const char*, int, 921bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov const char*, const char*, ...) { 931bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov ShowStatsAndAbort(); 941bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov} 951bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov 961bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanovint _CrtDbgReportW(int reportType, const wchar_t*, int, 971bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov const wchar_t*, const wchar_t*, ...) { 981bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov ShowStatsAndAbort(); 991bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov} 1001bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov 1011bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanovint _CrtSetReportMode(int, int) { 1021bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov return 0; 1031bbe2561a695af15f116e5ffec7e5f9cf7c54811Timur Iskhodzhanov} 104938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany} // extern "C" 105938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany 106d9a88ccecbd7af0d11dae4d23d85706479470fdfTimur Iskhodzhanovusing __interception::GetRealFunctionAddress; 107d9a88ccecbd7af0d11dae4d23d85706479470fdfTimur Iskhodzhanov 108d9a88ccecbd7af0d11dae4d23d85706479470fdfTimur Iskhodzhanov// We don't want to include "windows.h" in this file to avoid extra attributes 109d9a88ccecbd7af0d11dae4d23d85706479470fdfTimur Iskhodzhanov// set on malloc/free etc (e.g. dllimport), so declare a few things manually: 110d9a88ccecbd7af0d11dae4d23d85706479470fdfTimur Iskhodzhanovextern "C" int __stdcall VirtualProtect(void* addr, size_t size, 111d9a88ccecbd7af0d11dae4d23d85706479470fdfTimur Iskhodzhanov DWORD prot, DWORD *old_prot); 112d9a88ccecbd7af0d11dae4d23d85706479470fdfTimur Iskhodzhanovconst int PAGE_EXECUTE_READWRITE = 0x40; 113d9a88ccecbd7af0d11dae4d23d85706479470fdfTimur Iskhodzhanov 114d9a88ccecbd7af0d11dae4d23d85706479470fdfTimur Iskhodzhanovnamespace __asan { 115d9a88ccecbd7af0d11dae4d23d85706479470fdfTimur Iskhodzhanovvoid ReplaceSystemMalloc() { 1162716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanov#if defined(_DLL) 1172716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanov# ifdef _WIN64 1182716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanov# error ReplaceSystemMalloc was not tested on x64 1192716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanov# endif 120d9a88ccecbd7af0d11dae4d23d85706479470fdfTimur Iskhodzhanov char *crt_malloc; 121d9a88ccecbd7af0d11dae4d23d85706479470fdfTimur Iskhodzhanov if (GetRealFunctionAddress("malloc", (void**)&crt_malloc)) { 122d9a88ccecbd7af0d11dae4d23d85706479470fdfTimur Iskhodzhanov // Replace malloc in the CRT dll with a jump to our malloc. 123d9a88ccecbd7af0d11dae4d23d85706479470fdfTimur Iskhodzhanov DWORD old_prot, unused; 124d9a88ccecbd7af0d11dae4d23d85706479470fdfTimur Iskhodzhanov CHECK(VirtualProtect(crt_malloc, 16, PAGE_EXECUTE_READWRITE, &old_prot)); 125d9a88ccecbd7af0d11dae4d23d85706479470fdfTimur Iskhodzhanov REAL(memset)(crt_malloc, 0xCC /* int 3 */, 16); // just in case. 126d9a88ccecbd7af0d11dae4d23d85706479470fdfTimur Iskhodzhanov 1272716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanov ptrdiff_t jmp_offset = (char*)malloc - (char*)crt_malloc - 5; 128d9a88ccecbd7af0d11dae4d23d85706479470fdfTimur Iskhodzhanov crt_malloc[0] = 0xE9; // jmp, should be followed by an offset. 129d9a88ccecbd7af0d11dae4d23d85706479470fdfTimur Iskhodzhanov REAL(memcpy)(crt_malloc + 1, &jmp_offset, sizeof(jmp_offset)); 130d9a88ccecbd7af0d11dae4d23d85706479470fdfTimur Iskhodzhanov 131d9a88ccecbd7af0d11dae4d23d85706479470fdfTimur Iskhodzhanov CHECK(VirtualProtect(crt_malloc, 16, old_prot, &unused)); 132d9a88ccecbd7af0d11dae4d23d85706479470fdfTimur Iskhodzhanov 133d9a88ccecbd7af0d11dae4d23d85706479470fdfTimur Iskhodzhanov // FYI: FlushInstructionCache is needed on Itanium etc but not on x86/x64. 134d9a88ccecbd7af0d11dae4d23d85706479470fdfTimur Iskhodzhanov } 135d9a88ccecbd7af0d11dae4d23d85706479470fdfTimur Iskhodzhanov 136d9a88ccecbd7af0d11dae4d23d85706479470fdfTimur Iskhodzhanov // FIXME: investigate whether anything else is needed. 1372716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanov#endif 138d9a88ccecbd7af0d11dae4d23d85706479470fdfTimur Iskhodzhanov} 139d9a88ccecbd7af0d11dae4d23d85706479470fdfTimur Iskhodzhanov} // namespace __asan 140d9a88ccecbd7af0d11dae4d23d85706479470fdfTimur Iskhodzhanov 141938b105aaa1ebb08b1ddacb2944b3caa3524a5a5Kostya Serebryany#endif // _WIN32 142