// Copyright 2016 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include #include #include #include "core/fpdfapi/parser/fpdf_parser_decode.h" #include "core/fxcodec/codec/ccodec_basicmodule.h" #include "core/fxcodec/fx_codec.h" #include "testing/gtest/include/gtest/gtest.h" TEST(fxcodec, RLETestBadInputs) { const uint8_t src_buf[] = {1}; std::unique_ptr dest_buf; uint32_t dest_size = 0; CCodec_BasicModule* pEncoders = CCodec_ModuleMgr().GetBasicModule(); EXPECT_TRUE(pEncoders); // Error codes, not segvs, should callers pass us a nullptr pointer. EXPECT_FALSE(pEncoders->RunLengthEncode(src_buf, &dest_buf, nullptr)); EXPECT_FALSE(pEncoders->RunLengthEncode(src_buf, nullptr, &dest_size)); EXPECT_FALSE(pEncoders->RunLengthEncode({}, &dest_buf, &dest_size)); } // Check length 1 input works. Check terminating character is applied. TEST(fxcodec, RLETestShortInput) { 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); 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) { CCodec_BasicModule* pEncoders = CCodec_ModuleMgr().GetBasicModule(); EXPECT_TRUE(pEncoders); std::unique_ptr dest_buf; uint32_t dest_size = 0; std::unique_ptr decoded_buf; uint32_t decoded_size = 0; { // 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) { CCodec_BasicModule* pEncoders = CCodec_ModuleMgr().GetBasicModule(); EXPECT_TRUE(pEncoders); std::unique_ptr dest_buf; uint32_t dest_size = 0; std::unique_ptr decoded_buf; uint32_t decoded_size = 0; { // 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; } }