allocator_shim_override_ucrt_symbols_win.h 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. // Copyright 2016 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. // This header defines symbols to override the same functions in the Visual C++
  5. // CRT implementation.
  6. #ifndef BASE_ALLOCATOR_ALLOCATOR_SHIM_OVERRIDE_UCRT_SYMBOLS_WIN_H_
  7. #define BASE_ALLOCATOR_ALLOCATOR_SHIM_OVERRIDE_UCRT_SYMBOLS_WIN_H_
  8. #include <malloc.h>
  9. #include <windows.h>
  10. #include "base/allocator/allocator_shim_internals.h"
  11. // Even though most C++ allocation operators can be left alone since the
  12. // interception works at a lower level, these ones should be
  13. // overridden. Otherwise they redirect to malloc(), which is configured to crash
  14. // with an OOM in failure cases, such as allocation requests that are too large.
  15. SHIM_ALWAYS_EXPORT void* operator new(size_t size,
  16. const std::nothrow_t&) noexcept {
  17. return ShimCppNewNoThrow(size);
  18. }
  19. SHIM_ALWAYS_EXPORT void* operator new[](size_t size,
  20. const std::nothrow_t&) noexcept {
  21. return ShimCppNewNoThrow(size);
  22. }
  23. extern "C" {
  24. void* (*malloc_unchecked)(size_t) = &base::allocator::UncheckedAlloc;
  25. namespace {
  26. int win_new_mode = 0;
  27. } // namespace
  28. // This function behaves similarly to MSVC's _set_new_mode.
  29. // If flag is 0 (default), calls to malloc will behave normally.
  30. // If flag is 1, calls to malloc will behave like calls to new,
  31. // and the std_new_handler will be invoked on failure.
  32. // Returns the previous mode.
  33. //
  34. // Replaces _set_new_mode in ucrt\heap\new_mode.cpp
  35. int _set_new_mode(int flag) {
  36. // The MS CRT calls this function early on in startup, so this serves as a low
  37. // overhead proof that the allocator shim is in place for this process.
  38. base::allocator::g_is_win_shim_layer_initialized = true;
  39. int old_mode = win_new_mode;
  40. win_new_mode = flag;
  41. base::allocator::SetCallNewHandlerOnMallocFailure(win_new_mode != 0);
  42. return old_mode;
  43. }
  44. // Replaces _query_new_mode in ucrt\heap\new_mode.cpp
  45. int _query_new_mode() {
  46. return win_new_mode;
  47. }
  48. // These symbols override the CRT's implementation of the same functions.
  49. __declspec(restrict) void* malloc(size_t size) {
  50. return ShimMalloc(size, nullptr);
  51. }
  52. void free(void* ptr) {
  53. ShimFree(ptr, nullptr);
  54. }
  55. __declspec(restrict) void* realloc(void* ptr, size_t size) {
  56. return ShimRealloc(ptr, size, nullptr);
  57. }
  58. __declspec(restrict) void* calloc(size_t n, size_t size) {
  59. return ShimCalloc(n, size, nullptr);
  60. }
  61. // _msize() is the Windows equivalent of malloc_size().
  62. size_t _msize(void* memblock) {
  63. return ShimGetSizeEstimate(memblock, nullptr);
  64. }
  65. __declspec(restrict) void* _aligned_malloc(size_t size, size_t alignment) {
  66. return ShimAlignedMalloc(size, alignment, nullptr);
  67. }
  68. __declspec(restrict) void* _aligned_realloc(void* address,
  69. size_t size,
  70. size_t alignment) {
  71. return ShimAlignedRealloc(address, size, alignment, nullptr);
  72. }
  73. void _aligned_free(void* address) {
  74. ShimAlignedFree(address, nullptr);
  75. }
  76. // _recalloc_base is called by CRT internally.
  77. __declspec(restrict) void* _recalloc_base(void* block,
  78. size_t count,
  79. size_t size) {
  80. const size_t old_block_size = (block != nullptr) ? _msize(block) : 0;
  81. base::CheckedNumeric<size_t> new_block_size_checked = count;
  82. new_block_size_checked *= size;
  83. const size_t new_block_size = new_block_size_checked.ValueOrDie();
  84. void* const new_block = realloc(block, new_block_size);
  85. if (new_block != nullptr && old_block_size < new_block_size) {
  86. memset(static_cast<char*>(new_block) + old_block_size, 0,
  87. new_block_size - old_block_size);
  88. }
  89. return new_block;
  90. }
  91. __declspec(restrict) void* _malloc_base(size_t size) {
  92. return malloc(size);
  93. }
  94. __declspec(restrict) void* _calloc_base(size_t n, size_t size) {
  95. return calloc(n, size);
  96. }
  97. void _free_base(void* block) {
  98. free(block);
  99. }
  100. __declspec(restrict) void* _recalloc(void* block, size_t count, size_t size) {
  101. return _recalloc_base(block, count, size);
  102. }
  103. // The following uncommon _aligned_* routines are not used in Chromium and have
  104. // been shimmed to immediately crash to ensure that implementations are added if
  105. // uses are introduced.
  106. __declspec(restrict) void* _aligned_recalloc(void* address,
  107. size_t num,
  108. size_t size,
  109. size_t alignment) {
  110. CHECK(false) << "This routine has not been implemented";
  111. __builtin_unreachable();
  112. }
  113. size_t _aligned_msize(void* address, size_t alignment, size_t offset) {
  114. CHECK(false) << "This routine has not been implemented";
  115. __builtin_unreachable();
  116. }
  117. __declspec(restrict) void* _aligned_offset_malloc(size_t size,
  118. size_t alignment,
  119. size_t offset) {
  120. CHECK(false) << "This routine has not been implemented";
  121. __builtin_unreachable();
  122. }
  123. __declspec(restrict) void* _aligned_offset_realloc(void* address,
  124. size_t size,
  125. size_t alignment,
  126. size_t offset) {
  127. CHECK(false) << "This routine has not been implemented";
  128. __builtin_unreachable();
  129. }
  130. __declspec(restrict) void* _aligned_offset_recalloc(void* address,
  131. size_t num,
  132. size_t size,
  133. size_t alignment,
  134. size_t offset) {
  135. CHECK(false) << "This routine has not been implemented";
  136. __builtin_unreachable();
  137. }
  138. } // extern "C"
  139. #endif // BASE_ALLOCATOR_ALLOCATOR_SHIM_OVERRIDE_UCRT_SYMBOLS_WIN_H_