|  | // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #define _CRT_SECURE_NO_WARNINGS | 
|  |  | 
|  | #include "base/process/memory.h" | 
|  |  | 
|  | #include <limits> | 
|  |  | 
|  | #include "base/allocator/allocator_check.h" | 
|  | #include "base/allocator/buildflags.h" | 
|  | #include "base/compiler_specific.h" | 
|  | #include "base/debug/alias.h" | 
|  | #include "base/memory/aligned_memory.h" | 
|  | #include "base/strings/stringprintf.h" | 
|  | #include "build/build_config.h" | 
|  | #include "testing/gtest/include/gtest/gtest.h" | 
|  |  | 
|  | #if defined(OS_WIN) | 
|  | #include <windows.h> | 
|  | #endif | 
|  | #if defined(OS_POSIX) | 
|  | #include <errno.h> | 
|  | #endif | 
|  | #if defined(OS_MACOSX) | 
|  | #include <malloc/malloc.h> | 
|  | #include "base/allocator/allocator_interception_mac.h" | 
|  | #include "base/allocator/allocator_shim.h" | 
|  | #include "base/process/memory_unittest_mac.h" | 
|  | #endif | 
|  | #if defined(OS_LINUX) | 
|  | #include <malloc.h> | 
|  | #include "base/test/malloc_wrapper.h" | 
|  | #include "starboard/memory.h" | 
|  | #include "starboard/types.h" | 
|  | #endif | 
|  |  | 
|  | #if defined(OS_WIN) | 
|  |  | 
|  | #if defined(COMPILER_MSVC) | 
|  | // ssize_t needed for OutOfMemoryTest. | 
|  | #if defined(_WIN64) | 
|  | typedef __int64 ssize_t; | 
|  | #else | 
|  | typedef long ssize_t; | 
|  | #endif | 
|  | #endif | 
|  |  | 
|  | // HeapQueryInformation function pointer. | 
|  | typedef BOOL (WINAPI* HeapQueryFn)  \ | 
|  | (HANDLE, HEAP_INFORMATION_CLASS, PVOID, SIZE_T, PSIZE_T); | 
|  |  | 
|  | #endif  // defined(OS_WIN) | 
|  |  | 
|  | #if defined(OS_MACOSX) | 
|  |  | 
|  | // For the following Mac tests: | 
|  | // Note that base::EnableTerminationOnHeapCorruption() is called as part of | 
|  | // test suite setup and does not need to be done again, else mach_override | 
|  | // will fail. | 
|  |  | 
|  | TEST(ProcessMemoryTest, MacTerminateOnHeapCorruption) { | 
|  | #if BUILDFLAG(USE_ALLOCATOR_SHIM) | 
|  | base::allocator::InitializeAllocatorShim(); | 
|  | #endif | 
|  | // Assert that freeing an unallocated pointer will crash the process. | 
|  | char buf[9]; | 
|  | asm("" : "=r" (buf));  // Prevent clang from being too smart. | 
|  | #if ARCH_CPU_64_BITS | 
|  | // On 64 bit Macs, the malloc system automatically abort()s on heap corruption | 
|  | // but does not output anything. | 
|  | ASSERT_DEATH(SbMemoryDeallocate(buf), ""); | 
|  | #elif defined(ADDRESS_SANITIZER) | 
|  | // AddressSanitizer replaces malloc() and prints a different error message on | 
|  | // heap corruption. | 
|  | ASSERT_DEATH(SbMemoryDeallocate(buf), | 
|  | "attempting SbMemoryDeallocate on address which " | 
|  | "was not malloc\\(\\)-ed"); | 
|  | #else | 
|  | ADD_FAILURE() << "This test is not supported in this build configuration."; | 
|  | #endif | 
|  |  | 
|  | #if BUILDFLAG(USE_ALLOCATOR_SHIM) | 
|  | base::allocator::UninterceptMallocZonesForTesting(); | 
|  | #endif | 
|  | } | 
|  |  | 
|  | #endif  // defined(OS_MACOSX) | 
|  |  | 
|  | TEST(MemoryTest, AllocatorShimWorking) { | 
|  | #if defined(OS_MACOSX) | 
|  | #if BUILDFLAG(USE_ALLOCATOR_SHIM) | 
|  | base::allocator::InitializeAllocatorShim(); | 
|  | #endif | 
|  | base::allocator::InterceptAllocationsMac(); | 
|  | #endif | 
|  | ASSERT_TRUE(base::allocator::IsAllocatorInitialized()); | 
|  |  | 
|  | #if defined(OS_MACOSX) | 
|  | base::allocator::UninterceptMallocZonesForTesting(); | 
|  | #endif | 
|  | } | 
|  |  | 
|  | // OpenBSD does not support these tests. Don't test these on ASan/TSan/MSan | 
|  | // configurations: only test the real allocator. | 
|  | // Windows only supports these tests with the allocator shim in place. | 
|  | #if !defined(OS_OPENBSD) && BUILDFLAG(USE_ALLOCATOR_SHIM) && \ | 
|  | !defined(MEMORY_TOOL_REPLACES_ALLOCATOR) | 
|  |  | 
|  | namespace { | 
|  | #if defined(OS_WIN) | 
|  | // Windows raises an exception rather than using LOG(FATAL) in order to make the | 
|  | // exit code unique to OOM. | 
|  | const char* kOomRegex = ""; | 
|  | const int kExitCode = base::win::kOomExceptionCode; | 
|  | #else | 
|  | const char* kOomRegex = "Out of memory"; | 
|  | const int kExitCode = 1; | 
|  | #endif | 
|  | }  // namespace | 
|  |  | 
|  | class OutOfMemoryTest : public testing::Test { | 
|  | public: | 
|  | OutOfMemoryTest() | 
|  | : value_(nullptr), | 
|  | // Make test size as large as possible minus a few pages so | 
|  | // that alignment or other rounding doesn't make it wrap. | 
|  | test_size_(std::numeric_limits<std::size_t>::max() - 12 * 1024), | 
|  | // A test size that is > 2Gb and will cause the allocators to reject | 
|  | // the allocation due to security restrictions. See crbug.com/169327. | 
|  | insecure_test_size_(std::numeric_limits<int>::max()), | 
|  | signed_test_size_(std::numeric_limits<ssize_t>::max()) {} | 
|  |  | 
|  | protected: | 
|  | void* value_; | 
|  | size_t test_size_; | 
|  | size_t insecure_test_size_; | 
|  | ssize_t signed_test_size_; | 
|  | }; | 
|  |  | 
|  | class OutOfMemoryDeathTest : public OutOfMemoryTest { | 
|  | public: | 
|  | void SetUpInDeathAssert() { | 
|  | #if defined(OS_MACOSX) && BUILDFLAG(USE_ALLOCATOR_SHIM) | 
|  | base::allocator::InitializeAllocatorShim(); | 
|  | #endif | 
|  |  | 
|  | // Must call EnableTerminationOnOutOfMemory() because that is called from | 
|  | // chrome's main function and therefore hasn't been called yet. | 
|  | // Since this call may result in another thread being created and death | 
|  | // tests shouldn't be started in a multithread environment, this call | 
|  | // should be done inside of the ASSERT_DEATH. | 
|  | base::EnableTerminationOnOutOfMemory(); | 
|  | } | 
|  |  | 
|  | #if defined(OS_MACOSX) | 
|  | void TearDown() override { | 
|  | base::allocator::UninterceptMallocZonesForTesting(); | 
|  | } | 
|  | #endif | 
|  | }; | 
|  |  | 
|  | #if !defined(STARBOARD) | 
|  | TEST_F(OutOfMemoryDeathTest, New) { | 
|  | ASSERT_EXIT({ | 
|  | SetUpInDeathAssert(); | 
|  | value_ = operator new(test_size_); | 
|  | }, testing::ExitedWithCode(kExitCode), kOomRegex); | 
|  | } | 
|  |  | 
|  | TEST_F(OutOfMemoryDeathTest, NewArray) { | 
|  | ASSERT_EXIT({ | 
|  | SetUpInDeathAssert(); | 
|  | value_ = new char[test_size_]; | 
|  | }, testing::ExitedWithCode(kExitCode), kOomRegex); | 
|  | } | 
|  |  | 
|  | TEST_F(OutOfMemoryDeathTest, Malloc) { | 
|  | ASSERT_EXIT({ | 
|  | SetUpInDeathAssert(); | 
|  | value_ = SbMemoryAllocate(test_size_); | 
|  | }, testing::ExitedWithCode(kExitCode), kOomRegex); | 
|  | } | 
|  |  | 
|  | TEST_F(OutOfMemoryDeathTest, Realloc) { | 
|  | ASSERT_EXIT({ | 
|  | SetUpInDeathAssert(); | 
|  | value_ = SbMemoryReallocate(nullptr, test_size_); | 
|  | }, testing::ExitedWithCode(kExitCode), kOomRegex); | 
|  | } | 
|  |  | 
|  | TEST_F(OutOfMemoryDeathTest, Calloc) { | 
|  | ASSERT_EXIT({ | 
|  | SetUpInDeathAssert(); | 
|  | value_ = calloc(1024, test_size_ / 1024L); | 
|  | }, testing::ExitedWithCode(kExitCode), kOomRegex); | 
|  | } | 
|  |  | 
|  | TEST_F(OutOfMemoryDeathTest, AlignedAlloc) { | 
|  | ASSERT_EXIT({ | 
|  | SetUpInDeathAssert(); | 
|  | value_ = base::AlignedAlloc(test_size_, 8); | 
|  | }, testing::ExitedWithCode(kExitCode), kOomRegex); | 
|  | } | 
|  | #endif  // !defined(STARBOARD) | 
|  |  | 
|  | // POSIX does not define an aligned realloc function. | 
|  | #if defined(OS_WIN) | 
|  | TEST_F(OutOfMemoryDeathTest, AlignedRealloc) { | 
|  | ASSERT_EXIT({ | 
|  | SetUpInDeathAssert(); | 
|  | value_ = _aligned_realloc(NULL, test_size_, 8); | 
|  | }, testing::ExitedWithCode(kExitCode), kOomRegex); | 
|  | } | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | constexpr uint32_t kUnhandledExceptionExitCode = 0xBADA55; | 
|  |  | 
|  | // This unhandled exception filter exits the process with an exit code distinct | 
|  | // from the exception code. This is to verify that the out of memory new handler | 
|  | // causes an unhandled exception. | 
|  | LONG WINAPI ExitingUnhandledExceptionFilter(EXCEPTION_POINTERS* ExceptionInfo) { | 
|  | _exit(kUnhandledExceptionExitCode); | 
|  | } | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | TEST_F(OutOfMemoryDeathTest, NewHandlerGeneratesUnhandledException) { | 
|  | ASSERT_EXIT( | 
|  | { | 
|  | SetUpInDeathAssert(); | 
|  | SetUnhandledExceptionFilter(&ExitingUnhandledExceptionFilter); | 
|  | value_ = new char[test_size_]; | 
|  | }, | 
|  | testing::ExitedWithCode(kUnhandledExceptionExitCode), kOomRegex); | 
|  | } | 
|  | #endif  // defined(OS_WIN) | 
|  |  | 
|  | // OS X and Android have no 2Gb allocation limit. | 
|  | // See https://crbug.com/169327. | 
|  | #if !defined(OS_MACOSX) && !defined(OS_ANDROID) && !defined(STARBOARD) | 
|  | TEST_F(OutOfMemoryDeathTest, SecurityNew) { | 
|  | ASSERT_EXIT({ | 
|  | SetUpInDeathAssert(); | 
|  | value_ = operator new(insecure_test_size_); | 
|  | }, testing::ExitedWithCode(kExitCode), kOomRegex); | 
|  | } | 
|  |  | 
|  | TEST_F(OutOfMemoryDeathTest, SecurityNewArray) { | 
|  | ASSERT_EXIT({ | 
|  | SetUpInDeathAssert(); | 
|  | value_ = new char[insecure_test_size_]; | 
|  | }, testing::ExitedWithCode(kExitCode), kOomRegex); | 
|  | } | 
|  |  | 
|  | TEST_F(OutOfMemoryDeathTest, SecurityMalloc) { | 
|  | ASSERT_EXIT({ | 
|  | SetUpInDeathAssert(); | 
|  | value_ = SbMemoryAllocate(insecure_test_size_); | 
|  | }, testing::ExitedWithCode(kExitCode), kOomRegex); | 
|  | } | 
|  |  | 
|  | TEST_F(OutOfMemoryDeathTest, SecurityRealloc) { | 
|  | ASSERT_EXIT({ | 
|  | SetUpInDeathAssert(); | 
|  | value_ = SbMemoryReallocate(nullptr, insecure_test_size_); | 
|  | }, testing::ExitedWithCode(kExitCode), kOomRegex); | 
|  | } | 
|  |  | 
|  | TEST_F(OutOfMemoryDeathTest, SecurityCalloc) { | 
|  | ASSERT_EXIT({ | 
|  | SetUpInDeathAssert(); | 
|  | value_ = calloc(1024, insecure_test_size_ / 1024L); | 
|  | }, testing::ExitedWithCode(kExitCode), kOomRegex); | 
|  | } | 
|  |  | 
|  | TEST_F(OutOfMemoryDeathTest, SecurityAlignedAlloc) { | 
|  | ASSERT_EXIT({ | 
|  | SetUpInDeathAssert(); | 
|  | value_ = base::AlignedAlloc(insecure_test_size_, 8); | 
|  | }, testing::ExitedWithCode(kExitCode), kOomRegex); | 
|  | } | 
|  |  | 
|  | // POSIX does not define an aligned realloc function. | 
|  | #if defined(OS_WIN) | 
|  | TEST_F(OutOfMemoryDeathTest, SecurityAlignedRealloc) { | 
|  | ASSERT_EXIT({ | 
|  | SetUpInDeathAssert(); | 
|  | value_ = _aligned_realloc(NULL, insecure_test_size_, 8); | 
|  | }, testing::ExitedWithCode(kExitCode), kOomRegex); | 
|  | } | 
|  | #endif  // defined(OS_WIN) | 
|  | #endif  // !defined(OS_MACOSX) && !defined(OS_ANDROID) && !defined(STARBOARD) | 
|  |  | 
|  | #if defined(OS_LINUX) | 
|  |  | 
|  | TEST_F(OutOfMemoryDeathTest, Valloc) { | 
|  | ASSERT_DEATH({ | 
|  | SetUpInDeathAssert(); | 
|  | value_ = valloc(test_size_); | 
|  | }, kOomRegex); | 
|  | } | 
|  |  | 
|  | TEST_F(OutOfMemoryDeathTest, SecurityValloc) { | 
|  | ASSERT_DEATH({ | 
|  | SetUpInDeathAssert(); | 
|  | value_ = valloc(insecure_test_size_); | 
|  | }, kOomRegex); | 
|  | } | 
|  |  | 
|  | #if PVALLOC_AVAILABLE == 1 | 
|  | TEST_F(OutOfMemoryDeathTest, Pvalloc) { | 
|  | ASSERT_DEATH({ | 
|  | SetUpInDeathAssert(); | 
|  | value_ = pvalloc(test_size_); | 
|  | }, kOomRegex); | 
|  | } | 
|  |  | 
|  | TEST_F(OutOfMemoryDeathTest, SecurityPvalloc) { | 
|  | ASSERT_DEATH({ | 
|  | SetUpInDeathAssert(); | 
|  | value_ = pvalloc(insecure_test_size_); | 
|  | }, kOomRegex); | 
|  | } | 
|  | #endif  // PVALLOC_AVAILABLE == 1 | 
|  |  | 
|  | TEST_F(OutOfMemoryDeathTest, Memalign) { | 
|  | ASSERT_DEATH({ | 
|  | SetUpInDeathAssert(); | 
|  | value_ = memalign(4, test_size_); | 
|  | }, kOomRegex); | 
|  | } | 
|  |  | 
|  | TEST_F(OutOfMemoryDeathTest, ViaSharedLibraries) { | 
|  | // This tests that the run-time symbol resolution is overriding malloc for | 
|  | // shared libraries as well as for our code. | 
|  | ASSERT_DEATH({ | 
|  | SetUpInDeathAssert(); | 
|  | value_ = MallocWrapper(test_size_); | 
|  | }, kOomRegex); | 
|  | } | 
|  | #endif  // OS_LINUX | 
|  |  | 
|  | // Android doesn't implement posix_memalign(). | 
|  | #if defined(OS_POSIX) && !defined(OS_ANDROID) | 
|  | TEST_F(OutOfMemoryDeathTest, Posix_memalign) { | 
|  | // Grab the return value of posix_memalign to silence a compiler warning | 
|  | // about unused return values. We don't actually care about the return | 
|  | // value, since we're asserting death. | 
|  | ASSERT_DEATH({ | 
|  | SetUpInDeathAssert(); | 
|  | EXPECT_EQ(ENOMEM, posix_memalign(&value_, 8, test_size_)); | 
|  | }, kOomRegex); | 
|  | } | 
|  | #endif  // defined(OS_POSIX) && !defined(OS_ANDROID) | 
|  |  | 
|  | #if defined(OS_MACOSX) | 
|  |  | 
|  | // Purgeable zone tests | 
|  |  | 
|  | TEST_F(OutOfMemoryDeathTest, MallocPurgeable) { | 
|  | malloc_zone_t* zone = malloc_default_purgeable_zone(); | 
|  | ASSERT_DEATH({ | 
|  | SetUpInDeathAssert(); | 
|  | value_ = malloc_zone_malloc(zone, test_size_); | 
|  | }, kOomRegex); | 
|  | } | 
|  |  | 
|  | TEST_F(OutOfMemoryDeathTest, ReallocPurgeable) { | 
|  | malloc_zone_t* zone = malloc_default_purgeable_zone(); | 
|  | ASSERT_DEATH({ | 
|  | SetUpInDeathAssert(); | 
|  | value_ = malloc_zone_realloc(zone, NULL, test_size_); | 
|  | }, kOomRegex); | 
|  | } | 
|  |  | 
|  | TEST_F(OutOfMemoryDeathTest, CallocPurgeable) { | 
|  | malloc_zone_t* zone = malloc_default_purgeable_zone(); | 
|  | ASSERT_DEATH({ | 
|  | SetUpInDeathAssert(); | 
|  | value_ = malloc_zone_calloc(zone, 1024, test_size_ / 1024L); | 
|  | }, kOomRegex); | 
|  | } | 
|  |  | 
|  | TEST_F(OutOfMemoryDeathTest, VallocPurgeable) { | 
|  | malloc_zone_t* zone = malloc_default_purgeable_zone(); | 
|  | ASSERT_DEATH({ | 
|  | SetUpInDeathAssert(); | 
|  | value_ = malloc_zone_valloc(zone, test_size_); | 
|  | }, kOomRegex); | 
|  | } | 
|  |  | 
|  | TEST_F(OutOfMemoryDeathTest, PosixMemalignPurgeable) { | 
|  | malloc_zone_t* zone = malloc_default_purgeable_zone(); | 
|  | ASSERT_DEATH({ | 
|  | SetUpInDeathAssert(); | 
|  | value_ = malloc_zone_memalign(zone, 8, test_size_); | 
|  | }, kOomRegex); | 
|  | } | 
|  |  | 
|  | // Since these allocation functions take a signed size, it's possible that | 
|  | // calling them just once won't be enough to exhaust memory. In the 32-bit | 
|  | // environment, it's likely that these allocation attempts will fail because | 
|  | // not enough contiguous address space is available. In the 64-bit environment, | 
|  | // it's likely that they'll fail because they would require a preposterous | 
|  | // amount of (virtual) memory. | 
|  |  | 
|  | TEST_F(OutOfMemoryDeathTest, CFAllocatorSystemDefault) { | 
|  | ASSERT_DEATH({ | 
|  | SetUpInDeathAssert(); | 
|  | while ((value_ = | 
|  | base::AllocateViaCFAllocatorSystemDefault(signed_test_size_))) {} | 
|  | }, kOomRegex); | 
|  | } | 
|  |  | 
|  | TEST_F(OutOfMemoryDeathTest, CFAllocatorMalloc) { | 
|  | ASSERT_DEATH({ | 
|  | SetUpInDeathAssert(); | 
|  | while ((value_ = | 
|  | base::AllocateViaCFAllocatorMalloc(signed_test_size_))) {} | 
|  | }, kOomRegex); | 
|  | } | 
|  |  | 
|  | TEST_F(OutOfMemoryDeathTest, CFAllocatorMallocZone) { | 
|  | ASSERT_DEATH({ | 
|  | SetUpInDeathAssert(); | 
|  | while ((value_ = | 
|  | base::AllocateViaCFAllocatorMallocZone(signed_test_size_))) {} | 
|  | }, kOomRegex); | 
|  | } | 
|  |  | 
|  | #if !defined(ARCH_CPU_64_BITS) | 
|  |  | 
|  | // See process_util_unittest_mac.mm for an explanation of why this test isn't | 
|  | // run in the 64-bit environment. | 
|  |  | 
|  | TEST_F(OutOfMemoryDeathTest, PsychoticallyBigObjCObject) { | 
|  | ASSERT_DEATH({ | 
|  | SetUpInDeathAssert(); | 
|  | while ((value_ = base::AllocatePsychoticallyBigObjCObject())) {} | 
|  | }, kOomRegex); | 
|  | } | 
|  |  | 
|  | #endif  // !ARCH_CPU_64_BITS | 
|  | #endif  // OS_MACOSX | 
|  |  | 
|  | class OutOfMemoryHandledTest : public OutOfMemoryTest { | 
|  | public: | 
|  | static const size_t kSafeMallocSize = 512; | 
|  | static const size_t kSafeCallocSize = 128; | 
|  | static const size_t kSafeCallocItems = 4; | 
|  |  | 
|  | void SetUp() override { | 
|  | OutOfMemoryTest::SetUp(); | 
|  |  | 
|  | // We enable termination on OOM - just as Chrome does at early | 
|  | // initialization - and test that UncheckedMalloc and  UncheckedCalloc | 
|  | // properly by-pass this in order to allow the caller to handle OOM. | 
|  | base::EnableTerminationOnOutOfMemory(); | 
|  | } | 
|  |  | 
|  | void TearDown() override { | 
|  | #if defined(OS_MACOSX) | 
|  | base::allocator::UninterceptMallocZonesForTesting(); | 
|  | #endif | 
|  | } | 
|  | }; | 
|  |  | 
|  | #if defined(OS_WIN) | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | DWORD HandleOutOfMemoryException(EXCEPTION_POINTERS* exception_ptrs, | 
|  | size_t expected_size) { | 
|  | EXPECT_EQ(base::win::kOomExceptionCode, | 
|  | exception_ptrs->ExceptionRecord->ExceptionCode); | 
|  | EXPECT_LE(1U, exception_ptrs->ExceptionRecord->NumberParameters); | 
|  | EXPECT_EQ(expected_size, | 
|  | exception_ptrs->ExceptionRecord->ExceptionInformation[0]); | 
|  | return EXCEPTION_EXECUTE_HANDLER; | 
|  | } | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | TEST_F(OutOfMemoryTest, TerminateBecauseOutOfMemoryReportsAllocSize) { | 
|  | // On Windows, TerminateBecauseOutOfMemory reports the attempted allocation | 
|  | // size in the exception raised. | 
|  | #if defined(ARCH_CPU_64_BITS) | 
|  | // Test with a size larger than 32 bits on 64 bit machines. | 
|  | const size_t kAttemptedAllocationSize = 0xBADA55F00DULL; | 
|  | #else | 
|  | const size_t kAttemptedAllocationSize = 0xBADA55; | 
|  | #endif | 
|  |  | 
|  | __try { | 
|  | base::TerminateBecauseOutOfMemory(kAttemptedAllocationSize); | 
|  | } __except (HandleOutOfMemoryException(GetExceptionInformation(), | 
|  | kAttemptedAllocationSize)) { | 
|  | } | 
|  | } | 
|  | #endif  // OS_WIN | 
|  |  | 
|  | // TODO(b.kelemen): make UncheckedMalloc and UncheckedCalloc work | 
|  | // on Windows as well. | 
|  | TEST_F(OutOfMemoryHandledTest, UncheckedMalloc) { | 
|  | EXPECT_TRUE(base::UncheckedMalloc(kSafeMallocSize, &value_)); | 
|  | EXPECT_TRUE(value_ != nullptr); | 
|  | SbMemoryDeallocate(value_); | 
|  |  | 
|  | EXPECT_FALSE(base::UncheckedMalloc(test_size_, &value_)); | 
|  | EXPECT_TRUE(value_ == nullptr); | 
|  | } | 
|  |  | 
|  | TEST_F(OutOfMemoryHandledTest, UncheckedCalloc) { | 
|  | EXPECT_TRUE(base::UncheckedCalloc(1, kSafeMallocSize, &value_)); | 
|  | EXPECT_TRUE(value_ != nullptr); | 
|  | const char* bytes = static_cast<const char*>(value_); | 
|  | for (size_t i = 0; i < kSafeMallocSize; ++i) | 
|  | EXPECT_EQ(0, bytes[i]); | 
|  | SbMemoryDeallocate(value_); | 
|  |  | 
|  | EXPECT_TRUE( | 
|  | base::UncheckedCalloc(kSafeCallocItems, kSafeCallocSize, &value_)); | 
|  | EXPECT_TRUE(value_ != nullptr); | 
|  | bytes = static_cast<const char*>(value_); | 
|  | for (size_t i = 0; i < (kSafeCallocItems * kSafeCallocSize); ++i) | 
|  | EXPECT_EQ(0, bytes[i]); | 
|  | SbMemoryDeallocate(value_); | 
|  |  | 
|  | EXPECT_FALSE(base::UncheckedCalloc(1, test_size_, &value_)); | 
|  | EXPECT_TRUE(value_ == nullptr); | 
|  | } | 
|  | #endif  // !defined(OS_OPENBSD) && BUILDFLAG(ENABLE_WIN_ALLOCATOR_SHIM_TESTS) && | 
|  | // !defined(MEMORY_TOOL_REPLACES_ALLOCATOR) |