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