• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 The PDFium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "core/fxcrt/fx_memory.h"
6 
7 #include <limits>
8 #include <memory>
9 
10 #include "build/build_config.h"
11 #include "core/fxcrt/compiler_specific.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 
14 #if defined(PDF_USE_PARTITION_ALLOC)
15 #include "partition_alloc/partition_address_space.h"
16 #endif
17 
18 namespace {
19 
20 constexpr size_t kMaxByteAlloc = std::numeric_limits<size_t>::max();
21 constexpr size_t kMaxIntAlloc = kMaxByteAlloc / sizeof(int);
22 constexpr size_t kOverflowIntAlloc = kMaxIntAlloc + 100;
23 constexpr size_t kWidth = 640;
24 constexpr size_t kOverflowIntAlloc2D = kMaxIntAlloc / kWidth + 10;
25 constexpr size_t kCloseToMaxIntAlloc = kMaxIntAlloc - 100;
26 constexpr size_t kCloseToMaxByteAlloc = kMaxByteAlloc - 100;
27 
28 }  // namespace
29 
TEST(fxcrt,FXAllocZero)30 TEST(fxcrt, FXAllocZero) {
31   uint8_t* ptr = FX_Alloc(uint8_t, 0);
32   uint8_t* ptr2 = FX_Alloc(uint8_t, 0);
33   EXPECT_TRUE(ptr);      // Malloc(0) is distinguishable from OOM.
34   EXPECT_NE(ptr, ptr2);  // Each malloc(0) is distinguishable.
35   FX_Free(ptr2);
36   FX_Free(ptr);
37 }
38 
TEST(fxcrt,FXAllocOOM)39 TEST(fxcrt, FXAllocOOM) {
40   EXPECT_DEATH_IF_SUPPORTED((void)FX_Alloc(int, kCloseToMaxIntAlloc), "");
41 
42   int* ptr = FX_Alloc(int, 1);
43   EXPECT_TRUE(ptr);
44   EXPECT_DEATH_IF_SUPPORTED((void)FX_Realloc(int, ptr, kCloseToMaxIntAlloc),
45                             "");
46   FX_Free(ptr);
47 }
48 
TEST(fxcrt,FXAllocOverflow)49 TEST(fxcrt, FXAllocOverflow) {
50   // |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;
54 
55   ptr = FX_Alloc(int, 1);
56   EXPECT_TRUE(ptr);
57   EXPECT_DEATH_IF_SUPPORTED((void)FX_Realloc(int, ptr, kOverflowIntAlloc), "");
58   FX_Free(ptr);
59 }
60 
TEST(fxcrt,FXAllocOverflow2D)61 TEST(fxcrt, FXAllocOverflow2D) {
62   // |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;
68 }
69 
TEST(fxcrt,FXTryAllocOOM)70 TEST(fxcrt, FXTryAllocOOM) {
71   EXPECT_FALSE(FX_TryAlloc(int, kCloseToMaxIntAlloc));
72 
73   int* ptr = FX_Alloc(int, 1);
74   EXPECT_TRUE(ptr);
75   EXPECT_FALSE(FX_TryRealloc(int, ptr, kCloseToMaxIntAlloc));
76   FX_Free(ptr);
77 }
78 
TEST(fxcrt,FXTryAllocUninit)79 TEST(fxcrt, FXTryAllocUninit) {
80   int* ptr = FX_TryAllocUninit(int, 4);
81   EXPECT_TRUE(ptr);
82   FX_Free(ptr);
83 
84   ptr = FX_TryAllocUninit2D(int, 4, 4);
85   EXPECT_TRUE(ptr);
86   FX_Free(ptr);
87 }
88 
TEST(fxcrt,FXTryAllocUninitOOM)89 TEST(fxcrt, FXTryAllocUninitOOM) {
90   EXPECT_FALSE(FX_TryAllocUninit(int, kCloseToMaxIntAlloc));
91   EXPECT_FALSE(FX_TryAllocUninit2D(int, kWidth, kOverflowIntAlloc2D));
92 }
93 
94 #if !defined(COMPILER_GCC)
TEST(fxcrt,FXTryAllocOverflow)95 TEST(fxcrt, FXTryAllocOverflow) {
96   // |ptr| needs to be defined and used to avoid Clang optimizes away the
97   // calloc() statement overzealously for optimized builds.
98   int* ptr = (int*)calloc(sizeof(int), kOverflowIntAlloc);
99   EXPECT_FALSE(ptr) << ptr;
100 
101   ptr = FX_Alloc(int, 1);
102   EXPECT_TRUE(ptr);
103   *ptr = 1492;  // Arbitrary sentinel.
104   EXPECT_FALSE(FX_TryRealloc(int, ptr, kOverflowIntAlloc));
105   EXPECT_EQ(1492, *ptr);
106   FX_Free(ptr);
107 }
108 #endif
109 
TEST(fxcrt,FXMEMDefaultOOM)110 TEST(fxcrt, FXMEMDefaultOOM) {
111   EXPECT_FALSE(FXMEM_DefaultAlloc(kCloseToMaxByteAlloc));
112 
113   void* ptr = FXMEM_DefaultAlloc(1);
114   EXPECT_TRUE(ptr);
115   EXPECT_FALSE(FXMEM_DefaultRealloc(ptr, kCloseToMaxByteAlloc));
116   FXMEM_DefaultFree(ptr);
117 }
118 
TEST(fxcrt,AllocZeroesMemory)119 TEST(fxcrt, AllocZeroesMemory) {
120   uint8_t* ptr = FX_Alloc(uint8_t, 32);
121   ASSERT_TRUE(ptr);
122   for (size_t i = 0; i < 32; ++i) {
123     // SAFETY: required for testing, length and loop bounds 32.
124     EXPECT_EQ(0, UNSAFE_BUFFERS(ptr[i]));
125   }
126   FX_Free(ptr);
127 }
128 
TEST(fxcrt,FXAlign)129 TEST(fxcrt, FXAlign) {
130   static_assert(std::numeric_limits<size_t>::max() % 2 == 1,
131                 "numeric limit must be odd for this test");
132 
133   size_t s0 = 0;
134   size_t s1 = 1;
135   size_t s2 = 2;
136   size_t sbig = std::numeric_limits<size_t>::max() - 2;
137   EXPECT_EQ(0u, FxAlignToBoundary<2>(s0));
138   EXPECT_EQ(2u, FxAlignToBoundary<2>(s1));
139   EXPECT_EQ(2u, FxAlignToBoundary<2>(s2));
140   EXPECT_EQ(std::numeric_limits<size_t>::max() - 1, FxAlignToBoundary<2>(sbig));
141 
142   int i0 = 0;
143   int i511 = 511;
144   int i512 = 512;
145   int ineg = -513;
146   EXPECT_EQ(0, FxAlignToBoundary<512>(i0));
147   EXPECT_EQ(512, FxAlignToBoundary<512>(i511));
148   EXPECT_EQ(512, FxAlignToBoundary<512>(i512));
149   EXPECT_EQ(-512, FxAlignToBoundary<512>(ineg));
150 }
151 
152 #if defined(PDF_USE_PARTITION_ALLOC)
153 #if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && \
154     PA_BUILDFLAG(HAS_64_BIT_POINTERS)
TEST(FxMemory,NewOperatorResultIsPA)155 TEST(FxMemory, NewOperatorResultIsPA) {
156   auto obj = std::make_unique<double>(4.0);
157   EXPECT_TRUE(partition_alloc::IsManagedByPartitionAlloc(
158       reinterpret_cast<uintptr_t>(obj.get())));
159 #if PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
160   EXPECT_TRUE(partition_alloc::IsManagedByPartitionAllocBRPPool(
161       reinterpret_cast<uintptr_t>(obj.get())));
162 #endif  // PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
163 }
164 
TEST(FxMemory,MallocResultIsPA)165 TEST(FxMemory, MallocResultIsPA) {
166   void* obj = malloc(16);
167   EXPECT_TRUE(partition_alloc::IsManagedByPartitionAlloc(
168       reinterpret_cast<uintptr_t>(obj)));
169 #if PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
170   EXPECT_TRUE(partition_alloc::IsManagedByPartitionAllocBRPPool(
171       reinterpret_cast<uintptr_t>(obj)));
172 #endif  // PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
173   free(obj);
174 }
175 
TEST(FxMemory,StackObjectIsNotPA)176 TEST(FxMemory, StackObjectIsNotPA) {
177   int x = 3;
178   EXPECT_FALSE(partition_alloc::IsManagedByPartitionAlloc(
179       reinterpret_cast<uintptr_t>(&x)));
180 #if PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
181   EXPECT_FALSE(partition_alloc::IsManagedByPartitionAllocBRPPool(
182       reinterpret_cast<uintptr_t>(&x)));
183 #endif  // PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
184 }
185 #endif  // PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) &&
186         // PA_BUILDFLAG(HAS_64_BIT_POINTERS)
187 #endif  // defined(PDF_USE_PARTITION_ALLOC)
188