1 // Copyright 2016 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <stdint.h>
6
7 #include <limits>
8 #include <memory>
9
10 #include "core/fpdfapi/parser/fpdf_parser_decode.h"
11 #include "core/fxcodec/basic/basicmodule.h"
12 #include "core/fxcrt/fx_memory_wrappers.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14
TEST(fxcodec,RLETestBadInputs)15 TEST(fxcodec, RLETestBadInputs) {
16 const uint8_t src_buf[] = {1};
17 std::unique_ptr<uint8_t, FxFreeDeleter> dest_buf;
18 uint32_t dest_size = 0;
19
20 // Error codes, not segvs, should callers pass us a nullptr pointer.
21 EXPECT_FALSE(BasicModule::RunLengthEncode(src_buf, &dest_buf, nullptr));
22 EXPECT_FALSE(BasicModule::RunLengthEncode(src_buf, nullptr, &dest_size));
23 EXPECT_FALSE(BasicModule::RunLengthEncode({}, &dest_buf, &dest_size));
24 }
25
26 // Check length 1 input works. Check terminating character is applied.
TEST(fxcodec,RLETestShortInput)27 TEST(fxcodec, RLETestShortInput) {
28 const uint8_t src_buf[] = {1};
29 std::unique_ptr<uint8_t, FxFreeDeleter> dest_buf;
30 uint32_t dest_size = 0;
31
32 EXPECT_TRUE(BasicModule::RunLengthEncode(src_buf, &dest_buf, &dest_size));
33 ASSERT_EQ(3u, dest_size);
34 auto dest_buf_span = pdfium::make_span(dest_buf.get(), dest_size);
35 EXPECT_EQ(0, dest_buf_span[0]);
36 EXPECT_EQ(1, dest_buf_span[1]);
37 EXPECT_EQ(128, dest_buf_span[2]);
38 }
39
40 // Check a few basic cases (2 matching runs in a row, matching run followed
41 // by a non-matching run, and non-matching run followed by a matching run).
TEST(fxcodec,RLETestNormalInputs)42 TEST(fxcodec, RLETestNormalInputs) {
43 std::unique_ptr<uint8_t, FxFreeDeleter> dest_buf;
44 uint32_t dest_size = 0;
45 std::unique_ptr<uint8_t, FxFreeDeleter> decoded_buf;
46 uint32_t decoded_size = 0;
47
48 {
49 // Case 1: Match, match
50 const uint8_t src_buf_1[] = {2, 2, 2, 2, 4, 4, 4, 4, 4, 4};
51 EXPECT_TRUE(BasicModule::RunLengthEncode(src_buf_1, &dest_buf, &dest_size));
52 RunLengthDecode({dest_buf.get(), dest_size}, &decoded_buf, &decoded_size);
53 ASSERT_EQ(sizeof(src_buf_1), decoded_size);
54 auto decoded_buf_span = pdfium::make_span(decoded_buf.get(), decoded_size);
55 for (uint32_t i = 0; i < decoded_size; i++)
56 EXPECT_EQ(src_buf_1[i], decoded_buf_span[i]) << " at " << i;
57 }
58
59 {
60 // Case 2: Match, non-match
61 const uint8_t src_buf_2[] = {2, 2, 2, 2, 1, 2, 3, 4, 5, 6};
62 dest_buf.reset();
63 dest_size = 0;
64 EXPECT_TRUE(BasicModule::RunLengthEncode(src_buf_2, &dest_buf, &dest_size));
65 decoded_buf.reset();
66 decoded_size = 0;
67 RunLengthDecode({dest_buf.get(), dest_size}, &decoded_buf, &decoded_size);
68 ASSERT_EQ(sizeof(src_buf_2), decoded_size);
69 auto decoded_buf_span = pdfium::make_span(decoded_buf.get(), decoded_size);
70 for (uint32_t i = 0; i < decoded_size; i++)
71 EXPECT_EQ(src_buf_2[i], decoded_buf_span[i]) << " at " << i;
72 }
73
74 {
75 // Case 3: Non-match, match
76 const uint8_t src_buf_3[] = {1, 2, 3, 4, 5, 3, 3, 3, 3, 3};
77 dest_buf.reset();
78 dest_size = 0;
79 EXPECT_TRUE(BasicModule::RunLengthEncode(src_buf_3, &dest_buf, &dest_size));
80 decoded_buf.reset();
81 decoded_size = 0;
82 RunLengthDecode({dest_buf.get(), dest_size}, &decoded_buf, &decoded_size);
83 ASSERT_EQ(sizeof(src_buf_3), decoded_size);
84 auto decoded_buf_span = pdfium::make_span(decoded_buf.get(), decoded_size);
85 for (uint32_t i = 0; i < decoded_size; i++)
86 EXPECT_EQ(src_buf_3[i], decoded_buf_span[i]) << " at " << i;
87 }
88 }
89
90 // Check that runs longer than 128 are broken up properly, both matched and
91 // non-matched.
TEST(fxcodec,RLETestFullLengthInputs)92 TEST(fxcodec, RLETestFullLengthInputs) {
93 std::unique_ptr<uint8_t, FxFreeDeleter> dest_buf;
94 uint32_t dest_size = 0;
95 std::unique_ptr<uint8_t, FxFreeDeleter> decoded_buf;
96 uint32_t decoded_size = 0;
97
98 {
99 // Case 1: Match, match
100 const uint8_t src_buf_1[260] = {1};
101 EXPECT_TRUE(BasicModule::RunLengthEncode(src_buf_1, &dest_buf, &dest_size));
102 RunLengthDecode({dest_buf.get(), dest_size}, &decoded_buf, &decoded_size);
103 ASSERT_EQ(sizeof(src_buf_1), decoded_size);
104 auto decoded_buf_span = pdfium::make_span(decoded_buf.get(), decoded_size);
105 for (uint32_t i = 0; i < decoded_size; i++)
106 EXPECT_EQ(src_buf_1[i], decoded_buf_span[i]) << " at " << i;
107 }
108
109 {
110 // Case 2: Match, non-match
111 uint8_t src_buf_2[260] = {2};
112 for (uint16_t i = 128; i < 260; i++)
113 src_buf_2[i] = static_cast<uint8_t>(i - 125);
114 dest_buf.reset();
115 dest_size = 0;
116 EXPECT_TRUE(BasicModule::RunLengthEncode(src_buf_2, &dest_buf, &dest_size));
117 decoded_buf.reset();
118 decoded_size = 0;
119 RunLengthDecode({dest_buf.get(), dest_size}, &decoded_buf, &decoded_size);
120 ASSERT_EQ(sizeof(src_buf_2), decoded_size);
121 auto decoded_buf_span = pdfium::make_span(decoded_buf.get(), decoded_size);
122 for (uint32_t i = 0; i < decoded_size; i++)
123 EXPECT_EQ(src_buf_2[i], decoded_buf_span[i]) << " at " << i;
124 }
125
126 {
127 // Case 3: Non-match, match
128 uint8_t src_buf_3[260] = {3};
129 for (uint8_t i = 0; i < 128; i++)
130 src_buf_3[i] = i;
131 dest_buf.reset();
132 dest_size = 0;
133 EXPECT_TRUE(BasicModule::RunLengthEncode(src_buf_3, &dest_buf, &dest_size));
134 decoded_buf.reset();
135 decoded_size = 0;
136 RunLengthDecode({dest_buf.get(), dest_size}, &decoded_buf, &decoded_size);
137 ASSERT_EQ(sizeof(src_buf_3), decoded_size);
138 auto decoded_buf_span = pdfium::make_span(decoded_buf.get(), decoded_size);
139 for (uint32_t i = 0; i < decoded_size; i++)
140 EXPECT_EQ(src_buf_3[i], decoded_buf_span[i]) << " at " << i;
141 }
142
143 {
144 // Case 4: Non-match, non-match
145 uint8_t src_buf_4[260];
146 for (uint16_t i = 0; i < 260; i++)
147 src_buf_4[i] = static_cast<uint8_t>(i);
148 dest_buf.reset();
149 dest_size = 0;
150 EXPECT_TRUE(BasicModule::RunLengthEncode(src_buf_4, &dest_buf, &dest_size));
151 decoded_buf.reset();
152 decoded_size = 0;
153 RunLengthDecode({dest_buf.get(), dest_size}, &decoded_buf, &decoded_size);
154 ASSERT_EQ(sizeof(src_buf_4), decoded_size);
155 auto decoded_buf_span = pdfium::make_span(decoded_buf.get(), decoded_size);
156 for (uint32_t i = 0; i < decoded_size; i++)
157 EXPECT_EQ(src_buf_4[i], decoded_buf_span[i]) << " at " << i;
158 }
159 }
160