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