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/process/memory_unittest_mac.h" 25 #endif 26 #if defined(OS_LINUX) 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.*\\n?.*"); 125 126 base::debug::Alias(buf); 127 } 128 #endif // !defined(ADDRESS_SANITIZER) 129 130 TEST(ProcessMemoryTest, MacTerminateOnHeapCorruption) { 131 // Assert that freeing an unallocated pointer will crash the process. 132 char buf[9]; 133 asm("" : "=r" (buf)); // Prevent clang from being too smart. 134 #if ARCH_CPU_64_BITS 135 // On 64 bit Macs, the malloc system automatically abort()s on heap corruption 136 // but does not output anything. 137 ASSERT_DEATH(free(buf), ""); 138 #elif defined(ADDRESS_SANITIZER) 139 // AddressSanitizer replaces malloc() and prints a different error message on 140 // heap corruption. 141 ASSERT_DEATH(free(buf), "attempting free on address which " 142 "was not malloc\\(\\)-ed"); 143 #else 144 ASSERT_DEATH(free(buf), "being freed.*\\n?\\.*" 145 "\\*\\*\\* set a breakpoint in malloc_error_break to debug.*\\n?.*" 146 "Terminating process due to a potential for future heap corruption"); 147 #endif // ARCH_CPU_64_BITS || defined(ADDRESS_SANITIZER) 148 } 149 150 #endif // defined(OS_MACOSX) 151 152 // Android doesn't implement set_new_handler, so we can't use the 153 // OutOfMemoryTest cases. 154 // OpenBSD does not support these tests either. 155 // TODO(vandebo) make this work on Windows too. 156 #if !defined(OS_ANDROID) && !defined(OS_OPENBSD) && \ 157 !defined(OS_WIN) 158 159 #if defined(USE_TCMALLOC) 160 extern "C" { 161 int tc_set_new_mode(int mode); 162 } 163 #endif // defined(USE_TCMALLOC) 164 165 class OutOfMemoryTest : public testing::Test { 166 public: 167 OutOfMemoryTest() 168 : value_(NULL), 169 // Make test size as large as possible minus a few pages so 170 // that alignment or other rounding doesn't make it wrap. 171 test_size_(std::numeric_limits<std::size_t>::max() - 12 * 1024), 172 signed_test_size_(std::numeric_limits<ssize_t>::max()) { 173 } 174 175 #if defined(USE_TCMALLOC) 176 virtual void SetUp() OVERRIDE { 177 tc_set_new_mode(1); 178 } 179 180 virtual void TearDown() OVERRIDE { 181 tc_set_new_mode(0); 182 } 183 #endif // defined(USE_TCMALLOC) 184 185 protected: 186 void* value_; 187 size_t test_size_; 188 ssize_t signed_test_size_; 189 }; 190 191 class OutOfMemoryDeathTest : public OutOfMemoryTest { 192 public: 193 void SetUpInDeathAssert() { 194 // Must call EnableTerminationOnOutOfMemory() because that is called from 195 // chrome's main function and therefore hasn't been called yet. 196 // Since this call may result in another thread being created and death 197 // tests shouldn't be started in a multithread environment, this call 198 // should be done inside of the ASSERT_DEATH. 199 base::EnableTerminationOnOutOfMemory(); 200 } 201 }; 202 203 TEST_F(OutOfMemoryDeathTest, New) { 204 ASSERT_DEATH({ 205 SetUpInDeathAssert(); 206 value_ = operator new(test_size_); 207 }, ""); 208 } 209 210 TEST_F(OutOfMemoryDeathTest, NewArray) { 211 ASSERT_DEATH({ 212 SetUpInDeathAssert(); 213 value_ = new char[test_size_]; 214 }, ""); 215 } 216 217 TEST_F(OutOfMemoryDeathTest, Malloc) { 218 ASSERT_DEATH({ 219 SetUpInDeathAssert(); 220 value_ = malloc(test_size_); 221 }, ""); 222 } 223 224 TEST_F(OutOfMemoryDeathTest, Realloc) { 225 ASSERT_DEATH({ 226 SetUpInDeathAssert(); 227 value_ = realloc(NULL, test_size_); 228 }, ""); 229 } 230 231 TEST_F(OutOfMemoryDeathTest, Calloc) { 232 ASSERT_DEATH({ 233 SetUpInDeathAssert(); 234 value_ = calloc(1024, test_size_ / 1024L); 235 }, ""); 236 } 237 238 TEST_F(OutOfMemoryDeathTest, Valloc) { 239 ASSERT_DEATH({ 240 SetUpInDeathAssert(); 241 value_ = valloc(test_size_); 242 }, ""); 243 } 244 245 #if defined(OS_LINUX) 246 247 #if PVALLOC_AVAILABLE == 1 248 TEST_F(OutOfMemoryDeathTest, Pvalloc) { 249 ASSERT_DEATH({ 250 SetUpInDeathAssert(); 251 value_ = pvalloc(test_size_); 252 }, ""); 253 } 254 #endif // PVALLOC_AVAILABLE == 1 255 256 TEST_F(OutOfMemoryDeathTest, Memalign) { 257 ASSERT_DEATH({ 258 SetUpInDeathAssert(); 259 value_ = memalign(4, test_size_); 260 }, ""); 261 } 262 263 TEST_F(OutOfMemoryDeathTest, ViaSharedLibraries) { 264 // This tests that the run-time symbol resolution is overriding malloc for 265 // shared libraries (including libc itself) as well as for our code. 266 std::string format = base::StringPrintf("%%%zud", test_size_); 267 char *value = NULL; 268 ASSERT_DEATH({ 269 SetUpInDeathAssert(); 270 EXPECT_EQ(-1, asprintf(&value, format.c_str(), 0)); 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 class OutOfMemoryHandledTest : public OutOfMemoryTest { 379 public: 380 static const size_t kSafeMallocSize = 512; 381 static const size_t kSafeCallocSize = 128; 382 static const size_t kSafeCallocItems = 4; 383 384 virtual void SetUp() { 385 OutOfMemoryTest::SetUp(); 386 387 // We enable termination on OOM - just as Chrome does at early 388 // initialization - and test that UncheckedMalloc and UncheckedCalloc 389 // properly by-pass this in order to allow the caller to handle OOM. 390 base::EnableTerminationOnOutOfMemory(); 391 } 392 }; 393 394 // TODO(b.kelemen): make UncheckedMalloc and UncheckedCalloc work 395 // on Windows as well. 396 // UncheckedMalloc() and UncheckedCalloc() work as regular malloc()/calloc() 397 // under sanitizer tools. 398 #if !defined(MEMORY_TOOL_REPLACES_ALLOCATOR) 399 TEST_F(OutOfMemoryHandledTest, UncheckedMalloc) { 400 EXPECT_TRUE(base::UncheckedMalloc(kSafeMallocSize, &value_)); 401 EXPECT_TRUE(value_ != NULL); 402 free(value_); 403 404 EXPECT_FALSE(base::UncheckedMalloc(test_size_, &value_)); 405 EXPECT_TRUE(value_ == NULL); 406 } 407 408 TEST_F(OutOfMemoryHandledTest, UncheckedCalloc) { 409 EXPECT_TRUE(base::UncheckedCalloc(1, kSafeMallocSize, &value_)); 410 EXPECT_TRUE(value_ != NULL); 411 const char* bytes = static_cast<const char*>(value_); 412 for (size_t i = 0; i < kSafeMallocSize; ++i) 413 EXPECT_EQ(0, bytes[i]); 414 free(value_); 415 416 EXPECT_TRUE( 417 base::UncheckedCalloc(kSafeCallocItems, kSafeCallocSize, &value_)); 418 EXPECT_TRUE(value_ != NULL); 419 bytes = static_cast<const char*>(value_); 420 for (size_t i = 0; i < (kSafeCallocItems * kSafeCallocSize); ++i) 421 EXPECT_EQ(0, bytes[i]); 422 free(value_); 423 424 EXPECT_FALSE(base::UncheckedCalloc(1, test_size_, &value_)); 425 EXPECT_TRUE(value_ == NULL); 426 } 427 #endif // !defined(MEMORY_TOOL_REPLACES_ALLOCATOR) 428 #endif // !defined(OS_ANDROID) && !defined(OS_OPENBSD) && !defined(OS_WIN) 429