• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_gifcontext.h"
6 
7 #include "core/fxcrt/unowned_ptr.h"
8 #include "testing/gtest/include/gtest/gtest.h"
9 
10 class CFX_GifContextForTest : public CFX_GifContext {
11  public:
CFX_GifContextForTest(CCodec_GifModule * gif_module,CCodec_GifModule::Delegate * delegate)12   CFX_GifContextForTest(CCodec_GifModule* gif_module,
13                         CCodec_GifModule::Delegate* delegate)
14       : CFX_GifContext(gif_module, delegate) {}
~CFX_GifContextForTest()15   ~CFX_GifContextForTest() override {}
16 
17   using CFX_GifContext::ReadData;
18   using CFX_GifContext::ReadGifSignature;
19   using CFX_GifContext::ReadLogicalScreenDescriptor;
20 };
21 
TEST(CFX_GifContext,SetInputBuffer)22 TEST(CFX_GifContext, SetInputBuffer) {
23   CFX_GifContextForTest context(nullptr, nullptr);
24 
25   context.SetInputBuffer(nullptr, 0);
26   EXPECT_EQ(nullptr, context.next_in_);
27   EXPECT_EQ(0u, context.avail_in_);
28   EXPECT_EQ(0u, context.skip_size_);
29 
30   context.SetInputBuffer(nullptr, 100);
31   EXPECT_EQ(nullptr, context.next_in_);
32   EXPECT_EQ(100u, context.avail_in_);
33   EXPECT_EQ(0u, context.skip_size_);
34 
35   uint8_t buffer[] = {0x00, 0x01, 0x02};
36   context.SetInputBuffer(buffer, 0);
37   EXPECT_EQ(buffer, context.next_in_);
38   EXPECT_EQ(0u, context.avail_in_);
39   EXPECT_EQ(0u, context.skip_size_);
40 
41   context.SetInputBuffer(buffer, 3);
42   EXPECT_EQ(buffer, context.next_in_);
43   EXPECT_EQ(3u, context.avail_in_);
44   EXPECT_EQ(0u, context.skip_size_);
45 
46   context.SetInputBuffer(buffer, 100);
47   EXPECT_EQ(buffer, context.next_in_);
48   EXPECT_EQ(100u, context.avail_in_);
49   EXPECT_EQ(0u, context.skip_size_);
50 }
51 
TEST(CFX_GifContext,ReadData)52 TEST(CFX_GifContext, ReadData) {
53   CFX_GifContextForTest context(nullptr, nullptr);
54 
55   context.SetInputBuffer(nullptr, 0);
56   EXPECT_EQ(nullptr, context.ReadData(nullptr, 0));
57   EXPECT_EQ(nullptr, context.ReadData(nullptr, 10));
58 
59   uint8_t* dest_buffer = nullptr;
60   EXPECT_EQ(nullptr,
61             context.ReadData(reinterpret_cast<uint8_t**>(&dest_buffer), 0));
62   EXPECT_EQ(nullptr,
63             context.ReadData(reinterpret_cast<uint8_t**>(&dest_buffer), 10));
64 
65   uint8_t src_buffer[] = {0x00, 0x01, 0x02, 0x03, 0x04,
66                           0x05, 0x06, 0x07, 0x08, 0x09};
67   context.SetInputBuffer(src_buffer, 0);
68   EXPECT_EQ(nullptr,
69             context.ReadData(reinterpret_cast<uint8_t**>(&dest_buffer), 10));
70   EXPECT_EQ(reinterpret_cast<uint8_t*>(src_buffer), context.next_in_);
71   EXPECT_EQ(0u, context.avail_in_);
72   EXPECT_EQ(0u, context.skip_size_);
73 
74   dest_buffer = nullptr;
75   context.SetInputBuffer(src_buffer, 10);
76   EXPECT_EQ(src_buffer,
77             context.ReadData(reinterpret_cast<uint8_t**>(&dest_buffer), 10));
78   EXPECT_EQ(reinterpret_cast<uint8_t*>(src_buffer), dest_buffer);
79   EXPECT_EQ(src_buffer, context.next_in_);
80   EXPECT_EQ(10u, context.avail_in_);
81   EXPECT_EQ(10u, context.skip_size_);
82 
83   dest_buffer = nullptr;
84   context.SetInputBuffer(src_buffer, 10);
85   EXPECT_EQ(src_buffer,
86             context.ReadData(reinterpret_cast<uint8_t**>(&dest_buffer), 5));
87   EXPECT_EQ(reinterpret_cast<uint8_t*>(src_buffer), dest_buffer);
88   EXPECT_EQ(src_buffer, context.next_in_);
89   EXPECT_EQ(10u, context.avail_in_);
90   EXPECT_EQ(5u, context.skip_size_);
91 
92   dest_buffer = nullptr;
93   EXPECT_EQ(src_buffer + 5,
94             context.ReadData(reinterpret_cast<uint8_t**>(&dest_buffer), 5));
95   EXPECT_EQ(reinterpret_cast<uint8_t*>(src_buffer + 5), dest_buffer);
96   EXPECT_EQ(src_buffer, context.next_in_);
97   EXPECT_EQ(10u, context.avail_in_);
98   EXPECT_EQ(10u, context.skip_size_);
99 
100   dest_buffer = nullptr;
101   EXPECT_EQ(nullptr,
102             context.ReadData(reinterpret_cast<uint8_t**>(&dest_buffer), 5));
103   EXPECT_EQ(nullptr, dest_buffer);
104   EXPECT_EQ(src_buffer, context.next_in_);
105   EXPECT_EQ(10u, context.avail_in_);
106   EXPECT_EQ(10u, context.skip_size_);
107 }
108 
TEST(CFX_GifContext,ReadGifSignature)109 TEST(CFX_GifContext, ReadGifSignature) {
110   CFX_GifContextForTest context(nullptr, nullptr);
111 
112   {
113     uint8_t data[1];
114     context.SetInputBuffer(data, 0);
115     EXPECT_EQ(CFX_GifDecodeStatus::Unfinished, context.ReadGifSignature());
116     EXPECT_EQ(0u, context.skip_size_);
117   }
118   // Make sure testing the entire signature
119   {
120     uint8_t data[] = {'G', 'I', 'F'};
121     context.SetInputBuffer(data, sizeof(data));
122     EXPECT_EQ(CFX_GifDecodeStatus::Unfinished, context.ReadGifSignature());
123     EXPECT_EQ(0u, context.skip_size_);
124   }
125   {
126     uint8_t data[] = {'N', 'O', 'T', 'G', 'I', 'F'};
127     context.SetInputBuffer(data, sizeof(data));
128     EXPECT_EQ(CFX_GifDecodeStatus::Error, context.ReadGifSignature());
129     EXPECT_EQ(6u, context.skip_size_);
130   }
131   // Make sure not matching GIF8*a
132   {
133     uint8_t data[] = {'G', 'I', 'F', '8', '0', 'a'};
134     context.SetInputBuffer(data, sizeof(data));
135     EXPECT_EQ(CFX_GifDecodeStatus::Error, context.ReadGifSignature());
136     EXPECT_EQ(6u, context.skip_size_);
137   }
138   // Make sure not matching GIF**a
139   {
140     uint8_t data[] = {'G', 'I', 'F', '9', '2', 'a'};
141     context.SetInputBuffer(data, sizeof(data));
142     EXPECT_EQ(CFX_GifDecodeStatus::Error, context.ReadGifSignature());
143     EXPECT_EQ(6u, context.skip_size_);
144   }
145   // One valid signature
146   {
147     uint8_t data[] = {'G', 'I', 'F', '8', '7', 'a'};
148     context.SetInputBuffer(data, sizeof(data));
149     EXPECT_EQ(CFX_GifDecodeStatus::Success, context.ReadGifSignature());
150     EXPECT_EQ(6u, context.skip_size_);
151   }
152   // The other valid signature
153   {
154     uint8_t data[] = {'G', 'I', 'F', '8', '9', 'a'};
155     context.SetInputBuffer(data, sizeof(data));
156     EXPECT_EQ(CFX_GifDecodeStatus::Success, context.ReadGifSignature());
157     EXPECT_EQ(6u, context.skip_size_);
158   }
159 }
160 
TEST(CFX_GifContext,ReadLocalScreenDescriptor)161 TEST(CFX_GifContext, ReadLocalScreenDescriptor) {
162   CFX_GifContextForTest context(nullptr, nullptr);
163   {
164     uint8_t data[1];
165     context.SetInputBuffer(data, 0);
166     EXPECT_EQ(CFX_GifDecodeStatus::Unfinished,
167               context.ReadLogicalScreenDescriptor());
168   }
169   // LSD with all the values zero'd
170   {
171     uint8_t lsd[sizeof(CFX_GifLocalScreenDescriptor)];
172     memset(&lsd, 0, sizeof(CFX_GifLocalScreenDescriptor));
173     context.SetInputBuffer(lsd, sizeof(CFX_GifLocalScreenDescriptor));
174 
175     EXPECT_EQ(CFX_GifDecodeStatus::Success,
176               context.ReadLogicalScreenDescriptor());
177 
178     EXPECT_EQ(sizeof(CFX_GifLocalScreenDescriptor), context.skip_size_);
179     EXPECT_EQ(0, context.width_);
180     EXPECT_EQ(0, context.height_);
181     EXPECT_EQ(0u, context.bc_index_);
182     EXPECT_EQ(0u, context.pixel_aspect_);
183   }
184   // LSD with no global palette
185   {
186     uint8_t lsd[sizeof(CFX_GifLocalScreenDescriptor)] = {0x0A, 0x00, 0x00, 0x0F,
187                                                          0x00, 0x01, 0x02};
188     context.SetInputBuffer(lsd, sizeof(CFX_GifLocalScreenDescriptor));
189 
190     EXPECT_EQ(CFX_GifDecodeStatus::Success,
191               context.ReadLogicalScreenDescriptor());
192 
193     EXPECT_EQ(sizeof(CFX_GifLocalScreenDescriptor), context.skip_size_);
194     EXPECT_EQ(0x000A, context.width_);
195     EXPECT_EQ(0x0F00, context.height_);
196     EXPECT_EQ(0u, context.bc_index_);  // bc_index_ is 0 if no global palette
197     EXPECT_EQ(2u, context.pixel_aspect_);
198   }
199   // LSD with global palette bit set, but no global palette
200   {
201     uint8_t lsd[sizeof(CFX_GifLocalScreenDescriptor)] = {0x0A, 0x00, 0x00, 0x0F,
202                                                          0x80, 0x01, 0x02};
203     context.SetInputBuffer(lsd, sizeof(CFX_GifLocalScreenDescriptor));
204 
205     EXPECT_EQ(CFX_GifDecodeStatus::Unfinished,
206               context.ReadLogicalScreenDescriptor());
207 
208     EXPECT_EQ(0u, context.skip_size_);
209   }
210   // LSD with global palette
211   {
212     struct {
213       uint8_t lsd[sizeof(CFX_GifLocalScreenDescriptor)];
214       uint8_t palette[4 * sizeof(CFX_GifPalette)];
215     } data = {{0x0A, 0x00, 0x00, 0x0F, 0xA9, 0x01, 0x02},
216               {0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1}};
217     context.SetInputBuffer(reinterpret_cast<uint8_t*>(&data), sizeof(data));
218 
219     EXPECT_EQ(CFX_GifDecodeStatus::Success,
220               context.ReadLogicalScreenDescriptor());
221 
222     EXPECT_EQ(sizeof(data), context.skip_size_);
223     EXPECT_EQ(0x000A, context.width_);
224     EXPECT_EQ(0x0F00, context.height_);
225     EXPECT_EQ(1u, context.bc_index_);
226     EXPECT_EQ(2u, context.pixel_aspect_);
227 
228     EXPECT_EQ(1u, context.global_pal_exp_);
229     EXPECT_EQ(1, context.global_sort_flag_);
230     EXPECT_EQ(2, context.global_color_resolution_);
231     EXPECT_TRUE(0 == memcmp(data.palette, context.global_palette_.data(),
232                             sizeof(data.palette)));
233   }
234 }
235 
TEST(CFX_GifContext,ReadHeader)236 TEST(CFX_GifContext, ReadHeader) {
237   CFX_GifContextForTest context(nullptr, nullptr);
238   // Bad signature
239   {
240     struct {
241       uint8_t signature[6];
242       uint8_t lsd[sizeof(CFX_GifLocalScreenDescriptor)];
243     } data = {{'N', 'O', 'T', 'G', 'I', 'F'},
244               {0x0A, 0x00, 0x00, 0x0F, 0x00, 0x01, 0x02}};
245     context.SetInputBuffer(reinterpret_cast<uint8_t*>(&data), sizeof(data));
246 
247     EXPECT_EQ(CFX_GifDecodeStatus::Error, context.ReadHeader());
248 
249     EXPECT_EQ(sizeof(data.signature), context.skip_size_);
250   }
251   // Short after signature
252   {
253     uint8_t signature[] = {'G', 'I', 'F', '8', '7', 'a'};
254     context.SetInputBuffer(reinterpret_cast<uint8_t*>(&signature),
255                            sizeof(signature));
256 
257     EXPECT_EQ(CFX_GifDecodeStatus::Unfinished, context.ReadHeader());
258 
259     EXPECT_EQ(sizeof(signature), context.skip_size_);
260   }
261   // Success without global palette
262   {
263     struct {
264       uint8_t signature[6];
265       uint8_t lsd[sizeof(CFX_GifLocalScreenDescriptor)];
266     } data = {{'G', 'I', 'F', '8', '7', 'a'},
267               {0x0A, 0x00, 0x00, 0x0F, 0x00, 0x01, 0x02}};
268     context.SetInputBuffer(reinterpret_cast<uint8_t*>(&data), sizeof(data));
269 
270     EXPECT_EQ(CFX_GifDecodeStatus::Success, context.ReadHeader());
271 
272     EXPECT_EQ(sizeof(data), context.skip_size_);
273     EXPECT_EQ(0x000A, context.width_);
274     EXPECT_EQ(0x0F00, context.height_);
275     EXPECT_EQ(0u, context.bc_index_);  // bc_index_ is 0 if no global palette
276     EXPECT_EQ(2u, context.pixel_aspect_);
277   }
278   // Missing Global Palette
279   {
280     struct {
281       uint8_t signature[6];
282       uint8_t lsd[sizeof(CFX_GifLocalScreenDescriptor)];
283     } data = {{'G', 'I', 'F', '8', '7', 'a'},
284               {0x0A, 0x00, 0x00, 0x0F, 0x80, 0x01, 0x02}};
285     context.SetInputBuffer(reinterpret_cast<uint8_t*>(&data), sizeof(data));
286 
287     EXPECT_EQ(CFX_GifDecodeStatus::Unfinished, context.ReadHeader());
288 
289     EXPECT_EQ(sizeof(data.signature), context.skip_size_);
290   }
291   // Success with global palette
292   {
293     struct {
294       uint8_t signature[6];
295       uint8_t lsd[sizeof(CFX_GifLocalScreenDescriptor)];
296       uint8_t palette[4 * sizeof(CFX_GifPalette)];
297     } data = {{'G', 'I', 'F', '8', '7', 'a'},
298               {0x0A, 0x00, 0x00, 0x0F, 0xA9, 0x01, 0x02},
299               {0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1}};
300     context.SetInputBuffer(reinterpret_cast<uint8_t*>(&data), sizeof(data));
301 
302     EXPECT_EQ(CFX_GifDecodeStatus::Success, context.ReadHeader());
303 
304     EXPECT_EQ(sizeof(data), context.skip_size_);
305     EXPECT_EQ(0x000A, context.width_);
306     EXPECT_EQ(0x0F00, context.height_);
307     EXPECT_EQ(1u, context.bc_index_);
308     EXPECT_EQ(2u, context.pixel_aspect_);
309     EXPECT_EQ(1u, context.global_pal_exp_);
310     EXPECT_EQ(1, context.global_sort_flag_);
311     EXPECT_EQ(2, context.global_color_resolution_);
312     EXPECT_TRUE(0 == memcmp(data.palette, context.global_palette_.data(),
313                             sizeof(data.palette)));
314   }
315 }
316