1 // Copyright 2017 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 "core/fxcodec/gif/cfx_lzwdecompressor.h"
6
7 #include "core/fxcrt/fx_memory.h"
8 #include "testing/gtest/include/gtest/gtest.h"
9
TEST(CFX_LZWDecompressor,CreateBadParams)10 TEST(CFX_LZWDecompressor, CreateBadParams) {
11 EXPECT_EQ(nullptr, CFX_LZWDecompressor::Create(0x10, 0x02));
12 EXPECT_EQ(nullptr, CFX_LZWDecompressor::Create(0x04, 0x0F));
13 EXPECT_EQ(nullptr, CFX_LZWDecompressor::Create(0x02, 0x02));
14 }
15
TEST(CFX_LZWDecompressor,ExtractData)16 TEST(CFX_LZWDecompressor, ExtractData) {
17 uint8_t palette_exp = 0x1;
18 uint8_t code_exp = 0x2;
19 auto decompressor = CFX_LZWDecompressor::Create(palette_exp, code_exp);
20 ASSERT_NE(nullptr, decompressor);
21
22 // Check that 0 length extract does nothing
23 {
24 std::vector<uint8_t>* decompressed = decompressor->DecompressedForTest();
25 *decompressed = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
26 *(decompressor->DecompressedNextForTest()) = decompressed->size();
27 uint8_t dest_buf[20];
28 memset(dest_buf, static_cast<uint8_t>(-1), sizeof(dest_buf));
29
30 EXPECT_EQ(0u, decompressor->ExtractDataForTest(dest_buf, 0));
31 for (size_t i = 0; i < FX_ArraySize(dest_buf); ++i)
32 EXPECT_EQ(static_cast<uint8_t>(-1), dest_buf[i]);
33
34 EXPECT_EQ(10u, *(decompressor->DecompressedNextForTest()));
35 for (size_t i = 0; i < *(decompressor->DecompressedNextForTest()); ++i)
36 EXPECT_EQ(i, (*decompressed)[i]);
37 }
38
39 // Check that less than decompressed size only gets the expected number
40 {
41 std::vector<uint8_t>* decompressed = decompressor->DecompressedForTest();
42 *decompressed = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
43 *(decompressor->DecompressedNextForTest()) = decompressed->size();
44 uint8_t dest_buf[20];
45 memset(dest_buf, static_cast<uint8_t>(-1), sizeof(dest_buf));
46
47 EXPECT_EQ(5u, decompressor->ExtractDataForTest(dest_buf, 5));
48 size_t i = 0;
49 for (; i < 5; ++i)
50 EXPECT_EQ(9 - i, dest_buf[i]);
51 for (; i < FX_ArraySize(dest_buf); ++i)
52 EXPECT_EQ(static_cast<uint8_t>(-1), dest_buf[i]);
53
54 EXPECT_EQ(5u, *(decompressor->DecompressedNextForTest()));
55 for (i = 0; i < *(decompressor->DecompressedNextForTest()); ++i)
56 EXPECT_EQ(i, (*decompressed)[i]);
57 }
58
59 // Check that greater than decompressed size depletes the decompressor
60 {
61 std::vector<uint8_t>* decompressed = decompressor->DecompressedForTest();
62 *decompressed = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
63 *(decompressor->DecompressedNextForTest()) = decompressed->size();
64 uint8_t dest_buf[20];
65 memset(dest_buf, static_cast<uint8_t>(-1), sizeof(dest_buf));
66
67 EXPECT_EQ(10u, decompressor->ExtractDataForTest(dest_buf,
68 FX_ArraySize(dest_buf)));
69 size_t i = 0;
70 for (; i < 10; ++i)
71 EXPECT_EQ(9 - i, dest_buf[i]);
72 for (; i < FX_ArraySize(dest_buf); ++i)
73 EXPECT_EQ(static_cast<uint8_t>(-1), dest_buf[i]);
74
75 EXPECT_EQ(0u, *(decompressor->DecompressedNextForTest()));
76 }
77 }
78
TEST(CFX_LZWDecompressor,DecodeBadParams)79 TEST(CFX_LZWDecompressor, DecodeBadParams) {
80 uint8_t palette_exp = 0x0;
81 uint8_t code_exp = 0x2;
82 auto decompressor = CFX_LZWDecompressor::Create(palette_exp, code_exp);
83 ASSERT_NE(nullptr, decompressor);
84
85 uint8_t image_data[10];
86 uint32_t image_size = FX_ArraySize(image_data);
87
88 uint8_t output_data[10];
89 uint32_t output_size = FX_ArraySize(output_data);
90
91 EXPECT_EQ(
92 CFX_GifDecodeStatus::Error,
93 decompressor->Decode(nullptr, image_size, output_data, &output_size));
94 EXPECT_EQ(CFX_GifDecodeStatus::Error,
95 decompressor->Decode(image_data, 0, output_data, &output_size));
96 EXPECT_EQ(
97 CFX_GifDecodeStatus::Error,
98 decompressor->Decode(image_data, image_size, nullptr, &output_size));
99 EXPECT_EQ(CFX_GifDecodeStatus::Error,
100 decompressor->Decode(image_data, image_size, output_data, nullptr));
101
102 output_size = 0;
103 EXPECT_EQ(
104 CFX_GifDecodeStatus::InsufficientDestSize,
105 decompressor->Decode(image_data, image_size, output_data, &output_size));
106 }
107
TEST(CFX_LZWDecompressor,Decode1x1SingleColour)108 TEST(CFX_LZWDecompressor, Decode1x1SingleColour) {
109 uint8_t palette_exp = 0x0;
110 uint8_t code_exp = 0x2;
111 auto decompressor = CFX_LZWDecompressor::Create(palette_exp, code_exp);
112 ASSERT_NE(nullptr, decompressor);
113
114 uint8_t image_data[] = {0x44, 0x01};
115 uint32_t image_size = FX_ArraySize(image_data);
116
117 uint8_t expected_data[] = {0x00};
118 uint8_t output_data[FX_ArraySize(expected_data)];
119 memset(output_data, 0, sizeof(output_data));
120 uint32_t output_size = FX_ArraySize(output_data);
121
122 EXPECT_EQ(
123 CFX_GifDecodeStatus::Success,
124 decompressor->Decode(image_data, image_size, output_data, &output_size));
125
126 EXPECT_EQ(FX_ArraySize(output_data), output_size);
127 EXPECT_TRUE(0 == memcmp(expected_data, output_data, sizeof(expected_data)));
128 }
129
TEST(CFX_LZWDecompressor,Decode10x10SingleColour)130 TEST(CFX_LZWDecompressor, Decode10x10SingleColour) {
131 uint8_t palette_exp = 0x0;
132 uint8_t code_exp = 0x2;
133 auto decompressor = CFX_LZWDecompressor::Create(palette_exp, code_exp);
134 ASSERT_NE(nullptr, decompressor);
135
136 static constexpr uint8_t kImageData[] = {0x84, 0x8F, 0xA9, 0xCB,
137 0xED, 0x0F, 0x63, 0x2B};
138 uint32_t image_size = FX_ArraySize(kImageData);
139
140 static constexpr uint8_t kExpectedData[] = {
141 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
142 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
143 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
144 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
145 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
146 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
147 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
148 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
149 0x00, 0x00, 0x00, 0x00};
150 uint8_t output_data[FX_ArraySize(kExpectedData)];
151 memset(output_data, 0, sizeof(output_data));
152 uint32_t output_size = FX_ArraySize(output_data);
153
154 EXPECT_EQ(
155 CFX_GifDecodeStatus::Success,
156 decompressor->Decode(kImageData, image_size, output_data, &output_size));
157
158 EXPECT_EQ(FX_ArraySize(output_data), output_size);
159 EXPECT_TRUE(0 == memcmp(kExpectedData, output_data, sizeof(kExpectedData)));
160 }
161
TEST(CFX_LZWDecompressor,Decode10x10MultipleColour)162 TEST(CFX_LZWDecompressor, Decode10x10MultipleColour) {
163 uint8_t palette_exp = 0x1;
164 uint8_t code_exp = 0x2;
165 auto decompressor = CFX_LZWDecompressor::Create(palette_exp, code_exp);
166 ASSERT_NE(nullptr, decompressor);
167
168 static constexpr uint8_t kImageData[] = {
169 0x8C, 0x2D, 0x99, 0x87, 0x2A, 0x1C, 0xDC, 0x33, 0xA0, 0x02, 0x75,
170 0xEC, 0x95, 0xFA, 0xA8, 0xDE, 0x60, 0x8C, 0x04, 0x91, 0x4C, 0x01};
171 uint32_t image_size = FX_ArraySize(kImageData);
172
173 static constexpr uint8_t kExpectedData[] = {
174 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01,
175 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
176 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
177 0x00, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02,
178 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
179 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02,
180 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02,
181 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01,
182 0x01, 0x01, 0x01, 0x01};
183
184 uint8_t output_data[FX_ArraySize(kExpectedData)];
185 memset(output_data, 0, sizeof(output_data));
186 uint32_t output_size = FX_ArraySize(output_data);
187
188 EXPECT_EQ(
189 CFX_GifDecodeStatus::Success,
190 decompressor->Decode(kImageData, image_size, output_data, &output_size));
191
192 EXPECT_EQ(FX_ArraySize(output_data), output_size);
193 EXPECT_TRUE(0 == memcmp(kExpectedData, output_data, sizeof(kExpectedData)));
194 }
195
TEST(CFX_LZWDecompressor,HandleColourCodeOutOfPalette)196 TEST(CFX_LZWDecompressor, HandleColourCodeOutOfPalette) {
197 uint8_t palette_exp = 0x2; // Image uses 10 colours, so the palette exp
198 // should be 3, 2^(3+1) = 16 colours.
199 uint8_t code_exp = 0x4;
200 auto decompressor = CFX_LZWDecompressor::Create(palette_exp, code_exp);
201 ASSERT_NE(nullptr, decompressor);
202
203 static constexpr uint8_t kImageData[] = {
204 0x30, 0xC9, 0x49, 0x81, 0xBD, 0x78, 0xE8, 0xCD, 0x89, 0xFF,
205 0x60, 0x20, 0x8E, 0xE4, 0x61, 0x9E, 0xA8, 0xA1, 0xAE, 0x2C,
206 0xE2, 0xBE, 0xB0, 0x20, 0xCF, 0x74, 0x61, 0xDF, 0x78, 0x04};
207 uint32_t image_size = FX_ArraySize(kImageData);
208
209 uint8_t output_data[100]; // The uncompressed data is for a 10x10 image
210 memset(output_data, 0, sizeof(output_data));
211 uint32_t output_size = FX_ArraySize(output_data);
212
213 EXPECT_EQ(
214 CFX_GifDecodeStatus::Error,
215 decompressor->Decode(kImageData, image_size, output_data, &output_size));
216 }
217