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: 12 CFX_GifContextForTest(CCodec_GifModule* gif_module, 13 CCodec_GifModule::Delegate* delegate) 14 : CFX_GifContext(gif_module, delegate) {} 15 ~CFX_GifContextForTest() override {} 16 17 using CFX_GifContext::ReadData; 18 using CFX_GifContext::ReadGifSignature; 19 using CFX_GifContext::ReadLogicalScreenDescriptor; 20 }; 21 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 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 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 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 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