From 2e2acbdc523735fdbbf69b1f9fee9a24e4303045 Mon Sep 17 00:00:00 2001 From: Lei Zhang Date: Tue, 16 Oct 2018 05:21:13 +0000 Subject: Make {A85,RunLength}Encode()'s buffer out parameter a unique_ptr. Change-Id: I3f06ea7ed39c8a8fff57e07f14ff6c21bedbc028 Reviewed-on: https://pdfium-review.googlesource.com/c/43998 Commit-Queue: Lei Zhang Reviewed-by: Tom Sepez --- core/fxcodec/codec/ccodec_basicmodule.h | 5 +- core/fxcodec/codec/fx_codec.cpp | 35 ++-- core/fxcodec/codec/fx_codec_a85_unittest.cpp | 216 +++++++++++++------------ core/fxcodec/codec/fx_codec_rle_unittest.cpp | 233 +++++++++++++-------------- core/fxge/win32/cfx_psrenderer.cpp | 11 +- testing/fuzzers/pdf_codec_a85_fuzzer.cc | 3 +- testing/fuzzers/pdf_codec_rle_fuzzer.cc | 3 +- 7 files changed, 257 insertions(+), 249 deletions(-) diff --git a/core/fxcodec/codec/ccodec_basicmodule.h b/core/fxcodec/codec/ccodec_basicmodule.h index 2ad374037f..72dd016d44 100644 --- a/core/fxcodec/codec/ccodec_basicmodule.h +++ b/core/fxcodec/codec/ccodec_basicmodule.h @@ -9,6 +9,7 @@ #include +#include "core/fxcrt/fx_memory.h" #include "core/fxcrt/fx_system.h" #include "third_party/base/span.h" @@ -24,11 +25,11 @@ class CCodec_BasicModule { int bpc); bool RunLengthEncode(pdfium::span src_buf, - uint8_t** dest_buf, + std::unique_ptr* dest_buf, uint32_t* dest_size); bool A85Encode(pdfium::span src_buf, - uint8_t** dest_buf, + std::unique_ptr* dest_buf, uint32_t* dest_size); }; diff --git a/core/fxcodec/codec/fx_codec.cpp b/core/fxcodec/codec/fx_codec.cpp index d38f10aadd..f2c8e18843 100644 --- a/core/fxcodec/codec/fx_codec.cpp +++ b/core/fxcodec/codec/fx_codec.cpp @@ -1357,20 +1357,22 @@ CCodec_ModuleMgr::CCodec_ModuleMgr() CCodec_ModuleMgr::~CCodec_ModuleMgr() {} -bool CCodec_BasicModule::RunLengthEncode(pdfium::span src_span, - uint8_t** dest_buf, - uint32_t* dest_size) { +bool CCodec_BasicModule::RunLengthEncode( + pdfium::span src_span, + std::unique_ptr* dest_buf, + uint32_t* dest_size) { // Check inputs if (src_span.empty() || !dest_buf || !dest_size) return false; // Edge case if (src_span.size() == 1) { - *dest_buf = FX_Alloc(uint8_t, 3); - (*dest_buf)[0] = 0; - (*dest_buf)[1] = src_span[0]; - (*dest_buf)[2] = 128; *dest_size = 3; + dest_buf->reset(FX_Alloc(uint8_t, *dest_size)); + auto dest_buf_span = pdfium::make_span(dest_buf->get(), *dest_size); + dest_buf_span[0] = 0; + dest_buf_span[1] = src_span[0]; + dest_buf_span[2] = 128; return true; } @@ -1382,10 +1384,10 @@ bool CCodec_BasicModule::RunLengthEncode(pdfium::span src_span, estimated_size /= 3; estimated_size *= 4; estimated_size += 1; - *dest_buf = FX_Alloc(uint8_t, estimated_size.ValueOrDie()); + dest_buf->reset(FX_Alloc(uint8_t, estimated_size.ValueOrDie())); // Set up pointers. - uint8_t* out = *dest_buf; + uint8_t* out = dest_buf->get(); uint32_t run_start = 0; uint32_t run_end = 1; uint8_t x = src_span[run_start]; @@ -1436,13 +1438,14 @@ bool CCodec_BasicModule::RunLengthEncode(pdfium::span src_span, out += 2; } *out = 128; - *dest_size = out + 1 - *dest_buf; + *dest_size = out + 1 - dest_buf->get(); return true; } -bool CCodec_BasicModule::A85Encode(pdfium::span src_span, - uint8_t** dest_buf, - uint32_t* dest_size) { +bool CCodec_BasicModule::A85Encode( + pdfium::span src_span, + std::unique_ptr* dest_buf, + uint32_t* dest_size) { // Check inputs. if (!dest_buf || !dest_size) return false; @@ -1461,10 +1464,10 @@ bool CCodec_BasicModule::A85Encode(pdfium::span src_span, estimated_size += 4; estimated_size += src_span.size() / 30; estimated_size += 2; - *dest_buf = FX_Alloc(uint8_t, estimated_size.ValueOrDie()); + dest_buf->reset(FX_Alloc(uint8_t, estimated_size.ValueOrDie())); // Set up pointers. - uint8_t* out = *dest_buf; + uint8_t* out = dest_buf->get(); uint32_t pos = 0; uint32_t line_length = 0; while (src_span.size() >= 4 && pos < src_span.size() - 3) { @@ -1511,7 +1514,7 @@ bool CCodec_BasicModule::A85Encode(pdfium::span src_span, out[0] = '~'; out[1] = '>'; out += 2; - *dest_size = out - *dest_buf; + *dest_size = out - dest_buf->get(); return true; } diff --git a/core/fxcodec/codec/fx_codec_a85_unittest.cpp b/core/fxcodec/codec/fx_codec_a85_unittest.cpp index e0b6964f53..13728587d7 100644 --- a/core/fxcodec/codec/fx_codec_a85_unittest.cpp +++ b/core/fxcodec/codec/fx_codec_a85_unittest.cpp @@ -5,6 +5,7 @@ #include #include +#include #include "core/fxcodec/codec/ccodec_basicmodule.h" #include "core/fxcodec/fx_codec.h" @@ -12,7 +13,7 @@ TEST(fxcodec, A85TestBadInputs) { const uint8_t src_buf[] = {1, 2, 3, 4}; - uint8_t* dest_buf = nullptr; + std::unique_ptr dest_buf; uint32_t dest_size = 0; CCodec_BasicModule* pEncoders = CCodec_ModuleMgr().GetBasicModule(); @@ -26,135 +27,141 @@ TEST(fxcodec, A85TestBadInputs) { // No leftover bytes, just translate 2 sets of symbols. TEST(fxcodec, A85TestBasic) { - // Make sure really big values don't break. - const uint8_t src_buf[] = {1, 2, 3, 4, 255, 255, 255, 255}; - uint8_t* dest_buf = nullptr; - uint32_t dest_size = 0; - CCodec_BasicModule* pEncoders = CCodec_ModuleMgr().GetBasicModule(); EXPECT_TRUE(pEncoders); - // Should succeed. + // Make sure really big values don't break. + const uint8_t src_buf[] = {1, 2, 3, 4, 255, 255, 255, 255}; + std::unique_ptr dest_buf; + uint32_t dest_size = 0; EXPECT_TRUE(pEncoders->A85Encode(src_buf, &dest_buf, &dest_size)); // Should have 5 chars for each set of 4 and 2 terminators. - ASSERT_EQ(12u, dest_size); const uint8_t expected_out[] = {33, 60, 78, 63, 43, 115, 56, 87, 45, 33, 126, 62}; + ASSERT_EQ(FX_ArraySize(expected_out), dest_size); // Check the output - for (uint32_t i = 0; i < 12; i++) - EXPECT_EQ(expected_out[i], dest_buf[i]) << " at " << i; - FX_Free(dest_buf); + auto dest_buf_span = pdfium::make_span(dest_buf.get(), dest_size); + for (uint32_t i = 0; i < dest_size; i++) + EXPECT_EQ(expected_out[i], dest_buf_span[i]) << " at " << i; } // Leftover bytes. TEST(fxcodec, A85TestLeftoverBytes) { - // 1 Leftover Byte: - const uint8_t src_buf_1leftover[] = {1, 2, 3, 4, 255}; - uint8_t* dest_buf = nullptr; - uint32_t dest_size = 0; - CCodec_BasicModule* pEncoders = CCodec_ModuleMgr().GetBasicModule(); EXPECT_TRUE(pEncoders); - // Should succeed - EXPECT_TRUE(pEncoders->A85Encode(src_buf_1leftover, &dest_buf, &dest_size)); - ASSERT_EQ(9u, dest_size); // 5 chars for first symbol + 2 + 2 terminators. - uint8_t expected_out_1leftover[] = {33, 60, 78, 63, 43, 114, 114, 126, 62}; + std::unique_ptr dest_buf; + uint32_t dest_size = 0; - // Check the output - for (uint32_t i = 0; i < 9; i++) - EXPECT_EQ(expected_out_1leftover[i], dest_buf[i]) << " at " << i; - FX_Free(dest_buf); - - // 2 Leftover bytes: - const uint8_t src_buf_2leftover[] = {1, 2, 3, 4, 255, 254}; - dest_buf = nullptr; - dest_size = 0; - // Should succeed - EXPECT_TRUE(pEncoders->A85Encode(src_buf_2leftover, &dest_buf, &dest_size)); - ASSERT_EQ(10u, dest_size); // 5 chars for first symbol + 3 + 2 terminators. - const uint8_t expected_out_2leftover[] = {33, 60, 78, 63, 43, - 115, 56, 68, 126, 62}; + { + // 1 Leftover Byte: + const uint8_t src_buf_1leftover[] = {1, 2, 3, 4, 255}; + EXPECT_TRUE(pEncoders->A85Encode(src_buf_1leftover, &dest_buf, &dest_size)); - // Check the output - for (uint32_t i = 0; i < 10; i++) - EXPECT_EQ(expected_out_2leftover[i], dest_buf[i]) << " at " << i; - FX_Free(dest_buf); - - // 3 Leftover bytes: - const uint8_t src_buf_3leftover[] = {1, 2, 3, 4, 255, 254, 253}; - dest_buf = nullptr; - dest_size = 0; - // Should succeed - EXPECT_TRUE(pEncoders->A85Encode(src_buf_3leftover, &dest_buf, &dest_size)); - ASSERT_EQ(11u, dest_size); // 5 chars for first symbol + 4 + 2 terminators. - const uint8_t expected_out_3leftover[] = {33, 60, 78, 63, 43, 115, - 56, 77, 114, 126, 62}; + // 5 chars for first symbol + 2 + 2 terminators. + uint8_t expected_out_1leftover[] = {33, 60, 78, 63, 43, 114, 114, 126, 62}; + ASSERT_EQ(FX_ArraySize(expected_out_1leftover), dest_size); - // Check the output - for (uint32_t i = 0; i < 11; i++) - EXPECT_EQ(expected_out_3leftover[i], dest_buf[i]) << " at " << i; - FX_Free(dest_buf); + // Check the output + auto dest_buf_span = pdfium::make_span(dest_buf.get(), dest_size); + for (uint32_t i = 0; i < dest_size; i++) + EXPECT_EQ(expected_out_1leftover[i], dest_buf_span[i]) << " at " << i; + } + + { + // 2 Leftover bytes: + const uint8_t src_buf_2leftover[] = {1, 2, 3, 4, 255, 254}; + dest_buf.reset(); + dest_size = 0; + EXPECT_TRUE(pEncoders->A85Encode(src_buf_2leftover, &dest_buf, &dest_size)); + // 5 chars for first symbol + 3 + 2 terminators. + const uint8_t expected_out_2leftover[] = {33, 60, 78, 63, 43, + 115, 56, 68, 126, 62}; + ASSERT_EQ(FX_ArraySize(expected_out_2leftover), dest_size); + + // Check the output + auto dest_buf_span = pdfium::make_span(dest_buf.get(), dest_size); + for (uint32_t i = 0; i < dest_size; i++) + EXPECT_EQ(expected_out_2leftover[i], dest_buf_span[i]) << " at " << i; + } + + { + // 3 Leftover bytes: + const uint8_t src_buf_3leftover[] = {1, 2, 3, 4, 255, 254, 253}; + dest_buf.reset(); + dest_size = 0; + EXPECT_TRUE(pEncoders->A85Encode(src_buf_3leftover, &dest_buf, &dest_size)); + // 5 chars for first symbol + 4 + 2 terminators. + const uint8_t expected_out_3leftover[] = {33, 60, 78, 63, 43, 115, + 56, 77, 114, 126, 62}; + ASSERT_EQ(FX_ArraySize(expected_out_3leftover), dest_size); + + // Check the output + auto dest_buf_span = pdfium::make_span(dest_buf.get(), dest_size); + for (uint32_t i = 0; i < dest_size; i++) + EXPECT_EQ(expected_out_3leftover[i], dest_buf_span[i]) << " at " << i; + } } // Test all zeros comes through as "z". TEST(fxcodec, A85TestZeros) { - // Make sure really big values don't break. - const uint8_t src_buf[] = {1, 2, 3, 4, 0, 0, 0, 0}; - uint8_t* dest_buf = nullptr; - uint32_t dest_size = 0; - CCodec_BasicModule* pEncoders = CCodec_ModuleMgr().GetBasicModule(); EXPECT_TRUE(pEncoders); - // Should succeed. - EXPECT_TRUE(pEncoders->A85Encode(src_buf, &dest_buf, &dest_size)); - - // Should have 5 chars for first set of 4 + 1 for z + 2 terminators. - ASSERT_EQ(8u, dest_size); - const uint8_t expected_out[] = {33, 60, 78, 63, 43, 122, 126, 62}; - - // Check the output - for (uint32_t i = 0; i < 8; i++) - EXPECT_EQ(expected_out[i], dest_buf[i]) << " at " << i; - FX_Free(dest_buf); - - // Should also work if it is at the start: - const uint8_t src_buf_2[] = {0, 0, 0, 0, 1, 2, 3, 4}; - dest_buf = nullptr; - dest_size = 0; - - // Should succeed. - EXPECT_TRUE(pEncoders->A85Encode(src_buf_2, &dest_buf, &dest_size)); - - // Should have 5 chars for set of 4 + 1 for z + 2 terminators. - ASSERT_EQ(8u, dest_size); - const uint8_t expected_out_2[] = {122, 33, 60, 78, 63, 43, 126, 62}; + std::unique_ptr dest_buf; + uint32_t dest_size = 0; - // Check the output - for (uint32_t i = 0; i < 8; i++) - EXPECT_EQ(expected_out_2[i], dest_buf[i]) << " at " << i; - FX_Free(dest_buf); + { + // Make sure really big values don't break. + const uint8_t src_buf[] = {1, 2, 3, 4, 0, 0, 0, 0}; + EXPECT_TRUE(pEncoders->A85Encode(src_buf, &dest_buf, &dest_size)); - // Try with 2 leftover zero bytes. Make sure we don't get a "z". - const uint8_t src_buf_3[] = {1, 2, 3, 4, 0, 0}; - dest_buf = nullptr; - dest_size = 0; + // Should have 5 chars for first set of 4 + 1 for z + 2 terminators. + const uint8_t expected_out[] = {33, 60, 78, 63, 43, 122, 126, 62}; + ASSERT_EQ(FX_ArraySize(expected_out), dest_size); - // Should succeed. - EXPECT_TRUE(pEncoders->A85Encode(src_buf_3, &dest_buf, &dest_size)); + // Check the output + auto dest_buf_span = pdfium::make_span(dest_buf.get(), dest_size); + for (uint32_t i = 0; i < dest_size; i++) + EXPECT_EQ(expected_out[i], dest_buf_span[i]) << " at " << i; + } - // Should have 5 chars for set of 4 + 3 for last 2 + 2 terminators. - ASSERT_EQ(10u, dest_size); - const uint8_t expected_out_leftover[] = {33, 60, 78, 63, 43, - 33, 33, 33, 126, 62}; + { + // Should also work if it is at the start: + const uint8_t src_buf_2[] = {0, 0, 0, 0, 1, 2, 3, 4}; + dest_buf.reset(); + dest_size = 0; + EXPECT_TRUE(pEncoders->A85Encode(src_buf_2, &dest_buf, &dest_size)); + + // Should have 5 chars for set of 4 + 1 for z + 2 terminators. + const uint8_t expected_out_2[] = {122, 33, 60, 78, 63, 43, 126, 62}; + ASSERT_EQ(FX_ArraySize(expected_out_2), dest_size); + + // Check the output + auto dest_buf_span = pdfium::make_span(dest_buf.get(), dest_size); + for (uint32_t i = 0; i < dest_size; i++) + EXPECT_EQ(expected_out_2[i], dest_buf_span[i]) << " at " << i; + } - // Check the output - for (uint32_t i = 0; i < 10; i++) - EXPECT_EQ(expected_out_leftover[i], dest_buf[i]) << " at " << i; - FX_Free(dest_buf); + { + // Try with 2 leftover zero bytes. Make sure we don't get a "z". + const uint8_t src_buf_3[] = {1, 2, 3, 4, 0, 0}; + dest_buf.reset(); + dest_size = 0; + EXPECT_TRUE(pEncoders->A85Encode(src_buf_3, &dest_buf, &dest_size)); + + // Should have 5 chars for set of 4 + 3 for last 2 + 2 terminators. + const uint8_t expected_out_leftover[] = {33, 60, 78, 63, 43, + 33, 33, 33, 126, 62}; + ASSERT_EQ(FX_ArraySize(expected_out_leftover), dest_size); + + // Check the output + auto dest_buf_span = pdfium::make_span(dest_buf.get(), dest_size); + for (uint32_t i = 0; i < dest_size; i++) + EXPECT_EQ(expected_out_leftover[i], dest_buf_span[i]) << " at " << i; + } } // Make sure we get returns in the expected locations. @@ -175,7 +182,7 @@ TEST(fxcodec, A85TestLineBreaks) { src_buf[k + 2] = 3; src_buf[k + 3] = 4; } - uint8_t* dest_buf = nullptr; + std::unique_ptr dest_buf; uint32_t dest_size = 0; CCodec_BasicModule* pEncoders = CCodec_ModuleMgr().GetBasicModule(); @@ -190,10 +197,9 @@ TEST(fxcodec, A85TestLineBreaks) { ASSERT_EQ(166u, dest_size); // Check for the returns. - EXPECT_EQ(13, dest_buf[75]); - EXPECT_EQ(10, dest_buf[76]); - EXPECT_EQ(13, dest_buf[153]); - EXPECT_EQ(10, dest_buf[154]); - - FX_Free(dest_buf); + auto dest_buf_span = pdfium::make_span(dest_buf.get(), dest_size); + EXPECT_EQ(13, dest_buf_span[75]); + EXPECT_EQ(10, dest_buf_span[76]); + EXPECT_EQ(13, dest_buf_span[153]); + EXPECT_EQ(10, dest_buf_span[154]); } diff --git a/core/fxcodec/codec/fx_codec_rle_unittest.cpp b/core/fxcodec/codec/fx_codec_rle_unittest.cpp index 3ee0aa6368..433d96d112 100644 --- a/core/fxcodec/codec/fx_codec_rle_unittest.cpp +++ b/core/fxcodec/codec/fx_codec_rle_unittest.cpp @@ -14,7 +14,7 @@ TEST(fxcodec, RLETestBadInputs) { const uint8_t src_buf[] = {1}; - uint8_t* dest_buf = nullptr; + std::unique_ptr dest_buf; uint32_t dest_size = 0; CCodec_BasicModule* pEncoders = CCodec_ModuleMgr().GetBasicModule(); @@ -28,145 +28,144 @@ TEST(fxcodec, RLETestBadInputs) { // Check length 1 input works. Check terminating character is applied. TEST(fxcodec, RLETestShortInput) { - const uint8_t src_buf[] = {1}; - uint8_t* dest_buf = nullptr; - uint32_t dest_size = 0; - CCodec_BasicModule* pEncoders = CCodec_ModuleMgr().GetBasicModule(); EXPECT_TRUE(pEncoders); + const uint8_t src_buf[] = {1}; + std::unique_ptr dest_buf; + uint32_t dest_size = 0; + EXPECT_TRUE(pEncoders->RunLengthEncode(src_buf, &dest_buf, &dest_size)); ASSERT_EQ(3u, dest_size); - EXPECT_EQ(0, dest_buf[0]); - EXPECT_EQ(1, dest_buf[1]); - EXPECT_EQ(128, dest_buf[2]); - - FX_Free(dest_buf); + auto dest_buf_span = pdfium::make_span(dest_buf.get(), dest_size); + EXPECT_EQ(0, dest_buf_span[0]); + EXPECT_EQ(1, dest_buf_span[1]); + EXPECT_EQ(128, dest_buf_span[2]); } // Check a few basic cases (2 matching runs in a row, matching run followed // by a non-matching run, and non-matching run followed by a matching run). TEST(fxcodec, RLETestNormalInputs) { - // Match, match - const uint8_t src_buf_1[] = {2, 2, 2, 2, 4, 4, 4, 4, 4, 4}; - - // Match, non-match - const uint8_t src_buf_2[] = {2, 2, 2, 2, 1, 2, 3, 4, 5, 6}; - - // Non-match, match - const uint8_t src_buf_3[] = {1, 2, 3, 4, 5, 3, 3, 3, 3, 3}; - - uint32_t dest_size = 0; - uint8_t* dest_buf = nullptr; - CCodec_BasicModule* pEncoders = CCodec_ModuleMgr().GetBasicModule(); EXPECT_TRUE(pEncoders); - // Case 1: - EXPECT_TRUE(pEncoders->RunLengthEncode(src_buf_1, &dest_buf, &dest_size)); + std::unique_ptr dest_buf; + uint32_t dest_size = 0; std::unique_ptr decoded_buf; uint32_t decoded_size = 0; - RunLengthDecode({dest_buf, dest_size}, &decoded_buf, &decoded_size); - ASSERT_EQ(sizeof(src_buf_1), decoded_size); - for (uint32_t i = 0; i < decoded_size; i++) - EXPECT_EQ(src_buf_1[i], decoded_buf.get()[i]) << " at " << i; - FX_Free(dest_buf); - - // Case 2: - dest_buf = nullptr; - dest_size = 0; - EXPECT_TRUE(pEncoders->RunLengthEncode(src_buf_2, &dest_buf, &dest_size)); - decoded_buf.reset(); - decoded_size = 0; - RunLengthDecode({dest_buf, dest_size}, &decoded_buf, &decoded_size); - ASSERT_EQ(sizeof(src_buf_2), decoded_size); - for (uint32_t i = 0; i < decoded_size; i++) - EXPECT_EQ(src_buf_2[i], decoded_buf.get()[i]) << " at " << i; - FX_Free(dest_buf); - - // Case 3: - dest_buf = nullptr; - dest_size = 0; - EXPECT_TRUE(pEncoders->RunLengthEncode(src_buf_3, &dest_buf, &dest_size)); - decoded_buf.reset(); - decoded_size = 0; - RunLengthDecode({dest_buf, dest_size}, &decoded_buf, &decoded_size); - ASSERT_EQ(sizeof(src_buf_3), decoded_size); - for (uint32_t i = 0; i < decoded_size; i++) - EXPECT_EQ(src_buf_3[i], decoded_buf.get()[i]) << " at " << i; - FX_Free(dest_buf); + + { + // Case 1: Match, match + const uint8_t src_buf_1[] = {2, 2, 2, 2, 4, 4, 4, 4, 4, 4}; + EXPECT_TRUE(pEncoders->RunLengthEncode(src_buf_1, &dest_buf, &dest_size)); + RunLengthDecode({dest_buf.get(), dest_size}, &decoded_buf, &decoded_size); + ASSERT_EQ(sizeof(src_buf_1), decoded_size); + auto decoded_buf_span = pdfium::make_span(decoded_buf.get(), decoded_size); + for (uint32_t i = 0; i < decoded_size; i++) + EXPECT_EQ(src_buf_1[i], decoded_buf_span[i]) << " at " << i; + } + + { + // Case 2: Match, non-match + const uint8_t src_buf_2[] = {2, 2, 2, 2, 1, 2, 3, 4, 5, 6}; + dest_buf.reset(); + dest_size = 0; + EXPECT_TRUE(pEncoders->RunLengthEncode(src_buf_2, &dest_buf, &dest_size)); + decoded_buf.reset(); + decoded_size = 0; + RunLengthDecode({dest_buf.get(), dest_size}, &decoded_buf, &decoded_size); + ASSERT_EQ(sizeof(src_buf_2), decoded_size); + auto decoded_buf_span = pdfium::make_span(decoded_buf.get(), decoded_size); + for (uint32_t i = 0; i < decoded_size; i++) + EXPECT_EQ(src_buf_2[i], decoded_buf_span[i]) << " at " << i; + } + + { + // Case 3: Non-match, match + const uint8_t src_buf_3[] = {1, 2, 3, 4, 5, 3, 3, 3, 3, 3}; + dest_buf.reset(); + dest_size = 0; + EXPECT_TRUE(pEncoders->RunLengthEncode(src_buf_3, &dest_buf, &dest_size)); + decoded_buf.reset(); + decoded_size = 0; + RunLengthDecode({dest_buf.get(), dest_size}, &decoded_buf, &decoded_size); + ASSERT_EQ(sizeof(src_buf_3), decoded_size); + auto decoded_buf_span = pdfium::make_span(decoded_buf.get(), decoded_size); + for (uint32_t i = 0; i < decoded_size; i++) + EXPECT_EQ(src_buf_3[i], decoded_buf_span[i]) << " at " << i; + } } // Check that runs longer than 128 are broken up properly, both matched and // non-matched. TEST(fxcodec, RLETestFullLengthInputs) { - // Match, match - const uint8_t src_buf_1[260] = {1}; - - // Match, non-match - uint8_t src_buf_2[260] = {2}; - for (uint16_t i = 128; i < 260; i++) - src_buf_2[i] = (uint8_t)(i - 125); - - // Non-match, match - uint8_t src_buf_3[260] = {3}; - for (uint8_t i = 0; i < 128; i++) - src_buf_3[i] = i; - - // Non-match, non-match - uint8_t src_buf_4[260]; - for (uint16_t i = 0; i < 260; i++) - src_buf_4[i] = (uint8_t)(i); - - uint32_t dest_size = 0; - uint8_t* dest_buf = nullptr; - CCodec_BasicModule* pEncoders = CCodec_ModuleMgr().GetBasicModule(); EXPECT_TRUE(pEncoders); - // Case 1: - EXPECT_TRUE(pEncoders->RunLengthEncode(src_buf_1, &dest_buf, &dest_size)); + std::unique_ptr dest_buf; + uint32_t dest_size = 0; std::unique_ptr decoded_buf; uint32_t decoded_size = 0; - RunLengthDecode({dest_buf, dest_size}, &decoded_buf, &decoded_size); - ASSERT_EQ(sizeof(src_buf_1), decoded_size); - for (uint32_t i = 0; i < decoded_size; i++) - EXPECT_EQ(src_buf_1[i], decoded_buf.get()[i]) << " at " << i; - FX_Free(dest_buf); - - // Case 2: - dest_buf = nullptr; - dest_size = 0; - EXPECT_TRUE(pEncoders->RunLengthEncode(src_buf_2, &dest_buf, &dest_size)); - decoded_buf.reset(); - decoded_size = 0; - RunLengthDecode({dest_buf, dest_size}, &decoded_buf, &decoded_size); - ASSERT_EQ(sizeof(src_buf_2), decoded_size); - for (uint32_t i = 0; i < decoded_size; i++) - EXPECT_EQ(src_buf_2[i], decoded_buf.get()[i]) << " at " << i; - FX_Free(dest_buf); - - // Case 3: - dest_buf = nullptr; - dest_size = 0; - EXPECT_TRUE(pEncoders->RunLengthEncode(src_buf_3, &dest_buf, &dest_size)); - decoded_buf.reset(); - decoded_size = 0; - RunLengthDecode({dest_buf, dest_size}, &decoded_buf, &decoded_size); - ASSERT_EQ(sizeof(src_buf_3), decoded_size); - for (uint32_t i = 0; i < decoded_size; i++) - EXPECT_EQ(src_buf_3[i], decoded_buf.get()[i]) << " at " << i; - FX_Free(dest_buf); - - // Case 4: - dest_buf = nullptr; - dest_size = 0; - EXPECT_TRUE(pEncoders->RunLengthEncode(src_buf_4, &dest_buf, &dest_size)); - decoded_buf.reset(); - decoded_size = 0; - RunLengthDecode({dest_buf, dest_size}, &decoded_buf, &decoded_size); - ASSERT_EQ(sizeof(src_buf_4), decoded_size); - for (uint32_t i = 0; i < decoded_size; i++) - EXPECT_EQ(src_buf_4[i], decoded_buf.get()[i]) << " at " << i; - FX_Free(dest_buf); + + { + // Case 1: Match, match + const uint8_t src_buf_1[260] = {1}; + EXPECT_TRUE(pEncoders->RunLengthEncode(src_buf_1, &dest_buf, &dest_size)); + RunLengthDecode({dest_buf.get(), dest_size}, &decoded_buf, &decoded_size); + ASSERT_EQ(sizeof(src_buf_1), decoded_size); + auto decoded_buf_span = pdfium::make_span(decoded_buf.get(), decoded_size); + for (uint32_t i = 0; i < decoded_size; i++) + EXPECT_EQ(src_buf_1[i], decoded_buf_span[i]) << " at " << i; + } + + { + // Case 2: Match, non-match + uint8_t src_buf_2[260] = {2}; + for (uint16_t i = 128; i < 260; i++) + src_buf_2[i] = static_cast(i - 125); + dest_buf.reset(); + dest_size = 0; + EXPECT_TRUE(pEncoders->RunLengthEncode(src_buf_2, &dest_buf, &dest_size)); + decoded_buf.reset(); + decoded_size = 0; + RunLengthDecode({dest_buf.get(), dest_size}, &decoded_buf, &decoded_size); + ASSERT_EQ(sizeof(src_buf_2), decoded_size); + auto decoded_buf_span = pdfium::make_span(decoded_buf.get(), decoded_size); + for (uint32_t i = 0; i < decoded_size; i++) + EXPECT_EQ(src_buf_2[i], decoded_buf_span[i]) << " at " << i; + } + + { + // Case 3: Non-match, match + uint8_t src_buf_3[260] = {3}; + for (uint8_t i = 0; i < 128; i++) + src_buf_3[i] = i; + dest_buf.reset(); + dest_size = 0; + EXPECT_TRUE(pEncoders->RunLengthEncode(src_buf_3, &dest_buf, &dest_size)); + decoded_buf.reset(); + decoded_size = 0; + RunLengthDecode({dest_buf.get(), dest_size}, &decoded_buf, &decoded_size); + ASSERT_EQ(sizeof(src_buf_3), decoded_size); + auto decoded_buf_span = pdfium::make_span(decoded_buf.get(), decoded_size); + for (uint32_t i = 0; i < decoded_size; i++) + EXPECT_EQ(src_buf_3[i], decoded_buf_span[i]) << " at " << i; + } + + { + // Case 4: Non-match, non-match + uint8_t src_buf_4[260]; + for (uint16_t i = 0; i < 260; i++) + src_buf_4[i] = static_cast(i); + dest_buf.reset(); + dest_size = 0; + EXPECT_TRUE(pEncoders->RunLengthEncode(src_buf_4, &dest_buf, &dest_size)); + decoded_buf.reset(); + decoded_size = 0; + RunLengthDecode({dest_buf.get(), dest_size}, &decoded_buf, &decoded_size); + ASSERT_EQ(sizeof(src_buf_4), decoded_size); + auto decoded_buf_span = pdfium::make_span(decoded_buf.get(), decoded_size); + for (uint32_t i = 0; i < decoded_size; i++) + EXPECT_EQ(src_buf_4[i], decoded_buf_span[i]) << " at " << i; + } } diff --git a/core/fxge/win32/cfx_psrenderer.cpp b/core/fxge/win32/cfx_psrenderer.cpp index e66e9685ff..11acfc8b3d 100644 --- a/core/fxge/win32/cfx_psrenderer.cpp +++ b/core/fxge/win32/cfx_psrenderer.cpp @@ -66,8 +66,10 @@ void PSCompressData(int PSLevel, *filter = "/FlateDecode filter "; } } else { - if (pEncoders->GetBasicModule()->RunLengthEncode({src_buf, src_size}, - &dest_buf, &dest_size)) { + std::unique_ptr dest_buf_unique; + if (pEncoders->GetBasicModule()->RunLengthEncode( + {src_buf, src_size}, &dest_buf_unique, &dest_size)) { + dest_buf = dest_buf_unique.release(); *filter = "/RunLengthDecode filter "; } } @@ -685,13 +687,12 @@ bool CFX_PSRenderer::DrawText(int nChars, } void CFX_PSRenderer::WritePSBinary(const uint8_t* data, int len) { - uint8_t* dest_buf; + std::unique_ptr dest_buf; uint32_t dest_size; CCodec_ModuleMgr* pEncoders = CPDF_ModuleMgr::Get()->GetCodecModule(); if (pEncoders->GetBasicModule()->A85Encode({data, static_cast(len)}, &dest_buf, &dest_size)) { - m_pStream->WriteBlock(dest_buf, dest_size); - FX_Free(dest_buf); + m_pStream->WriteBlock(dest_buf.get(), dest_size); } else { m_pStream->WriteBlock(data, len); } diff --git a/testing/fuzzers/pdf_codec_a85_fuzzer.cc b/testing/fuzzers/pdf_codec_a85_fuzzer.cc index 0da713b831..e45b81fa5e 100644 --- a/testing/fuzzers/pdf_codec_a85_fuzzer.cc +++ b/testing/fuzzers/pdf_codec_a85_fuzzer.cc @@ -9,10 +9,9 @@ #include "core/fxcrt/fx_memory.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - uint8_t* dest_buf = nullptr; + std::unique_ptr dest_buf; uint32_t dest_size = 0; CCodec_BasicModule encoder_module; encoder_module.A85Encode({data, size}, &dest_buf, &dest_size); - FX_Free(dest_buf); return 0; } diff --git a/testing/fuzzers/pdf_codec_rle_fuzzer.cc b/testing/fuzzers/pdf_codec_rle_fuzzer.cc index adf454ecbd..13c4a48c24 100644 --- a/testing/fuzzers/pdf_codec_rle_fuzzer.cc +++ b/testing/fuzzers/pdf_codec_rle_fuzzer.cc @@ -9,10 +9,9 @@ #include "core/fxcrt/fx_memory.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - uint8_t* dest_buf = nullptr; + std::unique_ptr dest_buf; uint32_t dest_size = 0; CCodec_BasicModule encoder_module; encoder_module.RunLengthEncode({data, size}, &dest_buf, &dest_size); - FX_Free(dest_buf); return 0; } -- cgit v1.2.3