OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2012 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 |
| 5 #define _CRT_SECURE_NO_WARNINGS |
| 6 |
| 7 #include "base/process/memory.h" |
| 8 |
| 9 #include <limits> |
| 10 |
| 11 #include "base/compiler_specific.h" |
| 12 #include "base/debug/alias.h" |
| 13 #include "testing/gtest/include/gtest/gtest.h" |
| 14 |
| 15 #if defined(OS_WIN) |
| 16 #include <windows.h> |
| 17 #endif |
| 18 #if defined(OS_POSIX) |
| 19 #include <errno.h> |
| 20 #endif |
| 21 #if defined(OS_MACOSX) |
| 22 #include <malloc/malloc.h> |
| 23 #include "base/process/memory_unittest_mac.h" |
| 24 #endif |
| 25 #if defined(OS_LINUX) |
| 26 #include <glib.h> |
| 27 #include <malloc.h> |
| 28 #endif |
| 29 |
| 30 #if defined(OS_WIN) |
| 31 // HeapQueryInformation function pointer. |
| 32 typedef BOOL (WINAPI* HeapQueryFn) \ |
| 33 (HANDLE, HEAP_INFORMATION_CLASS, PVOID, SIZE_T, PSIZE_T); |
| 34 |
| 35 const int kConstantInModule = 42; |
| 36 |
| 37 TEST(ProcessMemoryTest, GetModuleFromAddress) { |
| 38 // Since the unit tests are their own EXE, this should be |
| 39 // equivalent to the EXE's HINSTANCE. |
| 40 // |
| 41 // kConstantInModule is a constant in this file and |
| 42 // therefore within the unit test EXE. |
| 43 EXPECT_EQ(::GetModuleHandle(NULL), |
| 44 base::GetModuleFromAddress( |
| 45 const_cast<int*>(&kConstantInModule))); |
| 46 |
| 47 // Any address within the kernel32 module should return |
| 48 // kernel32's HMODULE. Our only assumption here is that |
| 49 // kernel32 is larger than 4 bytes. |
| 50 HMODULE kernel32 = ::GetModuleHandle(L"kernel32.dll"); |
| 51 HMODULE kernel32_from_address = |
| 52 base::GetModuleFromAddress(reinterpret_cast<DWORD*>(kernel32) + 1); |
| 53 EXPECT_EQ(kernel32, kernel32_from_address); |
| 54 } |
| 55 |
| 56 TEST(ProcessMemoryTest, EnableLFH) { |
| 57 ASSERT_TRUE(base::EnableLowFragmentationHeap()); |
| 58 if (IsDebuggerPresent()) { |
| 59 // Under these conditions, LFH can't be enabled. There's no point to test |
| 60 // anything. |
| 61 const char* no_debug_env = getenv("_NO_DEBUG_HEAP"); |
| 62 if (!no_debug_env || strcmp(no_debug_env, "1")) |
| 63 return; |
| 64 } |
| 65 HMODULE kernel32 = GetModuleHandle(L"kernel32.dll"); |
| 66 ASSERT_TRUE(kernel32 != NULL); |
| 67 HeapQueryFn heap_query = reinterpret_cast<HeapQueryFn>(GetProcAddress( |
| 68 kernel32, |
| 69 "HeapQueryInformation")); |
| 70 |
| 71 // On Windows 2000, the function is not exported. This is not a reason to |
| 72 // fail but we won't be able to retrieves information about the heap, so we |
| 73 // should stop here. |
| 74 if (heap_query == NULL) |
| 75 return; |
| 76 |
| 77 HANDLE heaps[1024] = { 0 }; |
| 78 unsigned number_heaps = GetProcessHeaps(1024, heaps); |
| 79 EXPECT_GT(number_heaps, 0u); |
| 80 for (unsigned i = 0; i < number_heaps; ++i) { |
| 81 ULONG flag = 0; |
| 82 SIZE_T length; |
| 83 ASSERT_NE(0, heap_query(heaps[i], |
| 84 HeapCompatibilityInformation, |
| 85 &flag, |
| 86 sizeof(flag), |
| 87 &length)); |
| 88 // If flag is 0, the heap is a standard heap that does not support |
| 89 // look-asides. If flag is 1, the heap supports look-asides. If flag is 2, |
| 90 // the heap is a low-fragmentation heap (LFH). Note that look-asides are not |
| 91 // supported on the LFH. |
| 92 |
| 93 // We don't have any documented way of querying the HEAP_NO_SERIALIZE flag. |
| 94 EXPECT_LE(flag, 2u); |
| 95 EXPECT_NE(flag, 1u); |
| 96 } |
| 97 } |
| 98 #endif // defined(OS_WIN) |
| 99 |
| 100 #if defined(OS_MACOSX) |
| 101 |
| 102 // For the following Mac tests: |
| 103 // Note that base::EnableTerminationOnHeapCorruption() is called as part of |
| 104 // test suite setup and does not need to be done again, else mach_override |
| 105 // will fail. |
| 106 |
| 107 #if !defined(ADDRESS_SANITIZER) |
| 108 // The following code tests the system implementation of malloc() thus no need |
| 109 // to test it under AddressSanitizer. |
| 110 TEST(ProcessMemoryTest, MacMallocFailureDoesNotTerminate) { |
| 111 // Test that ENOMEM doesn't crash via CrMallocErrorBreak two ways: the exit |
| 112 // code and lack of the error string. The number of bytes is one less than |
| 113 // MALLOC_ABSOLUTE_MAX_SIZE, more than which the system early-returns NULL and |
| 114 // does not call through malloc_error_break(). See the comment at |
| 115 // EnableTerminationOnOutOfMemory() for more information. |
| 116 void* buf = NULL; |
| 117 ASSERT_EXIT( |
| 118 { |
| 119 base::EnableTerminationOnOutOfMemory(); |
| 120 |
| 121 buf = malloc(std::numeric_limits<size_t>::max() - (2 * PAGE_SIZE) - 1); |
| 122 }, |
| 123 testing::KilledBySignal(SIGTRAP), |
| 124 "\\*\\*\\* error: can't allocate region.*" |
| 125 "(Terminating process due to a potential for future heap " |
| 126 "corruption){0}"); |
| 127 |
| 128 base::debug::Alias(buf); |
| 129 } |
| 130 #endif // !defined(ADDRESS_SANITIZER) |
| 131 |
| 132 TEST(ProcessMemoryTest, MacTerminateOnHeapCorruption) { |
| 133 // Assert that freeing an unallocated pointer will crash the process. |
| 134 char buf[3]; |
| 135 asm("" : "=r" (buf)); // Prevent clang from being too smart. |
| 136 #if ARCH_CPU_64_BITS |
| 137 // On 64 bit Macs, the malloc system automatically abort()s on heap corruption |
| 138 // but does not output anything. |
| 139 ASSERT_DEATH(free(buf), ""); |
| 140 #elif defined(ADDRESS_SANITIZER) |
| 141 // AddressSanitizer replaces malloc() and prints a different error message on |
| 142 // heap corruption. |
| 143 ASSERT_DEATH(free(buf), "attempting free on address which " |
| 144 "was not malloc\\(\\)-ed"); |
| 145 #else |
| 146 ASSERT_DEATH(free(buf), "being freed.*" |
| 147 "\\*\\*\\* set a breakpoint in malloc_error_break to debug.*" |
| 148 "Terminating process due to a potential for future heap corruption"); |
| 149 #endif // ARCH_CPU_64_BITS || defined(ADDRESS_SANITIZER) |
| 150 } |
| 151 |
| 152 #endif // defined(OS_MACOSX) |
| 153 |
| 154 // Android doesn't implement set_new_handler, so we can't use the |
| 155 // OutOfMemoryTest cases. |
| 156 // OpenBSD does not support these tests either. |
| 157 // AddressSanitizer and ThreadSanitizer define the malloc()/free()/etc. |
| 158 // functions so that they don't crash if the program is out of memory, so the |
| 159 // OOM tests aren't supposed to work. |
| 160 // TODO(vandebo) make this work on Windows too. |
| 161 #if !defined(OS_ANDROID) && !defined(OS_OPENBSD) && \ |
| 162 !defined(OS_WIN) && \ |
| 163 !defined(ADDRESS_SANITIZER) && !defined(THREAD_SANITIZER) |
| 164 |
| 165 #if defined(USE_TCMALLOC) |
| 166 extern "C" { |
| 167 int tc_set_new_mode(int mode); |
| 168 } |
| 169 #endif // defined(USE_TCMALLOC) |
| 170 |
| 171 class OutOfMemoryDeathTest : public testing::Test { |
| 172 public: |
| 173 OutOfMemoryDeathTest() |
| 174 : value_(NULL), |
| 175 // Make test size as large as possible minus a few pages so |
| 176 // that alignment or other rounding doesn't make it wrap. |
| 177 test_size_(std::numeric_limits<std::size_t>::max() - 12 * 1024), |
| 178 signed_test_size_(std::numeric_limits<ssize_t>::max()) { |
| 179 } |
| 180 |
| 181 #if defined(USE_TCMALLOC) |
| 182 virtual void SetUp() OVERRIDE { |
| 183 tc_set_new_mode(1); |
| 184 } |
| 185 |
| 186 virtual void TearDown() OVERRIDE { |
| 187 tc_set_new_mode(0); |
| 188 } |
| 189 #endif // defined(USE_TCMALLOC) |
| 190 |
| 191 void SetUpInDeathAssert() { |
| 192 // Must call EnableTerminationOnOutOfMemory() because that is called from |
| 193 // chrome's main function and therefore hasn't been called yet. |
| 194 // Since this call may result in another thread being created and death |
| 195 // tests shouldn't be started in a multithread environment, this call |
| 196 // should be done inside of the ASSERT_DEATH. |
| 197 base::EnableTerminationOnOutOfMemory(); |
| 198 } |
| 199 |
| 200 void* value_; |
| 201 size_t test_size_; |
| 202 ssize_t signed_test_size_; |
| 203 }; |
| 204 |
| 205 TEST_F(OutOfMemoryDeathTest, New) { |
| 206 ASSERT_DEATH({ |
| 207 SetUpInDeathAssert(); |
| 208 value_ = operator new(test_size_); |
| 209 }, ""); |
| 210 } |
| 211 |
| 212 TEST_F(OutOfMemoryDeathTest, NewArray) { |
| 213 ASSERT_DEATH({ |
| 214 SetUpInDeathAssert(); |
| 215 value_ = new char[test_size_]; |
| 216 }, ""); |
| 217 } |
| 218 |
| 219 TEST_F(OutOfMemoryDeathTest, Malloc) { |
| 220 ASSERT_DEATH({ |
| 221 SetUpInDeathAssert(); |
| 222 value_ = malloc(test_size_); |
| 223 }, ""); |
| 224 } |
| 225 |
| 226 TEST_F(OutOfMemoryDeathTest, Realloc) { |
| 227 ASSERT_DEATH({ |
| 228 SetUpInDeathAssert(); |
| 229 value_ = realloc(NULL, test_size_); |
| 230 }, ""); |
| 231 } |
| 232 |
| 233 TEST_F(OutOfMemoryDeathTest, Calloc) { |
| 234 ASSERT_DEATH({ |
| 235 SetUpInDeathAssert(); |
| 236 value_ = calloc(1024, test_size_ / 1024L); |
| 237 }, ""); |
| 238 } |
| 239 |
| 240 TEST_F(OutOfMemoryDeathTest, Valloc) { |
| 241 ASSERT_DEATH({ |
| 242 SetUpInDeathAssert(); |
| 243 value_ = valloc(test_size_); |
| 244 }, ""); |
| 245 } |
| 246 |
| 247 #if defined(OS_LINUX) |
| 248 TEST_F(OutOfMemoryDeathTest, Pvalloc) { |
| 249 ASSERT_DEATH({ |
| 250 SetUpInDeathAssert(); |
| 251 value_ = pvalloc(test_size_); |
| 252 }, ""); |
| 253 } |
| 254 |
| 255 TEST_F(OutOfMemoryDeathTest, Memalign) { |
| 256 ASSERT_DEATH({ |
| 257 SetUpInDeathAssert(); |
| 258 value_ = memalign(4, test_size_); |
| 259 }, ""); |
| 260 } |
| 261 |
| 262 TEST_F(OutOfMemoryDeathTest, ViaSharedLibraries) { |
| 263 // g_try_malloc is documented to return NULL on failure. (g_malloc is the |
| 264 // 'safe' default that crashes if allocation fails). However, since we have |
| 265 // hopefully overridden malloc, even g_try_malloc should fail. This tests |
| 266 // that the run-time symbol resolution is overriding malloc for shared |
| 267 // libraries as well as for our code. |
| 268 ASSERT_DEATH({ |
| 269 SetUpInDeathAssert(); |
| 270 value_ = g_try_malloc(test_size_); |
| 271 }, ""); |
| 272 } |
| 273 #endif // OS_LINUX |
| 274 |
| 275 // Android doesn't implement posix_memalign(). |
| 276 #if defined(OS_POSIX) && !defined(OS_ANDROID) |
| 277 TEST_F(OutOfMemoryDeathTest, Posix_memalign) { |
| 278 // Grab the return value of posix_memalign to silence a compiler warning |
| 279 // about unused return values. We don't actually care about the return |
| 280 // value, since we're asserting death. |
| 281 ASSERT_DEATH({ |
| 282 SetUpInDeathAssert(); |
| 283 EXPECT_EQ(ENOMEM, posix_memalign(&value_, 8, test_size_)); |
| 284 }, ""); |
| 285 } |
| 286 #endif // defined(OS_POSIX) && !defined(OS_ANDROID) |
| 287 |
| 288 #if defined(OS_MACOSX) |
| 289 |
| 290 // Purgeable zone tests |
| 291 |
| 292 TEST_F(OutOfMemoryDeathTest, MallocPurgeable) { |
| 293 malloc_zone_t* zone = malloc_default_purgeable_zone(); |
| 294 ASSERT_DEATH({ |
| 295 SetUpInDeathAssert(); |
| 296 value_ = malloc_zone_malloc(zone, test_size_); |
| 297 }, ""); |
| 298 } |
| 299 |
| 300 TEST_F(OutOfMemoryDeathTest, ReallocPurgeable) { |
| 301 malloc_zone_t* zone = malloc_default_purgeable_zone(); |
| 302 ASSERT_DEATH({ |
| 303 SetUpInDeathAssert(); |
| 304 value_ = malloc_zone_realloc(zone, NULL, test_size_); |
| 305 }, ""); |
| 306 } |
| 307 |
| 308 TEST_F(OutOfMemoryDeathTest, CallocPurgeable) { |
| 309 malloc_zone_t* zone = malloc_default_purgeable_zone(); |
| 310 ASSERT_DEATH({ |
| 311 SetUpInDeathAssert(); |
| 312 value_ = malloc_zone_calloc(zone, 1024, test_size_ / 1024L); |
| 313 }, ""); |
| 314 } |
| 315 |
| 316 TEST_F(OutOfMemoryDeathTest, VallocPurgeable) { |
| 317 malloc_zone_t* zone = malloc_default_purgeable_zone(); |
| 318 ASSERT_DEATH({ |
| 319 SetUpInDeathAssert(); |
| 320 value_ = malloc_zone_valloc(zone, test_size_); |
| 321 }, ""); |
| 322 } |
| 323 |
| 324 TEST_F(OutOfMemoryDeathTest, PosixMemalignPurgeable) { |
| 325 malloc_zone_t* zone = malloc_default_purgeable_zone(); |
| 326 ASSERT_DEATH({ |
| 327 SetUpInDeathAssert(); |
| 328 value_ = malloc_zone_memalign(zone, 8, test_size_); |
| 329 }, ""); |
| 330 } |
| 331 |
| 332 // Since these allocation functions take a signed size, it's possible that |
| 333 // calling them just once won't be enough to exhaust memory. In the 32-bit |
| 334 // environment, it's likely that these allocation attempts will fail because |
| 335 // not enough contiguous address space is available. In the 64-bit environment, |
| 336 // it's likely that they'll fail because they would require a preposterous |
| 337 // amount of (virtual) memory. |
| 338 |
| 339 TEST_F(OutOfMemoryDeathTest, CFAllocatorSystemDefault) { |
| 340 ASSERT_DEATH({ |
| 341 SetUpInDeathAssert(); |
| 342 while ((value_ = |
| 343 base::AllocateViaCFAllocatorSystemDefault(signed_test_size_))) {} |
| 344 }, ""); |
| 345 } |
| 346 |
| 347 TEST_F(OutOfMemoryDeathTest, CFAllocatorMalloc) { |
| 348 ASSERT_DEATH({ |
| 349 SetUpInDeathAssert(); |
| 350 while ((value_ = |
| 351 base::AllocateViaCFAllocatorMalloc(signed_test_size_))) {} |
| 352 }, ""); |
| 353 } |
| 354 |
| 355 TEST_F(OutOfMemoryDeathTest, CFAllocatorMallocZone) { |
| 356 ASSERT_DEATH({ |
| 357 SetUpInDeathAssert(); |
| 358 while ((value_ = |
| 359 base::AllocateViaCFAllocatorMallocZone(signed_test_size_))) {} |
| 360 }, ""); |
| 361 } |
| 362 |
| 363 #if !defined(ARCH_CPU_64_BITS) |
| 364 |
| 365 // See process_util_unittest_mac.mm for an explanation of why this test isn't |
| 366 // run in the 64-bit environment. |
| 367 |
| 368 TEST_F(OutOfMemoryDeathTest, PsychoticallyBigObjCObject) { |
| 369 ASSERT_DEATH({ |
| 370 SetUpInDeathAssert(); |
| 371 while ((value_ = base::AllocatePsychoticallyBigObjCObject())) {} |
| 372 }, ""); |
| 373 } |
| 374 |
| 375 #endif // !ARCH_CPU_64_BITS |
| 376 #endif // OS_MACOSX |
| 377 |
| 378 #endif // !defined(OS_ANDROID) && !defined(OS_OPENBSD) && |
| 379 // !defined(OS_WIN) && !defined(ADDRESS_SANITIZER) |
OLD | NEW |