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