allocator_shim_default_dispatch_to_partition_alloc_unittest.cc 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. // Copyright 2020 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. #include "base/allocator/allocator_shim_default_dispatch_to_partition_alloc.h"
  5. #include <cstdlib>
  6. #include <cstring>
  7. #include "base/allocator/buildflags.h"
  8. #include "base/allocator/partition_allocator/partition_alloc_constants.h"
  9. #include "base/compiler_specific.h"
  10. #include "base/memory/page_size.h"
  11. #include "build/build_config.h"
  12. #include "testing/gtest/include/gtest/gtest.h"
  13. #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
  14. #include <malloc.h>
  15. #endif
  16. #if !defined(MEMORY_TOOL_REPLACES_ALLOCATOR) && BUILDFLAG(USE_PARTITION_ALLOC)
  17. namespace base {
  18. namespace internal {
  19. #if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
  20. // Platforms on which we override weak libc symbols.
  21. #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
  22. NOINLINE void FreeForTest(void* data) {
  23. free(data);
  24. }
  25. TEST(PartitionAllocAsMalloc, Mallinfo) {
  26. // mallinfo was deprecated in glibc 2.33. The Chrome OS device sysroot has
  27. // a new-enough glibc, but the Linux one doesn't yet, so we can't switch to
  28. // the replacement mallinfo2 yet.
  29. // Once we update the Linux sysroot to be new enough, this warning will
  30. // start firing on Linux too. At that point, s/mallinfo/mallinfo2/ in this
  31. // file and remove the pragma here and and the end of this function.
  32. #if BUILDFLAG(IS_CHROMEOS)
  33. #pragma clang diagnostic push
  34. #pragma clang diagnostic ignored "-Wdeprecated-declarations"
  35. #endif
  36. constexpr int kLargeAllocSize = 10 * 1024 * 1024;
  37. struct mallinfo before = mallinfo();
  38. void* data = malloc(1000);
  39. ASSERT_TRUE(data);
  40. void* aligned_data;
  41. ASSERT_EQ(0, posix_memalign(&aligned_data, 1024, 1000));
  42. ASSERT_TRUE(aligned_data);
  43. void* direct_mapped_data = malloc(kLargeAllocSize);
  44. ASSERT_TRUE(direct_mapped_data);
  45. struct mallinfo after_alloc = mallinfo();
  46. // Something is reported.
  47. EXPECT_GT(after_alloc.hblks, 0);
  48. EXPECT_GT(after_alloc.hblkhd, 0);
  49. EXPECT_GT(after_alloc.uordblks, 0);
  50. EXPECT_GT(after_alloc.hblks, kLargeAllocSize);
  51. // malloc() can reuse memory, so sizes are not necessarily changing, which
  52. // would mean that we need EXPECT_G*E*() rather than EXPECT_GT().
  53. //
  54. // However since we allocate direct-mapped memory, this increases the total.
  55. EXPECT_GT(after_alloc.hblks, before.hblks);
  56. EXPECT_GT(after_alloc.hblkhd, before.hblkhd);
  57. EXPECT_GT(after_alloc.uordblks, before.uordblks);
  58. // a simple malloc() / free() pair can be discarded by the compiler (and is),
  59. // making the test fail. It is sufficient to make |FreeForTest()| a NOINLINE
  60. // function for the call to not be eliminated, but this is required.
  61. FreeForTest(data);
  62. FreeForTest(aligned_data);
  63. FreeForTest(direct_mapped_data);
  64. struct mallinfo after_free = mallinfo();
  65. EXPECT_LT(after_free.hblks, after_alloc.hblks);
  66. EXPECT_LT(after_free.hblkhd, after_alloc.hblkhd);
  67. EXPECT_LT(after_free.uordblks, after_alloc.uordblks);
  68. #if BUILDFLAG(IS_CHROMEOS)
  69. #pragma clang diagnostic pop
  70. #endif
  71. }
  72. #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
  73. #endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
  74. // Note: the tests below are quite simple, they are used as simple smoke tests
  75. // for PartitionAlloc-Everywhere. Most of these directly dispatch to
  76. // PartitionAlloc, which has much more extensive tests.
  77. TEST(PartitionAllocAsMalloc, Simple) {
  78. void* data = PartitionMalloc(nullptr, 10, nullptr);
  79. EXPECT_TRUE(data);
  80. PartitionFree(nullptr, data, nullptr);
  81. }
  82. TEST(PartitionAllocAsMalloc, MallocUnchecked) {
  83. void* data = PartitionMallocUnchecked(nullptr, 10, nullptr);
  84. EXPECT_TRUE(data);
  85. PartitionFree(nullptr, data, nullptr);
  86. void* too_large = PartitionMallocUnchecked(nullptr, 4e9, nullptr);
  87. EXPECT_FALSE(too_large); // No crash.
  88. }
  89. TEST(PartitionAllocAsMalloc, Calloc) {
  90. constexpr size_t alloc_size = 100;
  91. void* data = PartitionCalloc(nullptr, 1, alloc_size, nullptr);
  92. EXPECT_TRUE(data);
  93. char* zeroes[alloc_size];
  94. memset(zeroes, 0, alloc_size);
  95. EXPECT_EQ(0, memcmp(zeroes, data, alloc_size));
  96. PartitionFree(nullptr, data, nullptr);
  97. }
  98. TEST(PartitionAllocAsMalloc, Memalign) {
  99. constexpr size_t alloc_size = 100;
  100. constexpr size_t alignment = 1024;
  101. void* data = PartitionMemalign(nullptr, alignment, alloc_size, nullptr);
  102. EXPECT_TRUE(data);
  103. EXPECT_EQ(0u, reinterpret_cast<uintptr_t>(data) % alignment);
  104. PartitionFree(nullptr, data, nullptr);
  105. }
  106. TEST(PartitionAllocAsMalloc, AlignedAlloc) {
  107. for (size_t alloc_size : {100, 100000, 10000000}) {
  108. for (size_t alignment = 1;
  109. alignment <= partition_alloc::kMaxSupportedAlignment;
  110. alignment <<= 1) {
  111. void* data =
  112. PartitionAlignedAlloc(nullptr, alloc_size, alignment, nullptr);
  113. EXPECT_TRUE(data);
  114. EXPECT_EQ(0u, reinterpret_cast<uintptr_t>(data) % alignment);
  115. PartitionFree(nullptr, data, nullptr);
  116. }
  117. }
  118. }
  119. TEST(PartitionAllocAsMalloc, AlignedRealloc) {
  120. for (size_t alloc_size : {100, 100000, 10000000}) {
  121. for (size_t alignment = 1;
  122. alignment <= partition_alloc::kMaxSupportedAlignment;
  123. alignment <<= 1) {
  124. void* data =
  125. PartitionAlignedAlloc(nullptr, alloc_size, alignment, nullptr);
  126. EXPECT_TRUE(data);
  127. void* data2 = PartitionAlignedRealloc(nullptr, data, alloc_size,
  128. alignment, nullptr);
  129. EXPECT_TRUE(data2);
  130. // Aligned realloc always relocates.
  131. EXPECT_NE(reinterpret_cast<uintptr_t>(data),
  132. reinterpret_cast<uintptr_t>(data2));
  133. PartitionFree(nullptr, data2, nullptr);
  134. }
  135. }
  136. }
  137. TEST(PartitionAllocAsMalloc, Realloc) {
  138. constexpr size_t alloc_size = 100;
  139. void* data = PartitionMalloc(nullptr, alloc_size, nullptr);
  140. EXPECT_TRUE(data);
  141. void* data2 = PartitionMalloc(nullptr, 2 * alloc_size, nullptr);
  142. EXPECT_TRUE(data2);
  143. EXPECT_NE(data2, data);
  144. PartitionFree(nullptr, data2, nullptr);
  145. }
  146. // crbug.com/1141752
  147. TEST(PartitionAllocAsMalloc, Alignment) {
  148. EXPECT_EQ(0u, reinterpret_cast<uintptr_t>(PartitionAllocMalloc::Allocator()) %
  149. alignof(partition_alloc::ThreadSafePartitionRoot));
  150. // This works fine even if nullptr is returned.
  151. EXPECT_EQ(0u, reinterpret_cast<uintptr_t>(
  152. PartitionAllocMalloc::OriginalAllocator()) %
  153. alignof(partition_alloc::ThreadSafePartitionRoot));
  154. EXPECT_EQ(0u, reinterpret_cast<uintptr_t>(
  155. PartitionAllocMalloc::AlignedAllocator()) %
  156. alignof(partition_alloc::ThreadSafePartitionRoot));
  157. }
  158. // crbug.com/1297945
  159. #if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && BUILDFLAG(IS_APPLE)
  160. TEST(PartitionAllocAsMalloc, DisableCrashOnOom) {
  161. PartitionAllocSetCallNewHandlerOnMallocFailure(false);
  162. // Smaller than the max size to avoid overflow checks with padding.
  163. void* ptr = PartitionMalloc(
  164. nullptr, std::numeric_limits<size_t>::max() - 10 * base::GetPageSize(),
  165. nullptr);
  166. // Should not crash.
  167. EXPECT_FALSE(ptr);
  168. PartitionAllocSetCallNewHandlerOnMallocFailure(true);
  169. }
  170. #endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && BUILDFLAG(IS_APPLE)
  171. } // namespace internal
  172. } // namespace base
  173. #endif // !defined(MEMORY_TOOL_REPLACES_ALLOCATOR) &&
  174. // BUILDFLAG(USE_PARTITION_ALLOC)