blob: cf8f481c8295e44dd2d4498df7b7a4b1aeb78239 [file] [log] [blame]
K. Moon832a6942022-10-31 20:11:31 +00001// Copyright 2015 The PDFium Authors
Tom Sepezed099be2015-05-15 16:30:52 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Tom Sepeza9deea92017-04-25 10:37:47 -07005#include "core/fxcrt/fx_memory.h"
6
Tom Sepezed099be2015-05-15 16:30:52 -07007#include <limits>
Tom Sepez45e5d5e2023-08-01 01:48:40 +00008#include <memory>
Tom Sepezed099be2015-05-15 16:30:52 -07009
Lei Zhangbc106482019-05-30 23:55:19 +000010#include "build/build_config.h"
Tom Sepez27863902024-03-28 21:53:49 +000011#include "core/fxcrt/compiler_specific.h"
Tom Sepezed099be2015-05-15 16:30:52 -070012#include "testing/gtest/include/gtest/gtest.h"
Tom Sepezed099be2015-05-15 16:30:52 -070013
Tom Sepez45e5d5e2023-08-01 01:48:40 +000014#if defined(PDF_USE_PARTITION_ALLOC)
Arthur Sonzogni34768112023-10-06 16:53:00 +000015#include "partition_alloc/partition_address_space.h"
Arthur Sonzogni159bccb2023-08-29 08:59:38 +000016#endif
Tom Sepez45e5d5e2023-08-01 01:48:40 +000017
Tom Sepezed099be2015-05-15 16:30:52 -070018namespace {
19
Lei Zhangd6f9fe02022-11-03 17:41:01 +000020constexpr size_t kMaxByteAlloc = std::numeric_limits<size_t>::max();
21constexpr size_t kMaxIntAlloc = kMaxByteAlloc / sizeof(int);
22constexpr size_t kOverflowIntAlloc = kMaxIntAlloc + 100;
23constexpr size_t kWidth = 640;
24constexpr size_t kOverflowIntAlloc2D = kMaxIntAlloc / kWidth + 10;
25constexpr size_t kCloseToMaxIntAlloc = kMaxIntAlloc - 100;
26constexpr size_t kCloseToMaxByteAlloc = kMaxByteAlloc - 100;
Tom Sepezed099be2015-05-15 16:30:52 -070027
28} // namespace
29
Tom Sepez57eea9a2019-11-19 21:37:47 +000030TEST(fxcrt, FX_AllocZero) {
31 uint8_t* ptr = FX_Alloc(uint8_t, 0);
Tom Sepezaf352392019-11-21 18:48:08 +000032 uint8_t* ptr2 = FX_Alloc(uint8_t, 0);
Lei Zhang144da5d2019-12-13 17:39:08 +000033 EXPECT_TRUE(ptr); // Malloc(0) is distinguishable from OOM.
Tom Sepezaf352392019-11-21 18:48:08 +000034 EXPECT_NE(ptr, ptr2); // Each malloc(0) is distinguishable.
35 FX_Free(ptr2);
Tom Sepez57eea9a2019-11-19 21:37:47 +000036 FX_Free(ptr);
37}
38
Lei Zhang204d96e2022-11-02 21:39:24 +000039TEST(fxcrt, FXAllocOOM) {
40 EXPECT_DEATH_IF_SUPPORTED((void)FX_Alloc(int, kCloseToMaxIntAlloc), "");
Tom Sepezed099be2015-05-15 16:30:52 -070041
Nico Weber9d8ec5a2015-08-04 13:00:21 -070042 int* ptr = FX_Alloc(int, 1);
43 EXPECT_TRUE(ptr);
Lei Zhang204d96e2022-11-02 21:39:24 +000044 EXPECT_DEATH_IF_SUPPORTED((void)FX_Realloc(int, ptr, kCloseToMaxIntAlloc),
45 "");
Nico Weber9d8ec5a2015-08-04 13:00:21 -070046 FX_Free(ptr);
Tom Sepezed099be2015-05-15 16:30:52 -070047}
48
49TEST(fxcrt, FX_AllocOverflow) {
weili14f5aeb2016-04-22 19:18:31 -070050 // |ptr| needs to be defined and used to avoid Clang optimizes away the
51 // FX_Alloc() statement overzealously for optimized builds.
52 int* ptr = nullptr;
53 EXPECT_DEATH_IF_SUPPORTED(ptr = FX_Alloc(int, kOverflowIntAlloc), "") << ptr;
Tom Sepezed099be2015-05-15 16:30:52 -070054
weili14f5aeb2016-04-22 19:18:31 -070055 ptr = FX_Alloc(int, 1);
Nico Weber9d8ec5a2015-08-04 13:00:21 -070056 EXPECT_TRUE(ptr);
Ryan Harrison6cec70a2018-06-05 14:06:10 +000057 EXPECT_DEATH_IF_SUPPORTED((void)FX_Realloc(int, ptr, kOverflowIntAlloc), "");
Nico Weber9d8ec5a2015-08-04 13:00:21 -070058 FX_Free(ptr);
Tom Sepezed099be2015-05-15 16:30:52 -070059}
60
Tom Sepez038cd082015-05-18 14:29:22 -070061TEST(fxcrt, FX_AllocOverflow2D) {
weili14f5aeb2016-04-22 19:18:31 -070062 // |ptr| needs to be defined and used to avoid Clang optimizes away the
63 // FX_Alloc() statement overzealously for optimized builds.
64 int* ptr = nullptr;
65 EXPECT_DEATH_IF_SUPPORTED(ptr = FX_Alloc2D(int, kWidth, kOverflowIntAlloc2D),
66 "")
67 << ptr;
Tom Sepez038cd082015-05-18 14:29:22 -070068}
69
Lei Zhang204d96e2022-11-02 21:39:24 +000070TEST(fxcrt, FXTryAllocOOM) {
71 EXPECT_FALSE(FX_TryAlloc(int, kCloseToMaxIntAlloc));
Tom Sepezed099be2015-05-15 16:30:52 -070072
Nico Weber9d8ec5a2015-08-04 13:00:21 -070073 int* ptr = FX_Alloc(int, 1);
74 EXPECT_TRUE(ptr);
Lei Zhang204d96e2022-11-02 21:39:24 +000075 EXPECT_FALSE(FX_TryRealloc(int, ptr, kCloseToMaxIntAlloc));
Nico Weber9d8ec5a2015-08-04 13:00:21 -070076 FX_Free(ptr);
Tom Sepezed099be2015-05-15 16:30:52 -070077}
78
Lei Zhangbc106482019-05-30 23:55:19 +000079#if !defined(COMPILER_GCC)
Tom Sepezed099be2015-05-15 16:30:52 -070080TEST(fxcrt, FX_TryAllocOverflow) {
weili14f5aeb2016-04-22 19:18:31 -070081 // |ptr| needs to be defined and used to avoid Clang optimizes away the
82 // calloc() statement overzealously for optimized builds.
83 int* ptr = (int*)calloc(sizeof(int), kOverflowIntAlloc);
84 EXPECT_FALSE(ptr) << ptr;
Tom Sepezed099be2015-05-15 16:30:52 -070085
weili14f5aeb2016-04-22 19:18:31 -070086 ptr = FX_Alloc(int, 1);
Nico Weber9d8ec5a2015-08-04 13:00:21 -070087 EXPECT_TRUE(ptr);
Tom Sepez26b28672018-09-13 18:18:44 +000088 *ptr = 1492; // Arbitrary sentinel.
Nico Weber9d8ec5a2015-08-04 13:00:21 -070089 EXPECT_FALSE(FX_TryRealloc(int, ptr, kOverflowIntAlloc));
Tom Sepez26b28672018-09-13 18:18:44 +000090 EXPECT_EQ(1492, *ptr);
Nico Weber9d8ec5a2015-08-04 13:00:21 -070091 FX_Free(ptr);
Tom Sepezed099be2015-05-15 16:30:52 -070092}
Lei Zhanga41801e2018-08-23 21:59:33 +000093#endif
Tom Sepezed099be2015-05-15 16:30:52 -070094
Lei Zhang204d96e2022-11-02 21:39:24 +000095TEST(fxcrt, FXMEMDefaultOOM) {
96 EXPECT_FALSE(FXMEM_DefaultAlloc(kCloseToMaxByteAlloc));
Tom Sepezed099be2015-05-15 16:30:52 -070097
Lei Zhangb810da22017-11-03 22:18:18 +000098 void* ptr = FXMEM_DefaultAlloc(1);
Nico Weber9d8ec5a2015-08-04 13:00:21 -070099 EXPECT_TRUE(ptr);
Lei Zhang204d96e2022-11-02 21:39:24 +0000100 EXPECT_FALSE(FXMEM_DefaultRealloc(ptr, kCloseToMaxByteAlloc));
Lei Zhangb810da22017-11-03 22:18:18 +0000101 FXMEM_DefaultFree(ptr);
Tom Sepezed099be2015-05-15 16:30:52 -0700102}
Tom Sepez30dc6aa2018-09-25 20:06:50 +0000103
Lei Zhanga7430c12020-04-01 20:57:14 +0000104TEST(fxcrt, AllocZeroesMemory) {
105 uint8_t* ptr = FX_Alloc(uint8_t, 32);
106 ASSERT_TRUE(ptr);
Tom Sepez27863902024-03-28 21:53:49 +0000107 for (size_t i = 0; i < 32; ++i) {
Tom Sepez22245502024-06-13 00:28:00 +0000108 // SAFETY: required for testing, length and loop bounds 32.
109 EXPECT_EQ(0, UNSAFE_BUFFERS(ptr[i]));
Tom Sepez27863902024-03-28 21:53:49 +0000110 }
Lei Zhanga7430c12020-04-01 20:57:14 +0000111 FX_Free(ptr);
112}
113
Tom Sepez30dc6aa2018-09-25 20:06:50 +0000114TEST(fxcrt, FXAlign) {
115 static_assert(std::numeric_limits<size_t>::max() % 2 == 1,
116 "numeric limit must be odd for this test");
117
118 size_t s0 = 0;
119 size_t s1 = 1;
120 size_t s2 = 2;
121 size_t sbig = std::numeric_limits<size_t>::max() - 2;
122 EXPECT_EQ(0u, FxAlignToBoundary<2>(s0));
123 EXPECT_EQ(2u, FxAlignToBoundary<2>(s1));
124 EXPECT_EQ(2u, FxAlignToBoundary<2>(s2));
125 EXPECT_EQ(std::numeric_limits<size_t>::max() - 1, FxAlignToBoundary<2>(sbig));
126
127 int i0 = 0;
128 int i511 = 511;
129 int i512 = 512;
130 int ineg = -513;
131 EXPECT_EQ(0, FxAlignToBoundary<512>(i0));
132 EXPECT_EQ(512, FxAlignToBoundary<512>(i511));
133 EXPECT_EQ(512, FxAlignToBoundary<512>(i512));
134 EXPECT_EQ(-512, FxAlignToBoundary<512>(ineg));
135}
Tom Sepez45e5d5e2023-08-01 01:48:40 +0000136
137#if defined(PDF_USE_PARTITION_ALLOC)
Arthur Sonzogni151ec022024-05-23 16:32:24 +0000138#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && \
139 PA_BUILDFLAG(HAS_64_BIT_POINTERS)
Tom Sepez45e5d5e2023-08-01 01:48:40 +0000140TEST(FxMemory, NewOperatorResultIsPA) {
141 auto obj = std::make_unique<double>(4.0);
142 EXPECT_TRUE(partition_alloc::IsManagedByPartitionAlloc(
143 reinterpret_cast<uintptr_t>(obj.get())));
Arthur Sonzogni151ec022024-05-23 16:32:24 +0000144#if PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
Tom Sepez45e5d5e2023-08-01 01:48:40 +0000145 EXPECT_TRUE(partition_alloc::IsManagedByPartitionAllocBRPPool(
146 reinterpret_cast<uintptr_t>(obj.get())));
Arthur Sonzogni151ec022024-05-23 16:32:24 +0000147#endif // PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
Tom Sepez45e5d5e2023-08-01 01:48:40 +0000148}
149
150TEST(FxMemory, MallocResultIsPA) {
151 void* obj = malloc(16);
152 EXPECT_TRUE(partition_alloc::IsManagedByPartitionAlloc(
153 reinterpret_cast<uintptr_t>(obj)));
Arthur Sonzogni151ec022024-05-23 16:32:24 +0000154#if PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
Tom Sepez45e5d5e2023-08-01 01:48:40 +0000155 EXPECT_TRUE(partition_alloc::IsManagedByPartitionAllocBRPPool(
156 reinterpret_cast<uintptr_t>(obj)));
Arthur Sonzogni151ec022024-05-23 16:32:24 +0000157#endif // PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
Tom Sepez45e5d5e2023-08-01 01:48:40 +0000158 free(obj);
159}
160
161TEST(FxMemory, StackObjectIsNotPA) {
162 int x = 3;
163 EXPECT_FALSE(partition_alloc::IsManagedByPartitionAlloc(
164 reinterpret_cast<uintptr_t>(&x)));
Arthur Sonzogni151ec022024-05-23 16:32:24 +0000165#if PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
Tom Sepez45e5d5e2023-08-01 01:48:40 +0000166 EXPECT_FALSE(partition_alloc::IsManagedByPartitionAllocBRPPool(
167 reinterpret_cast<uintptr_t>(&x)));
Arthur Sonzogni151ec022024-05-23 16:32:24 +0000168#endif // PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
Tom Sepez45e5d5e2023-08-01 01:48:40 +0000169}
Arthur Sonzogni151ec022024-05-23 16:32:24 +0000170#endif // PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) &&
171 // PA_BUILDFLAG(HAS_64_BIT_POINTERS)
Tom Sepez45e5d5e2023-08-01 01:48:40 +0000172#endif // defined(PDF_USE_PARTITION_ALLOC)