xref: /aosp_15_r20/external/pdfium/core/fxcrt/fx_memory_pa.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
1 // Copyright 2022 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 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #include "core/fxcrt/fx_memory.h"
8 
9 #include "base/allocator/partition_allocator/partition_alloc.h"
10 #include "core/fxcrt/fx_safe_types.h"
11 #include "third_party/base/no_destructor.h"
12 
13 #if !defined(PDF_USE_PARTITION_ALLOC)
14 #error "File compiled under wrong build option."
15 #endif
16 
17 namespace {
18 
19 constexpr partition_alloc::PartitionOptions kOptions = {};
20 
21 #ifndef V8_ENABLE_SANDBOX
GetArrayBufferPartitionAllocator()22 partition_alloc::PartitionAllocator& GetArrayBufferPartitionAllocator() {
23   static pdfium::base::NoDestructor<partition_alloc::PartitionAllocator>
24       s_array_buffer_allocator(kOptions);
25   return *s_array_buffer_allocator;
26 }
27 #endif  //  V8_ENABLE_SANDBOX
28 
GetGeneralPartitionAllocator()29 partition_alloc::PartitionAllocator& GetGeneralPartitionAllocator() {
30   static pdfium::base::NoDestructor<partition_alloc::PartitionAllocator>
31       s_general_allocator(kOptions);
32   return *s_general_allocator;
33 }
34 
GetStringPartitionAllocator()35 partition_alloc::PartitionAllocator& GetStringPartitionAllocator() {
36   static pdfium::base::NoDestructor<partition_alloc::PartitionAllocator>
37       s_string_allocator(kOptions);
38   return *s_string_allocator;
39 }
40 
41 }  // namespace
42 
43 namespace pdfium {
44 namespace internal {
45 
Alloc(size_t num_members,size_t member_size)46 void* Alloc(size_t num_members, size_t member_size) {
47   FX_SAFE_SIZE_T total = member_size;
48   total *= num_members;
49   if (!total.IsValid())
50     return nullptr;
51 
52   return GetGeneralPartitionAllocator().root()->AllocWithFlags(
53       partition_alloc::AllocFlags::kReturnNull, total.ValueOrDie(),
54       "GeneralPartition");
55 }
56 
Calloc(size_t num_members,size_t member_size)57 void* Calloc(size_t num_members, size_t member_size) {
58   FX_SAFE_SIZE_T total = member_size;
59   total *= num_members;
60   if (!total.IsValid())
61     return nullptr;
62 
63   return GetGeneralPartitionAllocator().root()->AllocWithFlags(
64       partition_alloc::AllocFlags::kReturnNull |
65           partition_alloc::AllocFlags::kZeroFill,
66       total.ValueOrDie(), "GeneralPartition");
67 }
68 
Realloc(void * ptr,size_t num_members,size_t member_size)69 void* Realloc(void* ptr, size_t num_members, size_t member_size) {
70   FX_SAFE_SIZE_T size = num_members;
71   size *= member_size;
72   if (!size.IsValid())
73     return nullptr;
74 
75   return GetGeneralPartitionAllocator().root()->ReallocWithFlags(
76       partition_alloc::AllocFlags::kReturnNull, ptr, size.ValueOrDie(),
77       "GeneralPartition");
78 }
79 
Dealloc(void * ptr)80 void Dealloc(void* ptr) {
81   // TODO(palmer): Removing this check exposes crashes when PDFium callers
82   // attempt to free |nullptr|. Although libc's |free| allows freeing |NULL|, no
83   // other Partition Alloc callers need this tolerant behavior. Additionally,
84   // checking for |nullptr| adds a branch to |PartitionFree|, and it's nice to
85   // not have to have that.
86   //
87   // So this check is hiding (what I consider to be) bugs, and we should try to
88   // fix them. https://bugs.chromium.org/p/pdfium/issues/detail?id=690
89   if (ptr) {
90     GetGeneralPartitionAllocator().root()->Free(ptr);
91   }
92 }
93 
StringAlloc(size_t num_members,size_t member_size)94 void* StringAlloc(size_t num_members, size_t member_size) {
95   FX_SAFE_SIZE_T total = member_size;
96   total *= num_members;
97   if (!total.IsValid())
98     return nullptr;
99 
100   return GetStringPartitionAllocator().root()->AllocWithFlags(
101       partition_alloc::AllocFlags::kReturnNull, total.ValueOrDie(),
102       "StringPartition");
103 }
104 
StringDealloc(void * ptr)105 void StringDealloc(void* ptr) {
106   // TODO(palmer): Removing this check exposes crashes when PDFium callers
107   // attempt to free |nullptr|. Although libc's |free| allows freeing |NULL|, no
108   // other Partition Alloc callers need this tolerant behavior. Additionally,
109   // checking for |nullptr| adds a branch to |PartitionFree|, and it's nice to
110   // not have to have that.
111   //
112   // So this check is hiding (what I consider to be) bugs, and we should try to
113   // fix them. https://bugs.chromium.org/p/pdfium/issues/detail?id=690
114   if (ptr) {
115     GetStringPartitionAllocator().root()->Free(ptr);
116   }
117 }
118 
119 }  // namespace internal
120 }  // namespace pdfium
121 
FX_InitializeMemoryAllocators()122 void FX_InitializeMemoryAllocators() {
123   static bool s_partition_allocators_initialized = false;
124   if (!s_partition_allocators_initialized) {
125     partition_alloc::PartitionAllocGlobalInit(FX_OutOfMemoryTerminate);
126     // These calls force the allocators to be created and initialized (via magic
127     // of static local variables).
128 #ifndef V8_ENABLE_SANDBOX
129     GetArrayBufferPartitionAllocator();
130 #endif  // V8_ENABLE_SANDBOX
131     GetGeneralPartitionAllocator();
132     GetStringPartitionAllocator();
133     s_partition_allocators_initialized = true;
134   }
135 }
136 
137 #ifndef V8_ENABLE_SANDBOX
FX_ArrayBufferAllocate(size_t length)138 void* FX_ArrayBufferAllocate(size_t length) {
139   return GetArrayBufferPartitionAllocator().root()->AllocWithFlags(
140       partition_alloc::AllocFlags::kZeroFill, length, "FXArrayBuffer");
141 }
142 
FX_ArrayBufferAllocateUninitialized(size_t length)143 void* FX_ArrayBufferAllocateUninitialized(size_t length) {
144   return GetArrayBufferPartitionAllocator().root()->Alloc(length,
145                                                           "FXArrayBuffer");
146 }
147 
FX_ArrayBufferFree(void * data)148 void FX_ArrayBufferFree(void* data) {
149   GetArrayBufferPartitionAllocator().root()->Free(data);
150 }
151 #endif  // V8_ENABLE_SANDBOX
152