Add fxcrt::Fill()
This is replacement for C++20 std::ranges:fill(), which itself is a
replacement for memset() in many cases. These should mass convert
to std::ranges::fill() once C++20 becomes available.
Avoid future unsafe_buffers annotations.
-- Use a better pattern than 0u to test non-modification.
Change-Id: I37891a721d61364a7af523512ae45b076a78d26a
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/118910
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Thomas Sepez <tsepez@google.com>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fdrm/fx_crypt_sha.cpp b/core/fdrm/fx_crypt_sha.cpp
index dbfd015..9c2bc96 100644
--- a/core/fdrm/fx_crypt_sha.cpp
+++ b/core/fdrm/fx_crypt_sha.cpp
@@ -10,6 +10,7 @@
#endif
#include "core/fdrm/fx_crypt.h"
+#include "core/fxcrt/stl_util.h"
#include <string.h>
@@ -445,7 +446,7 @@
context->state[5] = 0x9B05688C;
context->state[6] = 0x1F83D9AB;
context->state[7] = 0x5BE0CD19;
- memset(context->buffer, 0, sizeof(context->buffer));
+ fxcrt::Fill(context->buffer, 0);
}
void CRYPT_SHA256Update(CRYPT_sha2_context* context,
@@ -510,7 +511,7 @@
context->state[5] = 0x8eb44a8768581511ULL;
context->state[6] = 0xdb0c2e0d64f98fa7ULL;
context->state[7] = 0x47b5481dbefa4fa4ULL;
- memset(context->buffer, 0, sizeof(context->buffer));
+ fxcrt::Fill(context->buffer, 0);
}
void CRYPT_SHA384Update(CRYPT_sha2_context* context,
@@ -574,7 +575,7 @@
context->state[5] = 0x9b05688c2b3e6c1fULL;
context->state[6] = 0x1f83d9abfb41bd6bULL;
context->state[7] = 0x5be0cd19137e2179ULL;
- memset(context->buffer, 0, sizeof(context->buffer));
+ fxcrt::Fill(context->buffer, 0);
}
void CRYPT_SHA512Update(CRYPT_sha2_context* context,
diff --git a/core/fpdfapi/page/cpdf_colorspace_unittest.cpp b/core/fpdfapi/page/cpdf_colorspace_unittest.cpp
index 9cedbd1..4e60207 100644
--- a/core/fpdfapi/page/cpdf_colorspace_unittest.cpp
+++ b/core/fpdfapi/page/cpdf_colorspace_unittest.cpp
@@ -10,9 +10,9 @@
#include "core/fpdfapi/page/cpdf_colorspace.h"
#include <stdint.h>
-#include <string.h>
#include "core/fxcrt/retain_ptr.h"
+#include "core/fxcrt/stl_util.h"
#include "testing/gtest/include/gtest/gtest.h"
TEST(CPDF_CalGray, TranslateImageLine) {
@@ -23,7 +23,7 @@
ASSERT_TRUE(pCal);
uint8_t dst[12];
- memset(dst, 0xbd, sizeof(dst));
+ fxcrt::Fill(dst, 0xbd);
// `bTransMask` only applies to CYMK colorspaces.
pCal->TranslateImageLine(dst, kSrc, 4, 4, 1, /*bTransMask=*/false);
for (size_t i = 0; i < 12; ++i)
@@ -39,7 +39,7 @@
ASSERT_TRUE(pCal);
uint8_t dst[12];
- memset(dst, 0xbd, sizeof(dst));
+ fxcrt::Fill(dst, 0xbd);
// `bTransMask` only applies to CYMK colorspaces.
pCal->TranslateImageLine(dst, kSrc, 4, 4, 1, /*bTransMask=*/false);
for (size_t i = 0; i < 12; ++i)
diff --git a/core/fpdfapi/parser/cpdf_seekablemultistream_unittest.cpp b/core/fpdfapi/parser/cpdf_seekablemultistream_unittest.cpp
index 3a62f13..fa36d39 100644
--- a/core/fpdfapi/parser/cpdf_seekablemultistream_unittest.cpp
+++ b/core/fpdfapi/parser/cpdf_seekablemultistream_unittest.cpp
@@ -9,6 +9,7 @@
#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fpdfapi/parser/cpdf_stream.h"
+#include "core/fxcrt/stl_util.h"
#include "testing/gtest/include/gtest/gtest.h"
TEST(CPDFSeekableMultiStreamTest, NoStreams) {
@@ -17,7 +18,7 @@
pdfium::MakeRetain<CPDF_SeekableMultiStream>(std::move(streams));
uint8_t output_buffer[16];
- memset(output_buffer, 0xbd, sizeof(output_buffer));
+ fxcrt::Fill(output_buffer, 0xbd);
EXPECT_FALSE(fileread->ReadBlockAtOffset(
pdfium::make_span(output_buffer).first(0u), 0));
EXPECT_EQ(0xbd, output_buffer[0]);
@@ -32,7 +33,7 @@
pdfium::MakeRetain<CPDF_SeekableMultiStream>(std::move(streams));
uint8_t output_buffer[16];
- memset(output_buffer, 0xbd, sizeof(output_buffer));
+ fxcrt::Fill(output_buffer, 0xbd);
EXPECT_FALSE(fileread->ReadBlockAtOffset(
pdfium::make_span(output_buffer).first(0u), 0));
EXPECT_EQ(0xbd, output_buffer[0]);
@@ -59,33 +60,33 @@
pdfium::MakeRetain<CPDF_SeekableMultiStream>(std::move(streams));
uint8_t output_buffer[16];
- memset(output_buffer, 0xbd, sizeof(output_buffer));
+ fxcrt::Fill(output_buffer, 0xbd);
EXPECT_TRUE(fileread->ReadBlockAtOffset(
pdfium::make_span(output_buffer).first(0u), 0));
EXPECT_EQ(0xbd, output_buffer[0]);
- memset(output_buffer, 0xbd, sizeof(output_buffer));
+ fxcrt::Fill(output_buffer, 0xbd);
EXPECT_TRUE(fileread->ReadBlockAtOffset(
pdfium::make_span(output_buffer).first(0u), 1));
EXPECT_EQ(0xbd, output_buffer[0]);
- memset(output_buffer, 0xbd, sizeof(output_buffer));
+ fxcrt::Fill(output_buffer, 0xbd);
EXPECT_TRUE(fileread->ReadBlockAtOffset(
pdfium::make_span(output_buffer).first(1u), 0));
EXPECT_EQ(0, memcmp(output_buffer, "o", 1));
EXPECT_EQ(0xbd, output_buffer[1]);
- memset(output_buffer, 0xbd, sizeof(output_buffer));
+ fxcrt::Fill(output_buffer, 0xbd);
EXPECT_TRUE(fileread->ReadBlockAtOffset(output_buffer, 0));
EXPECT_EQ(0, memcmp(output_buffer, "one two three!!!", 16));
- memset(output_buffer, 0xbd, sizeof(output_buffer));
+ fxcrt::Fill(output_buffer, 0xbd);
EXPECT_TRUE(fileread->ReadBlockAtOffset(
pdfium::make_span(output_buffer).first(10u), 2));
EXPECT_EQ(0, memcmp(output_buffer, "e two thre", 10));
EXPECT_EQ(0xbd, output_buffer[11]);
- memset(output_buffer, 0xbd, sizeof(output_buffer));
+ fxcrt::Fill(output_buffer, 0xbd);
EXPECT_FALSE(fileread->ReadBlockAtOffset(output_buffer, 1));
EXPECT_EQ(0, memcmp(output_buffer, "ne two three!!!", 15));
EXPECT_EQ(0xbd, output_buffer[15]);
diff --git a/core/fxcodec/gif/lzw_decompressor.cpp b/core/fxcodec/gif/lzw_decompressor.cpp
index 3b82c8c..db46759 100644
--- a/core/fxcodec/gif/lzw_decompressor.cpp
+++ b/core/fxcodec/gif/lzw_decompressor.cpp
@@ -15,10 +15,12 @@
#include <algorithm>
#include <memory>
+#include <type_traits>
#include <utility>
#include "core/fxcrt/fx_safe_types.h"
#include "core/fxcrt/ptr_util.h"
+#include "core/fxcrt/stl_util.h"
namespace fxcodec {
@@ -144,9 +146,11 @@
code_size_cur_ = code_size_ + 1;
code_next_ = code_end_ + 1;
code_old_ = static_cast<uint16_t>(-1);
- memset(code_table_, 0, sizeof(code_table_));
- for (uint16_t i = 0; i < code_clear_; i++)
+ fxcrt::Fill(code_table_, CodeEntry{}); // Aggregate initialization.
+ static_assert(std::is_aggregate_v<CodeEntry>);
+ for (uint16_t i = 0; i < code_clear_; i++) {
code_table_[i].suffix = static_cast<uint8_t>(i);
+ }
decompressed_.resize(code_next_ - code_clear_ + 1);
decompressed_next_ = 0;
}
diff --git a/core/fxcodec/gif/lzw_decompressor_unittest.cpp b/core/fxcodec/gif/lzw_decompressor_unittest.cpp
index 7d0cde9..6b6ef5f 100644
--- a/core/fxcodec/gif/lzw_decompressor_unittest.cpp
+++ b/core/fxcodec/gif/lzw_decompressor_unittest.cpp
@@ -15,6 +15,7 @@
#include <iterator>
#include "core/fxcrt/data_vector.h"
+#include "core/fxcrt/stl_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -38,15 +39,15 @@
*decompressed = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
*(decompressor->DecompressedNextForTest()) = decompressed->size();
uint8_t dest_buf[20];
- memset(dest_buf, static_cast<uint8_t>(-1), sizeof(dest_buf));
-
+ fxcrt::Fill(dest_buf, 0xff);
EXPECT_EQ(0u, decompressor->ExtractDataForTest(dest_buf, 0));
- for (size_t i = 0; i < std::size(dest_buf); ++i)
+ for (size_t i = 0; i < std::size(dest_buf); ++i) {
EXPECT_EQ(static_cast<uint8_t>(-1), dest_buf[i]);
-
+ }
EXPECT_EQ(10u, *(decompressor->DecompressedNextForTest()));
- for (size_t i = 0; i < *(decompressor->DecompressedNextForTest()); ++i)
+ for (size_t i = 0; i < *(decompressor->DecompressedNextForTest()); ++i) {
EXPECT_EQ(i, (*decompressed)[i]);
+ }
}
// Check that less than decompressed size only gets the expected number
@@ -55,18 +56,19 @@
*decompressed = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
*(decompressor->DecompressedNextForTest()) = decompressed->size();
uint8_t dest_buf[20];
- memset(dest_buf, static_cast<uint8_t>(-1), sizeof(dest_buf));
-
+ fxcrt::Fill(dest_buf, 0xff);
EXPECT_EQ(5u, decompressor->ExtractDataForTest(dest_buf, 5));
size_t i = 0;
- for (; i < 5; ++i)
+ for (; i < 5; ++i) {
EXPECT_EQ(9 - i, dest_buf[i]);
- for (; i < std::size(dest_buf); ++i)
+ }
+ for (; i < std::size(dest_buf); ++i) {
EXPECT_EQ(static_cast<uint8_t>(-1), dest_buf[i]);
-
+ }
EXPECT_EQ(5u, *(decompressor->DecompressedNextForTest()));
- for (i = 0; i < *(decompressor->DecompressedNextForTest()); ++i)
+ for (i = 0; i < *(decompressor->DecompressedNextForTest()); ++i) {
EXPECT_EQ(i, (*decompressed)[i]);
+ }
}
// Check that greater than decompressed size depletes the decompressor
@@ -75,16 +77,16 @@
*decompressed = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
*(decompressor->DecompressedNextForTest()) = decompressed->size();
uint8_t dest_buf[20];
- memset(dest_buf, static_cast<uint8_t>(-1), sizeof(dest_buf));
-
+ fxcrt::Fill(dest_buf, 0xff);
EXPECT_EQ(10u,
decompressor->ExtractDataForTest(dest_buf, std::size(dest_buf)));
size_t i = 0;
- for (; i < 10; ++i)
+ for (; i < 10; ++i) {
EXPECT_EQ(9 - i, dest_buf[i]);
- for (; i < std::size(dest_buf); ++i)
+ }
+ for (; i < std::size(dest_buf); ++i) {
EXPECT_EQ(static_cast<uint8_t>(-1), dest_buf[i]);
-
+ }
EXPECT_EQ(0u, *(decompressor->DecompressedNextForTest()));
}
}
@@ -214,15 +216,14 @@
static constexpr uint8_t kExpectedScanline[] = {0x00, 0x00, 0x00, 0x00};
uint8_t output_data[std::size(kExpectedScanline)];
-
- memset(output_data, 0xFF, sizeof(output_data));
+ fxcrt::Fill(output_data, 0xff);
uint32_t output_size = std::size(output_data);
EXPECT_EQ(LZWDecompressor::Status::kInsufficientDestSize,
decompressor->Decode(output_data, &output_size));
EXPECT_EQ(std::size(kExpectedScanline), output_size);
EXPECT_THAT(output_data, ElementsAreArray(kExpectedScanline));
- memset(output_data, 0xFF, sizeof(output_data));
+ fxcrt::Fill(output_data, 0xff);
output_size = std::size(output_data);
EXPECT_EQ(LZWDecompressor::Status::kSuccess,
decompressor->Decode(output_data, &output_size));
diff --git a/core/fxcodec/jpx/jpx_unittest.cpp b/core/fxcodec/jpx/jpx_unittest.cpp
index c4bfc10..87f6dc8 100644
--- a/core/fxcodec/jpx/jpx_unittest.cpp
+++ b/core/fxcodec/jpx/jpx_unittest.cpp
@@ -17,6 +17,7 @@
#include "core/fxcodec/jpx/jpx_decode_utils.h"
#include "core/fxcrt/fx_memcpy_wrappers.h"
#include "core/fxcrt/fx_memory.h"
+#include "core/fxcrt/stl_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/libopenjpeg/opj_malloc.h"
@@ -45,12 +46,12 @@
uint8_t buffer[16];
// Reads of size 0 do nothing but return an error code.
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbd);
EXPECT_EQ(kReadError, opj_read_from_memory(buffer, 0, &dd));
EXPECT_EQ(0xbd, buffer[0]);
// Reads of nonzero size do nothing but return an error code.
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbd);
EXPECT_EQ(kReadError, opj_read_from_memory(buffer, sizeof(buffer), &dd));
EXPECT_EQ(0xbd, buffer[0]);
@@ -72,12 +73,12 @@
uint8_t buffer[16];
// Reads of size 0 do nothing but return an error code.
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbd);
EXPECT_EQ(kReadError, opj_read_from_memory(buffer, 0, &dd));
EXPECT_EQ(0xbd, buffer[0]);
// Reads of nonzero size do nothing but return an error code.
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbd);
EXPECT_EQ(kReadError, opj_read_from_memory(buffer, sizeof(buffer), &dd));
EXPECT_EQ(0xbd, buffer[0]);
@@ -100,7 +101,7 @@
DecodeData dd(stream_data, sizeof(stream_data));
// Exact sized read in a single call.
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbd);
EXPECT_EQ(8u, opj_read_from_memory(buffer, sizeof(buffer), &dd));
EXPECT_EQ(0x00, buffer[0]);
EXPECT_EQ(0x01, buffer[1]);
@@ -116,19 +117,19 @@
DecodeData dd(stream_data, sizeof(stream_data));
// Simple read.
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbd);
EXPECT_EQ(2u, opj_read_from_memory(buffer, 2, &dd));
EXPECT_EQ(0x00, buffer[0]);
EXPECT_EQ(0x01, buffer[1]);
EXPECT_EQ(0xbd, buffer[2]);
// Read of size 0 doesn't affect things.
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbd);
EXPECT_EQ(0u, opj_read_from_memory(buffer, 0, &dd));
EXPECT_EQ(0xbd, buffer[0]);
// Read exactly up to end of data.
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbd);
EXPECT_EQ(6u, opj_read_from_memory(buffer, 6, &dd));
EXPECT_EQ(0x02, buffer[0]);
EXPECT_EQ(0x03, buffer[1]);
@@ -139,7 +140,7 @@
EXPECT_EQ(0xbd, buffer[6]);
// Read of size 0 at EOF is still an error.
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbd);
EXPECT_EQ(kReadError, opj_read_from_memory(buffer, 0, &dd));
EXPECT_EQ(0xbd, buffer[0]);
}
@@ -151,7 +152,7 @@
DecodeData dd(stream_data, sizeof(stream_data));
// Read beyond bounds in a single step.
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbd);
EXPECT_EQ(8u, opj_read_from_memory(buffer, sizeof(buffer) + 1, &dd));
EXPECT_EQ(0x00, buffer[0]);
EXPECT_EQ(0x01, buffer[1]);
@@ -167,7 +168,7 @@
DecodeData dd(stream_data, sizeof(stream_data));
// Read well beyond bounds in a single step.
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbd);
EXPECT_EQ(8u, opj_read_from_memory(
buffer, std::numeric_limits<OPJ_SIZE_T>::max(), &dd));
EXPECT_EQ(0x00, buffer[0]);
@@ -185,7 +186,7 @@
// Read of size 6 gets first 6 bytes.
// rest of buffer intact.
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbd);
EXPECT_EQ(6u, opj_read_from_memory(buffer, 6, &dd));
EXPECT_EQ(0x00, buffer[0]);
EXPECT_EQ(0x01, buffer[1]);
@@ -196,14 +197,14 @@
EXPECT_EQ(0xbd, buffer[6]);
// Read of size 6 gets remaining two bytes.
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbd);
EXPECT_EQ(2u, opj_read_from_memory(buffer, 6, &dd));
EXPECT_EQ(0x86, buffer[0]);
EXPECT_EQ(0x87, buffer[1]);
EXPECT_EQ(0xbd, buffer[2]);
// Read of 6 more gets nothing and leaves rest of buffer intact.
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbd);
EXPECT_EQ(kReadError, opj_read_from_memory(buffer, 6, &dd));
EXPECT_EQ(0xbd, buffer[0]);
}
@@ -217,28 +218,28 @@
DecodeData dd(stream_data, sizeof(stream_data));
// Skiping within buffer is allowed.
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbd);
EXPECT_EQ(1u, opj_skip_from_memory(1, &dd));
EXPECT_EQ(1u, opj_read_from_memory(buffer, 1, &dd));
EXPECT_EQ(0x01, buffer[0]);
EXPECT_EQ(0xbd, buffer[1]);
// Skiping 0 bytes changes nothing.
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbd);
EXPECT_EQ(0, opj_skip_from_memory(0, &dd));
EXPECT_EQ(1u, opj_read_from_memory(buffer, 1, &dd));
EXPECT_EQ(0x02, buffer[0]);
EXPECT_EQ(0xbd, buffer[1]);
// Skiping to EOS-1 is possible.
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbd);
EXPECT_EQ(4u, opj_skip_from_memory(4, &dd));
EXPECT_EQ(1u, opj_read_from_memory(buffer, 1, &dd));
EXPECT_EQ(0x87, buffer[0]);
EXPECT_EQ(0xbd, buffer[1]);
// Next read fails.
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbd);
EXPECT_EQ(kReadError, opj_read_from_memory(buffer, 1, &dd));
EXPECT_EQ(0xbd, buffer[0]);
}
@@ -246,7 +247,7 @@
DecodeData dd(stream_data, sizeof(stream_data));
// Skiping directly to EOS is allowed.
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbd);
EXPECT_EQ(8u, opj_skip_from_memory(8, &dd));
// Next read fails.
@@ -257,7 +258,7 @@
DecodeData dd(stream_data, sizeof(stream_data));
// Skipping beyond end of stream is allowed and returns full distance.
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbd);
EXPECT_EQ(9u, opj_skip_from_memory(9, &dd));
// Next read fails.
@@ -269,7 +270,7 @@
// Skipping way beyond EOS is allowd, doesn't wrap, and returns
// full distance.
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbd);
EXPECT_EQ(4u, opj_skip_from_memory(4, &dd));
EXPECT_EQ(std::numeric_limits<OPJ_OFF_T>::max(),
opj_skip_from_memory(std::numeric_limits<OPJ_OFF_T>::max(), &dd));
@@ -282,7 +283,7 @@
DecodeData dd(stream_data, sizeof(stream_data));
// Negative skip within buffer not is allowed, position unchanged.
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbd);
EXPECT_EQ(4u, opj_skip_from_memory(4, &dd));
EXPECT_EQ(kSkipError, opj_skip_from_memory(-2, &dd));
@@ -292,7 +293,7 @@
EXPECT_EQ(0xbd, buffer[1]);
// Negative skip before buffer is not allowed, position unchanged.
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbd);
EXPECT_EQ(kSkipError, opj_skip_from_memory(-4, &dd));
// Next read succeeds as if nothing has happenned.
@@ -304,7 +305,7 @@
DecodeData dd(stream_data, sizeof(stream_data));
// Negative skip way before buffer is not allowed, doesn't wrap
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbd);
EXPECT_EQ(4u, opj_skip_from_memory(4, &dd));
EXPECT_EQ(kSkipError,
opj_skip_from_memory(std::numeric_limits<OPJ_OFF_T>::min(), &dd));
@@ -318,7 +319,7 @@
DecodeData dd(stream_data, sizeof(stream_data));
// Negative skip after EOS isn't alowed, still EOS.
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbd);
EXPECT_EQ(8u, opj_skip_from_memory(8, &dd));
EXPECT_EQ(kSkipError, opj_skip_from_memory(-4, &dd));
@@ -333,21 +334,21 @@
DecodeData dd(stream_data, sizeof(stream_data));
// Seeking within buffer is allowed and read succeeds
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbd);
EXPECT_TRUE(opj_seek_from_memory(1, &dd));
EXPECT_EQ(1u, opj_read_from_memory(buffer, 1, &dd));
EXPECT_EQ(0x01, buffer[0]);
EXPECT_EQ(0xbd, buffer[1]);
// Seeking before start returns error leaving position unchanged.
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbd);
EXPECT_FALSE(opj_seek_from_memory(-1, &dd));
EXPECT_EQ(1u, opj_read_from_memory(buffer, 1, &dd));
EXPECT_EQ(0x02, buffer[0]);
EXPECT_EQ(0xbd, buffer[1]);
// Seeking way before start returns error leaving position unchanged.
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbd);
EXPECT_FALSE(
opj_seek_from_memory(std::numeric_limits<OPJ_OFF_T>::min(), &dd));
EXPECT_EQ(1u, opj_read_from_memory(buffer, 1, &dd));
@@ -355,40 +356,40 @@
EXPECT_EQ(0xbd, buffer[1]);
// Seeking exactly to EOS is allowed but read fails.
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbd);
EXPECT_TRUE(opj_seek_from_memory(8, &dd));
EXPECT_EQ(kReadError, opj_read_from_memory(buffer, 1, &dd));
EXPECT_EQ(0xbd, buffer[0]);
// Seeking back to zero offset is allowed and read succeeds.
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbd);
EXPECT_TRUE(opj_seek_from_memory(0, &dd));
EXPECT_EQ(1u, opj_read_from_memory(buffer, 1, &dd));
EXPECT_EQ(0x00, buffer[0]);
EXPECT_EQ(0xbd, buffer[1]);
// Seeking beyond end of stream is allowed but read fails.
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbd);
EXPECT_TRUE(opj_seek_from_memory(16, &dd));
EXPECT_EQ(kReadError, opj_read_from_memory(buffer, 1, &dd));
EXPECT_EQ(0xbd, buffer[0]);
// Seeking within buffer after seek past EOF restores good state.
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbd);
EXPECT_TRUE(opj_seek_from_memory(4, &dd));
EXPECT_EQ(1u, opj_read_from_memory(buffer, 1, &dd));
EXPECT_EQ(0x84, buffer[0]);
EXPECT_EQ(0xbd, buffer[1]);
// Seeking way beyond EOS is allowed, doesn't wrap, and read fails.
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbd);
EXPECT_TRUE(opj_seek_from_memory(std::numeric_limits<OPJ_OFF_T>::max(), &dd));
EXPECT_EQ(kReadError, opj_read_from_memory(buffer, 1, &dd));
EXPECT_EQ(0xbd, buffer[0]);
}
TEST(fxcodec, YUV420ToRGB) {
- opj_image_comp_t u = {};
+ opj_image_comp_t u = {}; // Aggregate initialization.
static_assert(std::is_aggregate_v<decltype(u)>);
u.dx = 1;
u.dy = 1;
@@ -396,7 +397,7 @@
u.h = 16;
u.prec = 8;
u.bpp = 8;
- opj_image_comp_t v = {};
+ opj_image_comp_t v = {}; // Aggregate initialization.
static_assert(std::is_aggregate_v<decltype(v)>);
v.dx = 1;
v.dy = 1;
@@ -404,13 +405,13 @@
v.h = 16;
v.prec = 8;
v.bpp = 8;
- opj_image_comp_t y = {};
+ opj_image_comp_t y = {}; // Aggregate initialization.
static_assert(std::is_aggregate_v<decltype(y)>);
y.dx = 1;
y.dy = 1;
y.prec = 8;
y.bpp = 8;
- opj_image_t img = {};
+ opj_image_t img = {}; // Aggregate initialization.
static_assert(std::is_aggregate_v<decltype(img)>);
img.numcomps = 3;
img.color_space = OPJ_CLRSPC_SYCC;
diff --git a/core/fxcrt/BUILD.gn b/core/fxcrt/BUILD.gn
index bd5d617..70ad8c9 100644
--- a/core/fxcrt/BUILD.gn
+++ b/core/fxcrt/BUILD.gn
@@ -236,6 +236,7 @@
"scoped_set_insertion_unittest.cpp",
"shared_copy_on_write_unittest.cpp",
"span_util_unittest.cpp",
+ "stl_util_unittest.cpp",
"string_pool_template_unittest.cpp",
"tree_node_unittest.cpp",
"unowned_ptr_unittest.cpp",
diff --git a/core/fxcrt/stl_util.h b/core/fxcrt/stl_util.h
index 504bbc4..8fe1639 100644
--- a/core/fxcrt/stl_util.h
+++ b/core/fxcrt/stl_util.h
@@ -5,6 +5,7 @@
#ifndef CORE_FXCRT_STL_UTIL_H_
#define CORE_FXCRT_STL_UTIL_H_
+#include <algorithm>
#include <memory>
#include "core/fxcrt/numerics/safe_conversions.h"
@@ -40,6 +41,12 @@
return index >= 0 && index < CollectionSize<IndexType>(collection);
}
+// Equivalent of C++20 std::ranges::fill().
+template <typename T, typename V>
+void Fill(T& container, const V& value) {
+ std::fill(std::begin(container), std::end(container), value);
+}
+
} // namespace fxcrt
#endif // CORE_FXCRT_STL_UTIL_H_
diff --git a/core/fxcrt/stl_util_unittest.cpp b/core/fxcrt/stl_util_unittest.cpp
new file mode 100644
index 0000000..5ee6993
--- /dev/null
+++ b/core/fxcrt/stl_util_unittest.cpp
@@ -0,0 +1,46 @@
+// Copyright 2024 The PDFium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/fxcrt/stl_util.h"
+
+#include <stdint.h>
+
+#include <array>
+#include <vector>
+
+#include "core/fxcrt/span.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+TEST(fxcrt, FillCArray) {
+ uint32_t buf[4];
+ fxcrt::Fill(buf, 0x01020304u);
+ for (const auto b : buf) {
+ EXPECT_EQ(b, 0x01020304u);
+ }
+}
+
+TEST(fxcrt, FillStdArray) {
+ std::array<uint16_t, 10> buf;
+ fxcrt::Fill(buf, 0x0102u);
+ for (const auto b : buf) {
+ EXPECT_EQ(b, 0x0102u);
+ }
+}
+
+TEST(fxcrt, FillStdVector) {
+ std::vector<uint8_t> buf(15);
+ fxcrt::Fill(buf, 0x32u);
+ for (const auto b : buf) {
+ EXPECT_EQ(b, 0x32u);
+ }
+}
+
+TEST(fxcrt, FillSpan) {
+ float buf[12];
+ auto buf_span = pdfium::make_span(buf);
+ fxcrt::Fill(buf_span, 123.0f);
+ for (const auto b : buf) {
+ EXPECT_EQ(b, 123.0f);
+ }
+}
diff --git a/fpdfsdk/fpdf_structtree_embeddertest.cpp b/fpdfsdk/fpdf_structtree_embeddertest.cpp
index 0df7829..de53be0 100644
--- a/fpdfsdk/fpdf_structtree_embeddertest.cpp
+++ b/fpdfsdk/fpdf_structtree_embeddertest.cpp
@@ -10,6 +10,7 @@
#include <iterator>
#include <optional>
+#include "core/fxcrt/stl_util.h"
#include "public/fpdf_structtree.h"
#include "testing/embedder_test.h"
#include "testing/fx_string_testhelpers.h"
@@ -462,10 +463,11 @@
// Deliberately pass in a small buffer size to make sure |buffer| remains
// untouched.
+ fxcrt::Fill(buffer, 0xbdfcu);
ASSERT_EQ(18U, FPDF_StructElement_GetType(element, buffer, 1));
- for (size_t i = 0; i < std::size(buffer); ++i)
- EXPECT_EQ(0U, buffer[i]);
-
+ for (const auto b : buffer) {
+ EXPECT_EQ(0xbdfcu, b);
+ }
ASSERT_EQ(18U, FPDF_StructElement_GetType(element, buffer, sizeof(buffer)));
EXPECT_EQ(L"Document", GetPlatformWString(buffer));
}
@@ -506,14 +508,15 @@
ASSERT_EQ(1, FPDF_StructElement_CountChildren(child));
FPDF_STRUCTELEMENT gchild = FPDF_StructElement_GetChildAtIndex(child, 0);
- memset(buffer, 0, sizeof(buffer));
+
+ fxcrt::Fill(buffer, 0xbdfcu);
// Missing /Type in `gchild`
ASSERT_EQ(0U,
FPDF_StructElement_GetObjType(gchild, buffer, sizeof(buffer)));
// Buffer is untouched.
- for (size_t i = 0; i < std::size(buffer); ++i)
- EXPECT_EQ(0U, buffer[i]);
-
+ for (const auto b : buffer) {
+ EXPECT_EQ(0xbdfcu, b);
+ }
ASSERT_EQ(1, FPDF_StructElement_CountChildren(gchild));
FPDF_STRUCTELEMENT ggchild = FPDF_StructElement_GetChildAtIndex(gchild, 0);
ASSERT_EQ(28U,
@@ -577,16 +580,16 @@
ASSERT_EQ(0U, FPDF_StructElement_GetTitle(nullptr, nullptr, 0));
ASSERT_EQ(20U, FPDF_StructElement_GetTitle(element, nullptr, 0));
- memset(buffer, 0, sizeof(buffer));
// Deliberately pass in a small buffer size to make sure |buffer| remains
// untouched.
+ fxcrt::Fill(buffer, 0xbdfcu);
ASSERT_EQ(20U, FPDF_StructElement_GetTitle(element, buffer, 1));
- for (size_t i = 0; i < std::size(buffer); ++i)
- EXPECT_EQ(0U, buffer[i]);
+ for (const auto b : buffer) {
+ EXPECT_EQ(0xbdfcu, b);
+ }
ASSERT_EQ(20U,
FPDF_StructElement_GetTitle(element, buffer, sizeof(buffer)));
-
EXPECT_EQ(L"TitleText", GetPlatformWString(buffer));
ASSERT_EQ(1, FPDF_StructElement_CountChildren(element));
@@ -673,7 +676,7 @@
EXPECT_EQ(12U, out_len);
EXPECT_EQ(L"Table", GetPlatformWString(str_val));
- memset(buffer, 0, sizeof(buffer));
+ fxcrt::Fill(buffer, 0u);
ASSERT_TRUE(FPDF_StructElement_Attr_GetName(attr, 0, buffer,
sizeof(buffer), &out_len));
EXPECT_EQ(8U, out_len);
diff --git a/fpdfsdk/fpdf_text_embeddertest.cpp b/fpdfsdk/fpdf_text_embeddertest.cpp
index afff1ed..954323d 100644
--- a/fpdfsdk/fpdf_text_embeddertest.cpp
+++ b/fpdfsdk/fpdf_text_embeddertest.cpp
@@ -12,6 +12,7 @@
#include <vector>
#include "build/build_config.h"
+#include "core/fxcrt/stl_util.h"
#include "core/fxge/fx_font.h"
#include "public/cpp/fpdf_scopers.h"
#include "public/fpdf_doc.h"
@@ -53,7 +54,7 @@
ASSERT_TRUE(textpage);
unsigned short buffer[128];
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbdbd);
// Check that edge cases are handled gracefully
EXPECT_EQ(0, FPDFText_GetText(textpage, 0, 128, nullptr));
@@ -63,7 +64,7 @@
EXPECT_EQ(0, buffer[0]);
// Keep going and check the next case.
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbdbd);
EXPECT_EQ(2, FPDFText_GetText(textpage, 0, 1, buffer));
EXPECT_EQ(kHelloGoodbyeText[0], buffer[0]);
EXPECT_EQ(0, buffer[1]);
@@ -87,7 +88,7 @@
// the expected string, plus 2 more for the terminating character.
static const char kSmallExpected[] = "Hello";
unsigned short small_buffer[12];
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbdbd);
EXPECT_EQ(6, FPDFText_GetText(textpage, 0, 5, small_buffer));
EXPECT_TRUE(check_unsigned_shorts(kSmallExpected, small_buffer,
sizeof(kSmallExpected)));
@@ -206,19 +207,19 @@
9, FPDFText_GetBoundedText(textpage, 41.0, 56.0, 82.0, 48.0, nullptr, 0));
// Extract starting at character 4 as above.
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbdbd);
EXPECT_EQ(
1, FPDFText_GetBoundedText(textpage, 41.0, 56.0, 82.0, 48.0, buffer, 1));
EXPECT_TRUE(check_unsigned_shorts(kHelloGoodbyeText + 4, buffer, 1));
EXPECT_EQ(0xbdbd, buffer[1]);
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbdbd);
EXPECT_EQ(
9, FPDFText_GetBoundedText(textpage, 41.0, 56.0, 82.0, 48.0, buffer, 9));
EXPECT_TRUE(check_unsigned_shorts(kHelloGoodbyeText + 4, buffer, 8));
EXPECT_EQ(0xbdbd, buffer[9]);
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbdbd);
EXPECT_EQ(10, FPDFText_GetBoundedText(textpage, 41.0, 56.0, 82.0, 48.0,
buffer, 128));
EXPECT_TRUE(check_unsigned_shorts(kHelloGoodbyeText + 4, buffer, 9));
@@ -279,7 +280,7 @@
ASSERT_EQ(kCharCount, FPDFText_CountChars(textpage.get()));
unsigned short buffer[kCharCount + 1];
- memset(buffer, 0x42, sizeof(buffer));
+ fxcrt::Fill(buffer, 0x4242);
EXPECT_EQ(kCharCount + 1,
FPDFText_GetText(textpage.get(), 0, kCharCount, buffer));
EXPECT_EQ(0x05d1, buffer[0]);
@@ -694,20 +695,20 @@
// Retrieve a link with too small a buffer. Buffer will not be
// NUL-terminated, but must not be modified past indicated length,
// so pre-fill with a pattern to check write bounds.
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbdbd);
EXPECT_EQ(1, FPDFLink_GetURL(pagelink, 0, buffer, 1));
EXPECT_TRUE(check_unsigned_shorts(expected_url, buffer, 1));
EXPECT_EQ(0xbdbd, buffer[1]);
// Check buffer that doesn't have space for a terminating NUL.
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbdbd);
EXPECT_EQ(static_cast<int>(expected_len - 1),
FPDFLink_GetURL(pagelink, 0, buffer, expected_len - 1));
EXPECT_TRUE(check_unsigned_shorts(expected_url, buffer, expected_len - 1));
EXPECT_EQ(0xbdbd, buffer[expected_len - 1]);
// Retreive link with exactly-sized buffer.
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbdbd);
EXPECT_EQ(static_cast<int>(expected_len),
FPDFLink_GetURL(pagelink, 0, buffer, expected_len));
EXPECT_TRUE(check_unsigned_shorts(expected_url, buffer, expected_len));
@@ -715,7 +716,7 @@
EXPECT_EQ(0xbdbd, buffer[expected_len]);
// Retreive link with ample-sized-buffer.
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbdbd);
EXPECT_EQ(static_cast<int>(expected_len),
FPDFLink_GetURL(pagelink, 0, buffer, 128));
EXPECT_TRUE(check_unsigned_shorts(expected_url, buffer, expected_len));
@@ -1175,7 +1176,7 @@
EXPECT_EQ(kData[i], FPDFText_GetUnicode(textpage, kStartIndex + i));
unsigned short buffer[std::size(kData) + 1];
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbdbd);
int count = FPDFText_GetText(textpage, kStartIndex, std::size(kData), buffer);
ASSERT_GT(count, 0);
ASSERT_EQ(std::size(kData) + 1, static_cast<size_t>(count));
@@ -1253,7 +1254,7 @@
// Should not include the control characters in the output
unsigned short buffer[128];
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbdbd);
int num_chars = FPDFText_GetText(textpage, 0, 128, buffer);
ASSERT_EQ(kHelloGoodbyeTextSize, num_chars);
EXPECT_TRUE(
@@ -1264,7 +1265,7 @@
// Offset is the length of 'Hello, world!\r\n' + 2 control characters in the
// original stream
static const int offset = 17;
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbdbd);
num_chars = FPDFText_GetText(textpage, offset, 128, buffer);
ASSERT_GE(num_chars, 0);
@@ -1468,7 +1469,7 @@
ASSERT_TRUE(textpage);
unsigned short buffer[128];
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbdbd);
int num_chars = FPDFText_GetText(textpage.get(), 0, 128, buffer);
ASSERT_EQ(kHelloGoodbyeTextSize, num_chars);
EXPECT_TRUE(check_unsigned_shorts(kHelloGoodbyeText, buffer,
@@ -1479,7 +1480,7 @@
FPDFText_GetBoundedText(textpage.get(), box.left, box.top,
box.right, box.bottom, nullptr, 0));
- memset(buffer, 0xbd, sizeof(buffer));
+ fxcrt::Fill(buffer, 0xbdbd);
ASSERT_EQ(expected_char_count + 1,
FPDFText_GetBoundedText(textpage.get(), box.left, box.top,
box.right, box.bottom, buffer, 128));