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