blob: 51c5ae33caf41ab74ed979a625cd7ebeb3d4db88 [file] [log] [blame]
[email protected]bac984102013-06-28 17:40:241// 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
avibeced7c2015-12-24 06:47:599#include <stddef.h>
10
[email protected]bac984102013-06-28 17:40:2411#include <limits>
Benoît Lizé70f64a02020-01-15 00:33:1312#include <vector>
[email protected]bac984102013-06-28 17:40:2413
wfh08a96652016-04-01 22:36:3014#include "base/allocator/allocator_check.h"
Scott Violet44165792018-02-22 02:08:0815#include "base/allocator/buildflags.h"
Benoît Lizé70f64a02020-01-15 00:33:1316#include "base/allocator/partition_allocator/page_allocator.h"
[email protected]bac984102013-06-28 17:40:2417#include "base/compiler_specific.h"
18#include "base/debug/alias.h"
wfh08a96652016-04-01 22:36:3019#include "base/memory/aligned_memory.h"
Lei Zhang425893e2021-05-14 23:28:2520#include "base/memory/page_size.h"
avibeced7c2015-12-24 06:47:5921#include "build/build_config.h"
[email protected]bac984102013-06-28 17:40:2422#include "testing/gtest/include/gtest/gtest.h"
23
24#if defined(OS_WIN)
25#include <windows.h>
26#endif
27#if defined(OS_POSIX)
28#include <errno.h>
29#endif
Avi Drissman78281f32020-07-31 03:09:0330#if defined(OS_MAC)
[email protected]bac984102013-06-28 17:40:2431#include <malloc/malloc.h>
erikchenbf11b55a2017-02-10 01:34:4832#include "base/allocator/allocator_interception_mac.h"
33#include "base/allocator/allocator_shim.h"
Benoit Lize7a052052020-08-03 12:48:4634#include "base/allocator/buildflags.h"
[email protected]bac984102013-06-28 17:40:2435#include "base/process/memory_unittest_mac.h"
36#endif
Sean McAllister39b8d342020-08-25 09:08:3237#if defined(OS_LINUX) || defined(OS_CHROMEOS)
[email protected]bac984102013-06-28 17:40:2438#include <malloc.h>
icoolidge9a4f22d2015-04-07 19:28:0939#include "base/test/malloc_wrapper.h"
[email protected]bac984102013-06-28 17:40:2440#endif
Torne (Richard Coles)b8a9a662021-05-18 15:08:4741#if defined(OS_ANDROID)
42#include "base/android/build_info.h"
43#endif
[email protected]bac984102013-06-28 17:40:2444
45#if defined(OS_WIN)
wfh1bf93992015-09-21 02:21:1446
Thiago Farinaba7d2a422017-06-17 00:18:4947#if defined(COMPILER_MSVC)
wfh1bf93992015-09-21 02:21:1448// ssize_t needed for OutOfMemoryTest.
49#if defined(_WIN64)
50typedef __int64 ssize_t;
51#else
52typedef long ssize_t;
53#endif
54#endif
55
[email protected]bac984102013-06-28 17:40:2456// HeapQueryInformation function pointer.
57typedef BOOL (WINAPI* HeapQueryFn) \
58 (HANDLE, HEAP_INFORMATION_CLASS, PVOID, SIZE_T, PSIZE_T);
59
[email protected]bac984102013-06-28 17:40:2460#endif // defined(OS_WIN)
61
Avi Drissman78281f32020-07-31 03:09:0362#if defined(OS_MAC)
[email protected]bac984102013-06-28 17:40:2463
64// For the following Mac tests:
65// Note that base::EnableTerminationOnHeapCorruption() is called as part of
66// test suite setup and does not need to be done again, else mach_override
67// will fail.
68
Hans Wennborgc90800e2021-01-21 14:39:3469// Wrap free() in a function to thwart Clang's -Wfree-nonheap-object warning.
70static void callFree(void *ptr) {
71 free(ptr);
72}
73
[email protected]bac984102013-06-28 17:40:2474TEST(ProcessMemoryTest, MacTerminateOnHeapCorruption) {
primiano73228cd2017-05-25 15:16:0975#if BUILDFLAG(USE_ALLOCATOR_SHIM)
erikchenbf11b55a2017-02-10 01:34:4876 base::allocator::InitializeAllocatorShim();
77#endif
[email protected]bac984102013-06-28 17:40:2478 // Assert that freeing an unallocated pointer will crash the process.
[email protected]de8b1ad2013-07-22 21:46:5079 char buf[9];
Nico Weber57048a9c2019-08-29 18:24:4880 asm("" : "=m"(buf)); // Prevent clang from being too smart.
[email protected]bac984102013-06-28 17:40:2481#if ARCH_CPU_64_BITS
82 // On 64 bit Macs, the malloc system automatically abort()s on heap corruption
83 // but does not output anything.
Hans Wennborgc90800e2021-01-21 14:39:3484 ASSERT_DEATH(callFree(buf), "");
[email protected]bac984102013-06-28 17:40:2485#elif defined(ADDRESS_SANITIZER)
86 // AddressSanitizer replaces malloc() and prints a different error message on
87 // heap corruption.
Hans Wennborgc90800e2021-01-21 14:39:3488 ASSERT_DEATH(callFree(buf), "attempting free on address which "
[email protected]bac984102013-06-28 17:40:2489 "was not malloc\\(\\)-ed");
90#else
rsesek931d092b2015-01-29 17:21:5291 ADD_FAILURE() << "This test is not supported in this build configuration.";
92#endif
erikchen2f9bf052017-03-28 01:11:2693
primiano73228cd2017-05-25 15:16:0994#if BUILDFLAG(USE_ALLOCATOR_SHIM)
erikchen2f9bf052017-03-28 01:11:2695 base::allocator::UninterceptMallocZonesForTesting();
96#endif
[email protected]bac984102013-06-28 17:40:2497}
98
Avi Drissman78281f32020-07-31 03:09:0399#endif // defined(OS_MAC)
[email protected]bac984102013-06-28 17:40:24100
wfh08a96652016-04-01 22:36:30101TEST(MemoryTest, AllocatorShimWorking) {
Avi Drissman78281f32020-07-31 03:09:03102#if defined(OS_MAC)
primiano73228cd2017-05-25 15:16:09103#if BUILDFLAG(USE_ALLOCATOR_SHIM)
erikchenbf11b55a2017-02-10 01:34:48104 base::allocator::InitializeAllocatorShim();
105#endif
106 base::allocator::InterceptAllocationsMac();
107#endif
wfh08a96652016-04-01 22:36:30108 ASSERT_TRUE(base::allocator::IsAllocatorInitialized());
erikchen2f9bf052017-03-28 01:11:26109
Avi Drissman78281f32020-07-31 03:09:03110#if defined(OS_MAC)
erikchen2f9bf052017-03-28 01:11:26111 base::allocator::UninterceptMallocZonesForTesting();
112#endif
wfh08a96652016-04-01 22:36:30113}
114
primiano227dbd32016-08-03 16:31:03115// OpenBSD does not support these tests. Don't test these on ASan/TSan/MSan
116// configurations: only test the real allocator.
primiano3038b2f2017-05-26 15:48:32117#if !defined(OS_OPENBSD) && BUILDFLAG(USE_ALLOCATOR_SHIM) && \
gliderf9857092015-04-21 12:58:25118 !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
[email protected]bac984102013-06-28 17:40:24119
icoolidge85e13092015-04-20 18:47:12120namespace {
wfh8ca194a2016-07-20 02:06:54121#if defined(OS_WIN)
Benoit Lize7a052052020-08-03 12:48:46122
123// Windows raises an exception in order to make the exit code unique to OOM.
124#define ASSERT_OOM_DEATH(statement) \
125 ASSERT_EXIT(statement, \
126 testing::ExitedWithCode(base::win::kOomExceptionCode), "")
127
wfh8ca194a2016-07-20 02:06:54128#else
Benoit Lize7a052052020-08-03 12:48:46129
130#define ASSERT_OOM_DEATH(statement) ASSERT_DEATH(statement, "")
131
132#endif // defined(OS_WIN)
133
icoolidge85e13092015-04-20 18:47:12134} // namespace
135
[email protected]29159eb2014-03-21 22:07:03136class OutOfMemoryTest : public testing::Test {
[email protected]bac984102013-06-28 17:40:24137 public:
[email protected]29159eb2014-03-21 22:07:03138 OutOfMemoryTest()
Ivan Kotenkova16212a52017-11-08 12:37:33139 : value_(nullptr),
Avi Drissman5c8fd42b2020-08-26 17:09:25140 // Make test size as large as possible minus a few pages so that
141 // alignment or other rounding doesn't make it wrap.
142 test_size_(std::numeric_limits<std::size_t>::max() -
143 3 * base::GetPageSize()),
Ivan Kotenkova16212a52017-11-08 12:37:33144 // A test size that is > 2Gb and will cause the allocators to reject
145 // the allocation due to security restrictions. See crbug.com/169327.
146 insecure_test_size_(std::numeric_limits<int>::max()),
147 signed_test_size_(std::numeric_limits<ssize_t>::max()) {}
[email protected]bac984102013-06-28 17:40:24148
[email protected]29159eb2014-03-21 22:07:03149 protected:
150 void* value_;
151 size_t test_size_;
wfh1bf93992015-09-21 02:21:14152 size_t insecure_test_size_;
[email protected]29159eb2014-03-21 22:07:03153 ssize_t signed_test_size_;
154};
155
156class OutOfMemoryDeathTest : public OutOfMemoryTest {
157 public:
[email protected]bac984102013-06-28 17:40:24158 void SetUpInDeathAssert() {
Avi Drissman78281f32020-07-31 03:09:03159#if defined(OS_MAC) && BUILDFLAG(USE_ALLOCATOR_SHIM)
erikchenbf11b55a2017-02-10 01:34:48160 base::allocator::InitializeAllocatorShim();
161#endif
162
[email protected]bac984102013-06-28 17:40:24163 // Must call EnableTerminationOnOutOfMemory() because that is called from
164 // chrome's main function and therefore hasn't been called yet.
165 // Since this call may result in another thread being created and death
166 // tests shouldn't be started in a multithread environment, this call
167 // should be done inside of the ASSERT_DEATH.
168 base::EnableTerminationOnOutOfMemory();
169 }
erikchen2f9bf052017-03-28 01:11:26170
Avi Drissman78281f32020-07-31 03:09:03171#if defined(OS_MAC)
erikchen2f9bf052017-03-28 01:11:26172 void TearDown() override {
173 base::allocator::UninterceptMallocZonesForTesting();
174 }
175#endif
Torne (Richard Coles)b8a9a662021-05-18 15:08:47176
177 // These tests don't work properly on old x86 Android; crbug.com/1181112
178 bool ShouldSkipTest() {
179#if defined(OS_ANDROID) && defined(ARCH_CPU_X86)
180 return base::android::BuildInfo::GetInstance()->sdk_int() <
181 base::android::SDK_VERSION_NOUGAT;
Peter Kotwicz2ebc2f22021-08-18 19:21:44182#else
Torne (Richard Coles)b8a9a662021-05-18 15:08:47183 return false;
Peter Kotwicz2ebc2f22021-08-18 19:21:44184#endif
Torne (Richard Coles)b8a9a662021-05-18 15:08:47185 }
[email protected]bac984102013-06-28 17:40:24186};
187
[email protected]bac984102013-06-28 17:40:24188TEST_F(OutOfMemoryDeathTest, New) {
Torne (Richard Coles)b8a9a662021-05-18 15:08:47189 if (ShouldSkipTest()) {
190 return;
191 }
Benoit Lize7a052052020-08-03 12:48:46192 ASSERT_OOM_DEATH({
193 SetUpInDeathAssert();
194 value_ = operator new(test_size_);
195 });
[email protected]bac984102013-06-28 17:40:24196}
197
198TEST_F(OutOfMemoryDeathTest, NewArray) {
Torne (Richard Coles)b8a9a662021-05-18 15:08:47199 if (ShouldSkipTest()) {
200 return;
201 }
Benoit Lize7a052052020-08-03 12:48:46202 ASSERT_OOM_DEATH({
203 SetUpInDeathAssert();
204 value_ = new char[test_size_];
205 });
[email protected]bac984102013-06-28 17:40:24206}
207
208TEST_F(OutOfMemoryDeathTest, Malloc) {
Torne (Richard Coles)b8a9a662021-05-18 15:08:47209 if (ShouldSkipTest()) {
210 return;
211 }
Benoit Lize7a052052020-08-03 12:48:46212 ASSERT_OOM_DEATH({
213 SetUpInDeathAssert();
214 value_ = malloc(test_size_);
215 });
[email protected]bac984102013-06-28 17:40:24216}
217
218TEST_F(OutOfMemoryDeathTest, Realloc) {
Torne (Richard Coles)b8a9a662021-05-18 15:08:47219 if (ShouldSkipTest()) {
220 return;
221 }
Benoit Lize7a052052020-08-03 12:48:46222 ASSERT_OOM_DEATH({
223 SetUpInDeathAssert();
224 value_ = realloc(nullptr, test_size_);
225 });
[email protected]bac984102013-06-28 17:40:24226}
227
228TEST_F(OutOfMemoryDeathTest, Calloc) {
Torne (Richard Coles)b8a9a662021-05-18 15:08:47229 if (ShouldSkipTest()) {
230 return;
231 }
Benoit Lize7a052052020-08-03 12:48:46232 ASSERT_OOM_DEATH({
233 SetUpInDeathAssert();
234 value_ = calloc(1024, test_size_ / 1024L);
235 });
[email protected]bac984102013-06-28 17:40:24236}
237
wfh08a96652016-04-01 22:36:30238TEST_F(OutOfMemoryDeathTest, AlignedAlloc) {
Torne (Richard Coles)b8a9a662021-05-18 15:08:47239 if (ShouldSkipTest()) {
240 return;
241 }
Benoit Lize7a052052020-08-03 12:48:46242 ASSERT_OOM_DEATH({
243 SetUpInDeathAssert();
244 value_ = base::AlignedAlloc(test_size_, 8);
245 });
wfh08a96652016-04-01 22:36:30246}
wfh08a96652016-04-01 22:36:30247
248// POSIX does not define an aligned realloc function.
249#if defined(OS_WIN)
250TEST_F(OutOfMemoryDeathTest, AlignedRealloc) {
Torne (Richard Coles)b8a9a662021-05-18 15:08:47251 if (ShouldSkipTest()) {
252 return;
253 }
Benoit Lize7a052052020-08-03 12:48:46254 ASSERT_OOM_DEATH({
255 SetUpInDeathAssert();
256 value_ = _aligned_realloc(nullptr, test_size_, 8);
257 });
wfh08a96652016-04-01 22:36:30258}
Sigurdur Asgeirssoneef087df2017-07-27 15:52:13259
260namespace {
261
262constexpr uint32_t kUnhandledExceptionExitCode = 0xBADA55;
263
264// This unhandled exception filter exits the process with an exit code distinct
265// from the exception code. This is to verify that the out of memory new handler
266// causes an unhandled exception.
267LONG WINAPI ExitingUnhandledExceptionFilter(EXCEPTION_POINTERS* ExceptionInfo) {
268 _exit(kUnhandledExceptionExitCode);
269}
270
271} // namespace
272
273TEST_F(OutOfMemoryDeathTest, NewHandlerGeneratesUnhandledException) {
274 ASSERT_EXIT(
275 {
276 SetUpInDeathAssert();
277 SetUnhandledExceptionFilter(&ExitingUnhandledExceptionFilter);
278 value_ = new char[test_size_];
279 },
Benoit Lize7a052052020-08-03 12:48:46280 testing::ExitedWithCode(kUnhandledExceptionExitCode), "");
Sigurdur Asgeirssoneef087df2017-07-27 15:52:13281}
wfh08a96652016-04-01 22:36:30282#endif // defined(OS_WIN)
283
primiano227dbd32016-08-03 16:31:03284// OS X and Android have no 2Gb allocation limit.
wfh1bf93992015-09-21 02:21:14285// See https://crbug.com/169327.
Avi Drissman78281f32020-07-31 03:09:03286#if !defined(OS_MAC) && !defined(OS_ANDROID)
wfh1bf93992015-09-21 02:21:14287TEST_F(OutOfMemoryDeathTest, SecurityNew) {
Benoit Lize7a052052020-08-03 12:48:46288 ASSERT_OOM_DEATH({
289 SetUpInDeathAssert();
290 value_ = operator new(insecure_test_size_);
291 });
wfh1bf93992015-09-21 02:21:14292}
293
294TEST_F(OutOfMemoryDeathTest, SecurityNewArray) {
Benoit Lize7a052052020-08-03 12:48:46295 ASSERT_OOM_DEATH({
296 SetUpInDeathAssert();
297 value_ = new char[insecure_test_size_];
298 });
wfh1bf93992015-09-21 02:21:14299}
300
301TEST_F(OutOfMemoryDeathTest, SecurityMalloc) {
Benoit Lize7a052052020-08-03 12:48:46302 ASSERT_OOM_DEATH({
303 SetUpInDeathAssert();
304 value_ = malloc(insecure_test_size_);
305 });
wfh1bf93992015-09-21 02:21:14306}
307
308TEST_F(OutOfMemoryDeathTest, SecurityRealloc) {
Benoit Lize7a052052020-08-03 12:48:46309 ASSERT_OOM_DEATH({
310 SetUpInDeathAssert();
311 value_ = realloc(nullptr, insecure_test_size_);
312 });
wfh1bf93992015-09-21 02:21:14313}
314
315TEST_F(OutOfMemoryDeathTest, SecurityCalloc) {
Benoit Lize7a052052020-08-03 12:48:46316 ASSERT_OOM_DEATH({
317 SetUpInDeathAssert();
318 value_ = calloc(1024, insecure_test_size_ / 1024L);
319 });
wfh1bf93992015-09-21 02:21:14320}
wfh08a96652016-04-01 22:36:30321
322TEST_F(OutOfMemoryDeathTest, SecurityAlignedAlloc) {
Benoit Lize7a052052020-08-03 12:48:46323 ASSERT_OOM_DEATH({
324 SetUpInDeathAssert();
325 value_ = base::AlignedAlloc(insecure_test_size_, 8);
326 });
wfh08a96652016-04-01 22:36:30327}
328
329// POSIX does not define an aligned realloc function.
330#if defined(OS_WIN)
331TEST_F(OutOfMemoryDeathTest, SecurityAlignedRealloc) {
Benoit Lize7a052052020-08-03 12:48:46332 ASSERT_OOM_DEATH({
333 SetUpInDeathAssert();
334 value_ = _aligned_realloc(nullptr, insecure_test_size_, 8);
335 });
wfh08a96652016-04-01 22:36:30336}
337#endif // defined(OS_WIN)
Avi Drissman78281f32020-07-31 03:09:03338#endif // !defined(OS_MAC) && !defined(OS_ANDROID)
wfh1bf93992015-09-21 02:21:14339
Sean McAllister39b8d342020-08-25 09:08:32340#if defined(OS_LINUX) || defined(OS_CHROMEOS)
wfh1bf93992015-09-21 02:21:14341
[email protected]bac984102013-06-28 17:40:24342TEST_F(OutOfMemoryDeathTest, Valloc) {
Benoit Lize7a052052020-08-03 12:48:46343 ASSERT_OOM_DEATH({
344 SetUpInDeathAssert();
345 value_ = valloc(test_size_);
346 EXPECT_TRUE(value_);
347 });
[email protected]bac984102013-06-28 17:40:24348}
349
wfh1bf93992015-09-21 02:21:14350TEST_F(OutOfMemoryDeathTest, SecurityValloc) {
Benoit Lize7a052052020-08-03 12:48:46351 ASSERT_OOM_DEATH({
352 SetUpInDeathAssert();
353 value_ = valloc(insecure_test_size_);
354 });
wfh1bf93992015-09-21 02:21:14355}
[email protected]6bad17e2014-03-04 04:54:26356
[email protected]bac984102013-06-28 17:40:24357TEST_F(OutOfMemoryDeathTest, Pvalloc) {
Benoit Lize7a052052020-08-03 12:48:46358 ASSERT_OOM_DEATH({
359 SetUpInDeathAssert();
360 value_ = pvalloc(test_size_);
361 });
[email protected]bac984102013-06-28 17:40:24362}
wfh1bf93992015-09-21 02:21:14363
364TEST_F(OutOfMemoryDeathTest, SecurityPvalloc) {
Benoit Lize7a052052020-08-03 12:48:46365 ASSERT_OOM_DEATH({
366 SetUpInDeathAssert();
367 value_ = pvalloc(insecure_test_size_);
368 });
wfh1bf93992015-09-21 02:21:14369}
[email protected]bac984102013-06-28 17:40:24370
371TEST_F(OutOfMemoryDeathTest, Memalign) {
Benoit Lize7a052052020-08-03 12:48:46372 ASSERT_OOM_DEATH({
373 SetUpInDeathAssert();
374 value_ = memalign(4, test_size_);
375 });
[email protected]bac984102013-06-28 17:40:24376}
377
378TEST_F(OutOfMemoryDeathTest, ViaSharedLibraries) {
[email protected]6ec70cc72013-11-20 05:33:46379 // This tests that the run-time symbol resolution is overriding malloc for
icoolidge9a4f22d2015-04-07 19:28:09380 // shared libraries as well as for our code.
Benoit Lize7a052052020-08-03 12:48:46381 ASSERT_OOM_DEATH({
icoolidge9a4f22d2015-04-07 19:28:09382 SetUpInDeathAssert();
383 value_ = MallocWrapper(test_size_);
Benoit Lize7a052052020-08-03 12:48:46384 });
[email protected]bac984102013-06-28 17:40:24385}
Sean McAllister39b8d342020-08-25 09:08:32386#endif // defined(OS_LINUX) || defined(OS_CHROMEOS)
[email protected]bac984102013-06-28 17:40:24387
388// Android doesn't implement posix_memalign().
389#if defined(OS_POSIX) && !defined(OS_ANDROID)
390TEST_F(OutOfMemoryDeathTest, Posix_memalign) {
391 // Grab the return value of posix_memalign to silence a compiler warning
392 // about unused return values. We don't actually care about the return
393 // value, since we're asserting death.
Benoit Lize7a052052020-08-03 12:48:46394 ASSERT_OOM_DEATH({
395 SetUpInDeathAssert();
396 EXPECT_EQ(ENOMEM, posix_memalign(&value_, 8, test_size_));
397 });
[email protected]bac984102013-06-28 17:40:24398}
399#endif // defined(OS_POSIX) && !defined(OS_ANDROID)
400
Avi Drissman78281f32020-07-31 03:09:03401#if defined(OS_MAC)
[email protected]bac984102013-06-28 17:40:24402
403// Purgeable zone tests
404
405TEST_F(OutOfMemoryDeathTest, MallocPurgeable) {
406 malloc_zone_t* zone = malloc_default_purgeable_zone();
Benoit Lize7a052052020-08-03 12:48:46407 ASSERT_OOM_DEATH({
408 SetUpInDeathAssert();
409 value_ = malloc_zone_malloc(zone, test_size_);
410 });
[email protected]bac984102013-06-28 17:40:24411}
412
413TEST_F(OutOfMemoryDeathTest, ReallocPurgeable) {
414 malloc_zone_t* zone = malloc_default_purgeable_zone();
Benoit Lize7a052052020-08-03 12:48:46415 ASSERT_OOM_DEATH({
416 SetUpInDeathAssert();
417 value_ = malloc_zone_realloc(zone, nullptr, test_size_);
418 });
[email protected]bac984102013-06-28 17:40:24419}
420
421TEST_F(OutOfMemoryDeathTest, CallocPurgeable) {
422 malloc_zone_t* zone = malloc_default_purgeable_zone();
Benoit Lize7a052052020-08-03 12:48:46423 ASSERT_OOM_DEATH({
424 SetUpInDeathAssert();
425 value_ = malloc_zone_calloc(zone, 1024, test_size_ / 1024L);
426 });
[email protected]bac984102013-06-28 17:40:24427}
428
429TEST_F(OutOfMemoryDeathTest, VallocPurgeable) {
430 malloc_zone_t* zone = malloc_default_purgeable_zone();
Benoit Lize7a052052020-08-03 12:48:46431 ASSERT_OOM_DEATH({
432 SetUpInDeathAssert();
433 value_ = malloc_zone_valloc(zone, test_size_);
434 });
[email protected]bac984102013-06-28 17:40:24435}
436
437TEST_F(OutOfMemoryDeathTest, PosixMemalignPurgeable) {
438 malloc_zone_t* zone = malloc_default_purgeable_zone();
Benoit Lize7a052052020-08-03 12:48:46439 ASSERT_OOM_DEATH({
440 SetUpInDeathAssert();
441 value_ = malloc_zone_memalign(zone, 8, test_size_);
442 });
[email protected]bac984102013-06-28 17:40:24443}
444
445// Since these allocation functions take a signed size, it's possible that
446// calling them just once won't be enough to exhaust memory. In the 32-bit
447// environment, it's likely that these allocation attempts will fail because
448// not enough contiguous address space is available. In the 64-bit environment,
449// it's likely that they'll fail because they would require a preposterous
450// amount of (virtual) memory.
451
452TEST_F(OutOfMemoryDeathTest, CFAllocatorSystemDefault) {
Benoit Lize7a052052020-08-03 12:48:46453 ASSERT_OOM_DEATH({
454 SetUpInDeathAssert();
455 while ((value_ =
456 base::AllocateViaCFAllocatorSystemDefault(signed_test_size_))) {
457 }
458 });
[email protected]bac984102013-06-28 17:40:24459}
460
461TEST_F(OutOfMemoryDeathTest, CFAllocatorMalloc) {
Benoit Lize7a052052020-08-03 12:48:46462 ASSERT_OOM_DEATH({
463 SetUpInDeathAssert();
464 while ((value_ = base::AllocateViaCFAllocatorMalloc(signed_test_size_))) {
465 }
466 });
[email protected]bac984102013-06-28 17:40:24467}
468
469TEST_F(OutOfMemoryDeathTest, CFAllocatorMallocZone) {
Benoit Lize7a052052020-08-03 12:48:46470 ASSERT_OOM_DEATH({
471 SetUpInDeathAssert();
472 while (
473 (value_ = base::AllocateViaCFAllocatorMallocZone(signed_test_size_))) {
474 }
475 });
[email protected]bac984102013-06-28 17:40:24476}
477
Avi Drissman78281f32020-07-31 03:09:03478#endif // OS_MAC
[email protected]bac984102013-06-28 17:40:24479
[email protected]29159eb2014-03-21 22:07:03480class OutOfMemoryHandledTest : public OutOfMemoryTest {
481 public:
482 static const size_t kSafeMallocSize = 512;
483 static const size_t kSafeCallocSize = 128;
484 static const size_t kSafeCallocItems = 4;
485
dcheng8aef37612014-12-23 02:56:47486 void SetUp() override {
[email protected]29159eb2014-03-21 22:07:03487 OutOfMemoryTest::SetUp();
488
489 // We enable termination on OOM - just as Chrome does at early
490 // initialization - and test that UncheckedMalloc and UncheckedCalloc
491 // properly by-pass this in order to allow the caller to handle OOM.
492 base::EnableTerminationOnOutOfMemory();
493 }
erikchen2f9bf052017-03-28 01:11:26494
495 void TearDown() override {
Avi Drissman78281f32020-07-31 03:09:03496#if defined(OS_MAC)
erikchen2f9bf052017-03-28 01:11:26497 base::allocator::UninterceptMallocZonesForTesting();
498#endif
499 }
[email protected]29159eb2014-03-21 22:07:03500};
501
siggi7a7fbf7c52017-02-06 20:45:04502#if defined(OS_WIN)
503
504namespace {
505
506DWORD HandleOutOfMemoryException(EXCEPTION_POINTERS* exception_ptrs,
507 size_t expected_size) {
508 EXPECT_EQ(base::win::kOomExceptionCode,
509 exception_ptrs->ExceptionRecord->ExceptionCode);
510 EXPECT_LE(1U, exception_ptrs->ExceptionRecord->NumberParameters);
511 EXPECT_EQ(expected_size,
512 exception_ptrs->ExceptionRecord->ExceptionInformation[0]);
513 return EXCEPTION_EXECUTE_HANDLER;
514}
515
516} // namespace
517
518TEST_F(OutOfMemoryTest, TerminateBecauseOutOfMemoryReportsAllocSize) {
519// On Windows, TerminateBecauseOutOfMemory reports the attempted allocation
520// size in the exception raised.
521#if defined(ARCH_CPU_64_BITS)
522 // Test with a size larger than 32 bits on 64 bit machines.
523 const size_t kAttemptedAllocationSize = 0xBADA55F00DULL;
524#else
525 const size_t kAttemptedAllocationSize = 0xBADA55;
526#endif
527
528 __try {
529 base::TerminateBecauseOutOfMemory(kAttemptedAllocationSize);
530 } __except (HandleOutOfMemoryException(GetExceptionInformation(),
531 kAttemptedAllocationSize)) {
532 }
533}
534#endif // OS_WIN
535
Sean McAllister39b8d342020-08-25 09:08:32536#if defined(ARCH_CPU_32_BITS) && \
537 (defined(OS_WIN) || defined(OS_LINUX) || defined(OS_CHROMEOS))
Benoît Lizé70f64a02020-01-15 00:33:13538
539void TestAllocationsReleaseReservation(void* (*alloc_fn)(size_t),
540 void (*free_fn)(void*)) {
541 base::ReleaseReservation();
542 base::EnableTerminationOnOutOfMemory();
543
544 constexpr size_t kMiB = 1 << 20;
545 constexpr size_t kReservationSize = 512 * kMiB; // MiB.
546
547 size_t reservation_size = kReservationSize;
548 while (!base::ReserveAddressSpace(reservation_size)) {
549 reservation_size -= 16 * kMiB;
550 }
551 ASSERT_TRUE(base::HasReservationForTesting());
552 ASSERT_GT(reservation_size, 0u);
553
554 // Allocate a large area at a time to bump into address space exhaustion
555 // before other limits. It is important not to do a larger allocation, to
556 // verify that we can allocate without removing the reservation. On the other
557 // hand, must be large enough to make the underlying implementation call
558 // mmap()/VirtualAlloc().
559 size_t allocation_size = reservation_size / 2;
560
561 std::vector<void*> areas;
562 // Pre-reserve the vector to make sure that we don't hit the address space
563 // limit while resizing the array.
564 areas.reserve(((2 * 4096 * kMiB) / allocation_size) + 1);
565
566 while (true) {
567 void* area = alloc_fn(allocation_size / 2);
568 ASSERT_TRUE(area);
569 areas.push_back(area);
570
571 // Working as intended, the allocation was successful, and the reservation
572 // was dropped instead of crashing.
573 //
574 // Meaning that the test is either successful, or crashes.
575 if (!base::HasReservationForTesting())
576 break;
577 }
578
579 EXPECT_GE(areas.size(), 2u)
580 << "Should be able to allocate without releasing the reservation";
581
582 for (void* ptr : areas)
583 free_fn(ptr);
584}
585
586TEST_F(OutOfMemoryHandledTest, MallocReleasesReservation) {
587 TestAllocationsReleaseReservation(malloc, free);
588}
589
590TEST_F(OutOfMemoryHandledTest, NewReleasesReservation) {
591 TestAllocationsReleaseReservation(
592 [](size_t size) { return static_cast<void*>(new char[size]); },
593 [](void* ptr) { delete[] static_cast<char*>(ptr); });
594}
Sean McAllister39b8d342020-08-25 09:08:32595#endif // defined(ARCH_CPU_32_BITS) && (defined(OS_WIN) || defined(OS_LINUX) ||
596 // defined(OS_CHROMEOS))
Benoît Lizé70f64a02020-01-15 00:33:13597
Benoit Lize2b7a7462020-08-03 09:20:53598// See the comment in |UncheckedMalloc()|, it behaves as malloc() in these
599// cases.
Takashi Sakamotoab56f412020-09-18 13:46:18600#if defined(OS_ANDROID)
Benoit Lize2b7a7462020-08-03 09:20:53601
Benoit Lizeced56e12020-08-06 09:14:48602// TODO(crbug.com/1112840): Fails on some Android bots.
Benoit Lizeced56e12020-08-06 09:14:48603#define MAYBE_UncheckedMallocDies DISABLED_UncheckedMallocDies
604#define MAYBE_UncheckedCallocDies DISABLED_UncheckedCallocDies
Benoit Lizeced56e12020-08-06 09:14:48605
606TEST_F(OutOfMemoryDeathTest, MAYBE_UncheckedMallocDies) {
Benoit Lize7a052052020-08-03 12:48:46607 ASSERT_OOM_DEATH({
608 SetUpInDeathAssert();
609 void* data;
610 bool ok = base::UncheckedMalloc(test_size_, &data);
611 EXPECT_TRUE(!data || ok);
612 });
Benoit Lize2b7a7462020-08-03 09:20:53613}
614
Benoit Lizeced56e12020-08-06 09:14:48615TEST_F(OutOfMemoryDeathTest, MAYBE_UncheckedCallocDies) {
Benoit Lize7a052052020-08-03 12:48:46616 ASSERT_OOM_DEATH({
617 SetUpInDeathAssert();
618 void* data;
619 bool ok = base::UncheckedCalloc(1, test_size_, &data);
620 EXPECT_TRUE(!data || ok);
621 });
Benoit Lize2b7a7462020-08-03 09:20:53622}
623
624#else
625
[email protected]29159eb2014-03-21 22:07:03626TEST_F(OutOfMemoryHandledTest, UncheckedMalloc) {
627 EXPECT_TRUE(base::UncheckedMalloc(kSafeMallocSize, &value_));
Ivan Kotenkova16212a52017-11-08 12:37:33628 EXPECT_TRUE(value_ != nullptr);
[email protected]29159eb2014-03-21 22:07:03629 free(value_);
630
631 EXPECT_FALSE(base::UncheckedMalloc(test_size_, &value_));
Ivan Kotenkova16212a52017-11-08 12:37:33632 EXPECT_TRUE(value_ == nullptr);
[email protected]29159eb2014-03-21 22:07:03633}
634
635TEST_F(OutOfMemoryHandledTest, UncheckedCalloc) {
636 EXPECT_TRUE(base::UncheckedCalloc(1, kSafeMallocSize, &value_));
Ivan Kotenkova16212a52017-11-08 12:37:33637 EXPECT_TRUE(value_ != nullptr);
[email protected]29159eb2014-03-21 22:07:03638 const char* bytes = static_cast<const char*>(value_);
639 for (size_t i = 0; i < kSafeMallocSize; ++i)
640 EXPECT_EQ(0, bytes[i]);
641 free(value_);
642
643 EXPECT_TRUE(
644 base::UncheckedCalloc(kSafeCallocItems, kSafeCallocSize, &value_));
Ivan Kotenkova16212a52017-11-08 12:37:33645 EXPECT_TRUE(value_ != nullptr);
[email protected]29159eb2014-03-21 22:07:03646 bytes = static_cast<const char*>(value_);
647 for (size_t i = 0; i < (kSafeCallocItems * kSafeCallocSize); ++i)
648 EXPECT_EQ(0, bytes[i]);
649 free(value_);
650
651 EXPECT_FALSE(base::UncheckedCalloc(1, test_size_, &value_));
Ivan Kotenkova16212a52017-11-08 12:37:33652 EXPECT_TRUE(value_ == nullptr);
[email protected]29159eb2014-03-21 22:07:03653}
Benoit Lize2b7a7462020-08-03 09:20:53654
655#endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) || defined(OS_ANDROID)
656
657#endif // !defined(OS_OPENBSD) && BUILDFLAG(USE_ALLOCATOR_SHIM) &&
primiano227dbd32016-08-03 16:31:03658 // !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)