Add FX_AllocUninit() and FX_AllocUninit2D().
Add functions that are similar to FX_Alloc() and FX_Alloc2D(), but do
not initialize the allocated memory. Use them in some places that
immediately writes into the allocated memory.
Bug: pdfium:1171
Change-Id: If5aac228d3f237aff3bc5cf96bb1af9d5443d5fe
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/68170
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp b/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp
index 62c3df5..faa62a2 100644
--- a/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp
+++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp
@@ -405,7 +405,7 @@
"q 1 0 0 1 0 0 cm 3.102 4.6700001 m 5.4500012 .28999999 "
"l 4.2399998 3.1499999 4.65 2.98 3.456 0.24 c 3.102 4.6700001 l h f Q\n";
size_t buf_len = FX_ArraySize(content);
- std::unique_ptr<uint8_t, FxFreeDeleter> buf(FX_Alloc(uint8_t, buf_len));
+ std::unique_ptr<uint8_t, FxFreeDeleter> buf(FX_AllocUninit(uint8_t, buf_len));
memcpy(buf.get(), content, buf_len);
auto pStream = pdfium::MakeRetain<CPDF_Stream>(std::move(buf), buf_len,
std::move(pDict));
diff --git a/core/fpdfapi/page/cpdf_image.cpp b/core/fpdfapi/page/cpdf_image.cpp
index 68703c4..3861e45 100644
--- a/core/fpdfapi/page/cpdf_image.cpp
+++ b/core/fpdfapi/page/cpdf_image.cpp
@@ -268,7 +268,7 @@
pMaskDict->SetNewFor<CPDF_Name>("ColorSpace", "DeviceGray");
pMaskDict->SetNewFor<CPDF_Number>("BitsPerComponent", 8);
if (pMaskBitmap->GetFormat() != FXDIB_1bppMask) {
- mask_buf.reset(FX_Alloc2D(uint8_t, maskHeight, maskWidth));
+ mask_buf.reset(FX_AllocUninit2D(uint8_t, maskHeight, maskWidth));
mask_size = maskHeight * maskWidth; // Safe since checked alloc returned.
for (int32_t a = 0; a < maskHeight; a++) {
memcpy(mask_buf.get() + a * maskWidth, pMaskBitmap->GetScanline(a),
diff --git a/core/fpdfapi/page/cpdf_streamparser.cpp b/core/fpdfapi/page/cpdf_streamparser.cpp
index aa8a27b..26857f4 100644
--- a/core/fpdfapi/page/cpdf_streamparser.cpp
+++ b/core/fpdfapi/page/cpdf_streamparser.cpp
@@ -170,7 +170,7 @@
uint32_t dwStreamSize;
if (decoder.IsEmpty()) {
dwOrigSize = std::min<uint32_t>(dwOrigSize, m_pBuf.size() - m_Pos);
- pData.reset(FX_Alloc(uint8_t, dwOrigSize));
+ pData.reset(FX_AllocUninit(uint8_t, dwOrigSize));
auto copy_span = m_pBuf.subspan(m_Pos, dwOrigSize);
memcpy(pData.get(), copy_span.data(), copy_span.size());
dwStreamSize = dwOrigSize;
@@ -200,7 +200,7 @@
dwStreamSize += m_Pos - dwPrevPos;
}
m_Pos = dwSavePos;
- pData.reset(FX_Alloc(uint8_t, dwStreamSize));
+ pData.reset(FX_AllocUninit(uint8_t, dwStreamSize));
auto copy_span = m_pBuf.subspan(m_Pos, dwStreamSize);
memcpy(pData.get(), copy_span.data(), copy_span.size());
m_Pos += dwStreamSize;
diff --git a/core/fpdfapi/parser/cpdf_object_unittest.cpp b/core/fpdfapi/parser/cpdf_object_unittest.cpp
index 8ad3104..08fdfeb 100644
--- a/core/fpdfapi/parser/cpdf_object_unittest.cpp
+++ b/core/fpdfapi/parser/cpdf_object_unittest.cpp
@@ -71,7 +71,8 @@
// Stream object.
const char content[] = "abcdefghijklmnopqrstuvwxyz";
size_t buf_len = FX_ArraySize(content);
- std::unique_ptr<uint8_t, FxFreeDeleter> buf(FX_Alloc(uint8_t, buf_len));
+ std::unique_ptr<uint8_t, FxFreeDeleter> buf(
+ FX_AllocUninit(uint8_t, buf_len));
memcpy(buf.get(), content, buf_len);
auto pNewDict = pdfium::MakeRetain<CPDF_Dictionary>();
m_StreamDictObj = pNewDict;
@@ -612,7 +613,7 @@
uint8_t content[] = "content: this is a stream";
size_t data_size = FX_ArraySize(content);
std::unique_ptr<uint8_t, FxFreeDeleter> data(
- FX_Alloc(uint8_t, data_size));
+ FX_AllocUninit(uint8_t, data_size));
memcpy(data.get(), content, data_size);
stream_vals[i] =
arr->AppendNew<CPDF_Stream>(std::move(data), data_size, vals[i]);
@@ -658,7 +659,8 @@
// The data buffer will be owned by stream object, so it needs to be
// dynamically allocated.
size_t buf_size = sizeof(data);
- std::unique_ptr<uint8_t, FxFreeDeleter> buf(FX_Alloc(uint8_t, buf_size));
+ std::unique_ptr<uint8_t, FxFreeDeleter> buf(
+ FX_AllocUninit(uint8_t, buf_size));
memcpy(buf.get(), data, buf_size);
CPDF_Stream* stream_val = arr->InsertNewAt<CPDF_Stream>(
13, std::move(buf), buf_size, stream_dict);
diff --git a/core/fpdfapi/parser/cpdf_stream.cpp b/core/fpdfapi/parser/cpdf_stream.cpp
index 4b5ef5c..8237338 100644
--- a/core/fpdfapi/parser/cpdf_stream.cpp
+++ b/core/fpdfapi/parser/cpdf_stream.cpp
@@ -130,7 +130,7 @@
void CPDF_Stream::SetData(pdfium::span<const uint8_t> pData) {
std::unique_ptr<uint8_t, FxFreeDeleter> data_copy;
if (!pData.empty()) {
- data_copy.reset(FX_Alloc(uint8_t, pData.size()));
+ data_copy.reset(FX_AllocUninit(uint8_t, pData.size()));
memcpy(data_copy.get(), pData.data(), pData.size());
}
TakeData(std::move(data_copy), pData.size());
diff --git a/core/fpdfapi/parser/cpdf_stream_acc.cpp b/core/fpdfapi/parser/cpdf_stream_acc.cpp
index 23c314f..ef16ffe 100644
--- a/core/fpdfapi/parser/cpdf_stream_acc.cpp
+++ b/core/fpdfapi/parser/cpdf_stream_acc.cpp
@@ -91,7 +91,7 @@
m_dwSize = 0;
return p;
}
- std::unique_ptr<uint8_t, FxFreeDeleter> p(FX_Alloc(uint8_t, m_dwSize));
+ std::unique_ptr<uint8_t, FxFreeDeleter> p(FX_AllocUninit(uint8_t, m_dwSize));
memcpy(p.get(), m_pData.Get(), m_dwSize);
return p;
}
diff --git a/core/fpdfapi/render/cpdf_docrenderdata_unittest.cpp b/core/fpdfapi/render/cpdf_docrenderdata_unittest.cpp
index bad221e..cd38bcc 100644
--- a/core/fpdfapi/render/cpdf_docrenderdata_unittest.cpp
+++ b/core/fpdfapi/render/cpdf_docrenderdata_unittest.cpp
@@ -89,7 +89,7 @@
static const char content[] = "1234";
size_t len = FX_ArraySize(content);
- std::unique_ptr<uint8_t, FxFreeDeleter> buf(FX_Alloc(uint8_t, len));
+ std::unique_ptr<uint8_t, FxFreeDeleter> buf(FX_AllocUninit(uint8_t, len));
memcpy(buf.get(), content, len);
return pdfium::MakeRetain<CPDF_Stream>(std::move(buf), len,
std::move(func_dict));
@@ -131,7 +131,7 @@
static const char content[] = "{ 360 mul sin 2 div }";
size_t len = FX_ArraySize(content);
- std::unique_ptr<uint8_t, FxFreeDeleter> buf(FX_Alloc(uint8_t, len));
+ std::unique_ptr<uint8_t, FxFreeDeleter> buf(FX_AllocUninit(uint8_t, len));
memcpy(buf.get(), content, len);
return pdfium::MakeRetain<CPDF_Stream>(std::move(buf), len,
std::move(func_dict));
@@ -151,7 +151,7 @@
static const char content[] = "garbage";
size_t len = FX_ArraySize(content);
- std::unique_ptr<uint8_t, FxFreeDeleter> buf(FX_Alloc(uint8_t, len));
+ std::unique_ptr<uint8_t, FxFreeDeleter> buf(FX_AllocUninit(uint8_t, len));
memcpy(buf.get(), content, len);
return pdfium::MakeRetain<CPDF_Stream>(std::move(buf), len,
std::move(func_dict));
diff --git a/core/fpdfdoc/cpdf_filespec_unittest.cpp b/core/fpdfdoc/cpdf_filespec_unittest.cpp
index a075c5e..daeee4e 100644
--- a/core/fpdfdoc/cpdf_filespec_unittest.cpp
+++ b/core/fpdfdoc/cpdf_filespec_unittest.cpp
@@ -210,7 +210,8 @@
// Set the file stream.
auto pDict = pdfium::MakeRetain<CPDF_Dictionary>();
size_t buf_len = strlen(streams[i]) + 1;
- std::unique_ptr<uint8_t, FxFreeDeleter> buf(FX_Alloc(uint8_t, buf_len));
+ std::unique_ptr<uint8_t, FxFreeDeleter> buf(
+ FX_AllocUninit(uint8_t, buf_len));
memcpy(buf.get(), streams[i], buf_len);
file_dict->SetNewFor<CPDF_Stream>(keys[i], std::move(buf), buf_len,
std::move(pDict));
@@ -247,7 +248,7 @@
CPDF_Dictionary* file_dict =
file_spec.GetObj()->AsDictionary()->GetDictFor("EF");
auto pDict = pdfium::MakeRetain<CPDF_Dictionary>();
- std::unique_ptr<uint8_t, FxFreeDeleter> buf(FX_Alloc(uint8_t, 6));
+ std::unique_ptr<uint8_t, FxFreeDeleter> buf(FX_AllocUninit(uint8_t, 6));
memcpy(buf.get(), "hello", 6);
file_dict->SetNewFor<CPDF_Stream>("UF", std::move(buf), 6,
std::move(pDict));
diff --git a/core/fxcodec/progressivedecoder.cpp b/core/fxcodec/progressivedecoder.cpp
index e948b39..73fdf2a 100644
--- a/core/fxcodec/progressivedecoder.cpp
+++ b/core/fxcodec/progressivedecoder.cpp
@@ -760,7 +760,7 @@
m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight);
m_pBmpContext = std::move(pBmpContext);
if (m_SrcPaletteNumber) {
- m_pSrcPalette.reset(FX_Alloc(FX_ARGB, m_SrcPaletteNumber));
+ m_pSrcPalette.reset(FX_AllocUninit(FX_ARGB, m_SrcPaletteNumber));
memcpy(m_pSrcPalette.get(), palette->data(),
m_SrcPaletteNumber * sizeof(FX_ARGB));
} else {
diff --git a/core/fxcodec/tiff/tiffmodule.cpp b/core/fxcodec/tiff/tiffmodule.cpp
index 179fca6..c1f4c7b 100644
--- a/core/fxcodec/tiff/tiffmodule.cpp
+++ b/core/fxcodec/tiff/tiffmodule.cpp
@@ -209,7 +209,7 @@
if (!buf)
return;
size_t size = strlen(buf);
- uint8_t* ptr = FX_Alloc(uint8_t, size + 1);
+ uint8_t* ptr = FX_AllocUninit(uint8_t, size + 1);
memcpy(ptr, buf, size);
ptr[size] = 0;
pAttr->m_Exif[tag] = ptr;
diff --git a/core/fxcrt/fx_memory.cpp b/core/fxcrt/fx_memory.cpp
index 9a9dd95..f2b47f0 100644
--- a/core/fxcrt/fx_memory.cpp
+++ b/core/fxcrt/fx_memory.cpp
@@ -73,6 +73,33 @@
namespace internal {
+void* Alloc(size_t num_members, size_t member_size) {
+ FX_SAFE_SIZE_T total = member_size;
+ total *= num_members;
+ if (!total.IsValid())
+ return nullptr;
+
+ constexpr int kFlags = pdfium::base::PartitionAllocReturnNull;
+ return pdfium::base::PartitionAllocGenericFlags(
+ GetGeneralPartitionAllocator().root(), kFlags, total.ValueOrDie(),
+ "GeneralPartition");
+}
+
+void* AllocOrDie(size_t num_members, size_t member_size) {
+ void* result = Alloc(num_members, member_size);
+ if (!result)
+ FX_OutOfMemoryTerminate(); // Never returns.
+
+ return result;
+}
+
+void* AllocOrDie2D(size_t w, size_t h, size_t member_size) {
+ if (w >= std::numeric_limits<size_t>::max() / h)
+ FX_OutOfMemoryTerminate(); // Never returns.
+
+ return AllocOrDie(w * h, member_size);
+}
+
void* Calloc(size_t num_members, size_t member_size) {
FX_SAFE_SIZE_T total = member_size;
total *= num_members;
@@ -99,7 +126,6 @@
}
void* CallocOrDie(size_t num_members, size_t member_size) {
- // TODO(tsepez): See if we can avoid the implicit memset(0).
void* result = Calloc(num_members, member_size);
if (!result)
FX_OutOfMemoryTerminate(); // Never returns.
diff --git a/core/fxcrt/fx_memory.h b/core/fxcrt/fx_memory.h
index d8f6661..63efd08 100644
--- a/core/fxcrt/fx_memory.h
+++ b/core/fxcrt/fx_memory.h
@@ -45,8 +45,19 @@
#define FX_TryRealloc(type, ptr, size) \
static_cast<type*>(internal::Realloc(ptr, size, sizeof(type)))
+// These never return nullptr, but return uninitialized memory.
+// TOOD(thestig): Add FX_TryAllocUninit() if there is a use case.
+#define FX_AllocUninit(type, size) \
+ static_cast<type*>(internal::AllocOrDie(size, sizeof(type)))
+#define FX_AllocUninit2D(type, w, h) \
+ static_cast<type*>(internal::AllocOrDie2D(w, h, sizeof(type)))
+
namespace internal {
+void* Alloc(size_t num_members, size_t member_size);
+void* AllocOrDie(size_t num_members, size_t member_size);
+void* AllocOrDie2D(size_t w, size_t h, size_t member_size);
+
void* Calloc(size_t num_members, size_t member_size);
void* Realloc(void* ptr, size_t num_members, size_t member_size);
void* CallocOrDie(size_t num_members, size_t member_size);
diff --git a/fpdfsdk/fpdf_attachment.cpp b/fpdfsdk/fpdf_attachment.cpp
index 7f55691..fcad33f 100644
--- a/fpdfsdk/fpdf_attachment.cpp
+++ b/fpdfsdk/fpdf_attachment.cpp
@@ -251,7 +251,7 @@
true);
// Create the file stream and have the filespec dictionary link to it.
- std::unique_ptr<uint8_t, FxFreeDeleter> stream(FX_Alloc(uint8_t, len));
+ std::unique_ptr<uint8_t, FxFreeDeleter> stream(FX_AllocUninit(uint8_t, len));
memcpy(stream.get(), contents, len);
CPDF_Stream* pFileStream = pDoc->NewIndirect<CPDF_Stream>(
std::move(stream), len, std::move(pFileStreamDict));
diff --git a/third_party/agg23/agg_array.h b/third_party/agg23/agg_array.h
index 8dcb0af..fba41a7 100644
--- a/third_party/agg23/agg_array.h
+++ b/third_party/agg23/agg_array.h
@@ -126,7 +126,7 @@
{
if(new_size > m_size) {
if(new_size > m_capacity) {
- T* data = FX_Alloc(T, new_size);
+ T* data = FX_AllocUninit(T, new_size);
memcpy(data, m_array, m_size * sizeof(T));
FX_Free(m_array);
m_array = data;
@@ -318,7 +318,7 @@
{
unsigned i;
for(i = 0; i < v.m_num_blocks; ++i) {
- m_blocks[i] = FX_Alloc(T, block_size);
+ m_blocks[i] = FX_AllocUninit(T, block_size);
memcpy(m_blocks[i], v.m_blocks[i], block_size * sizeof(T));
}
}