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