blob: cef4f9a9a5b5241aebf6f6823637b57400729924 [file] [log] [blame]
Lei Zhang94293682016-01-27 18:27:56 -08001// Copyright 2014 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// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
Dan Sinclair764ec512016-03-14 13:35:12 -04007#include "core/fxcodec/lgif/fx_gif.h"
Lei Zhang4467dea2016-02-25 12:39:15 -08008
Nicolas Pena2e2ee0e2017-05-10 14:42:26 -04009#include <algorithm>
Nicolas Pena1e5a98a2017-05-03 10:54:23 -040010#include <utility>
11
Dan Sinclair764ec512016-03-14 13:35:12 -040012#include "core/fxcodec/lbmp/fx_bmp.h"
Nicolas Pena2199ab82017-05-11 18:44:29 -040013#include "core/fxcodec/lgif/cgifcontext.h"
Nicolas Penaef73cf52017-05-12 14:36:06 -040014#include "third_party/base/logging.h"
Nicolas Pena808828c2017-05-09 12:35:19 -040015#include "third_party/base/ptr_util.h"
tsepez8aafdf92017-01-09 07:08:54 -080016#include "third_party/base/stl_util.h"
Lei Zhang4467dea2016-02-25 12:39:15 -080017
Nicolas Pena1e5a98a2017-05-03 10:54:23 -040018static_assert(sizeof(GifImageInfo) == 9,
19 "GifImageInfo should have a size of 9");
20static_assert(sizeof(GifPalette) == 3, "GifPalette should have a size of 3");
21static_assert(sizeof(GifPTE) == 13, "GifPTE should have a size of 13");
22static_assert(sizeof(GifGCE) == 5, "GifGCE should have a size of 5");
23static_assert(sizeof(GifHeader) == 6, "GifHeader should have a size of 6");
24static_assert(sizeof(GifLSD) == 7, "GifLSD should have a size of 7");
25
Nicolas Penaec3a9e22017-05-02 10:45:35 -040026namespace {
27
Nicolas Pena2199ab82017-05-11 18:44:29 -040028uint8_t* gif_read_data(CGifContext* context,
Nicolas Penaec3a9e22017-05-02 10:45:35 -040029 uint8_t** des_buf_pp,
30 uint32_t data_size) {
Nicolas Pena2199ab82017-05-11 18:44:29 -040031 if (!context || context->avail_in < context->skip_size + data_size)
Nicolas Penaec3a9e22017-05-02 10:45:35 -040032 return nullptr;
33
Nicolas Pena2199ab82017-05-11 18:44:29 -040034 *des_buf_pp = context->next_in + context->skip_size;
35 context->skip_size += data_size;
Nicolas Penaec3a9e22017-05-02 10:45:35 -040036 return *des_buf_pp;
37}
38
Nicolas Pena2199ab82017-05-11 18:44:29 -040039void gif_save_decoding_status(CGifContext* context, int32_t status) {
40 context->decode_status = status;
41 context->next_in += context->skip_size;
42 context->avail_in -= context->skip_size;
43 context->skip_size = 0;
Nicolas Penaec3a9e22017-05-02 10:45:35 -040044}
45
Nicolas Pena2199ab82017-05-11 18:44:29 -040046GifDecodeStatus gif_decode_extension(CGifContext* context) {
Nicolas Penaec3a9e22017-05-02 10:45:35 -040047 uint8_t* data_size_ptr = nullptr;
48 uint8_t* data_ptr = nullptr;
Nicolas Pena2199ab82017-05-11 18:44:29 -040049 uint32_t skip_size_org = context->skip_size;
50 switch (context->decode_status) {
Nicolas Penaec3a9e22017-05-02 10:45:35 -040051 case GIF_D_STATUS_EXT_CE: {
Nicolas Pena2199ab82017-05-11 18:44:29 -040052 if (!gif_read_data(context, &data_size_ptr, 1)) {
53 context->skip_size = skip_size_org;
Nicolas Pena1e5a98a2017-05-03 10:54:23 -040054 return GifDecodeStatus::Unfinished;
Nicolas Penaec3a9e22017-05-02 10:45:35 -040055 }
Nicolas Pena2199ab82017-05-11 18:44:29 -040056 context->cmt_data.clear();
Nicolas Penaec3a9e22017-05-02 10:45:35 -040057 while (*data_size_ptr != GIF_BLOCK_TERMINAL) {
58 uint8_t data_size = *data_size_ptr;
Nicolas Pena2199ab82017-05-11 18:44:29 -040059 if (!gif_read_data(context, &data_ptr, *data_size_ptr) ||
60 !gif_read_data(context, &data_size_ptr, 1)) {
61 context->skip_size = skip_size_org;
Nicolas Pena1e5a98a2017-05-03 10:54:23 -040062 return GifDecodeStatus::Unfinished;
Nicolas Penaec3a9e22017-05-02 10:45:35 -040063 }
Nicolas Pena2199ab82017-05-11 18:44:29 -040064 context->cmt_data += CFX_ByteString(data_ptr, data_size);
Nicolas Penaec3a9e22017-05-02 10:45:35 -040065 }
Nicolas Pena2e2ee0e2017-05-10 14:42:26 -040066 break;
67 }
Nicolas Penaec3a9e22017-05-02 10:45:35 -040068 case GIF_D_STATUS_EXT_PTE: {
Nicolas Pena2e2ee0e2017-05-10 14:42:26 -040069 GifPTE* gif_pte = nullptr;
Nicolas Pena2199ab82017-05-11 18:44:29 -040070 if (!gif_read_data(context, reinterpret_cast<uint8_t**>(&gif_pte), 13))
Nicolas Pena1e5a98a2017-05-03 10:54:23 -040071 return GifDecodeStatus::Unfinished;
Nicolas Penaec3a9e22017-05-02 10:45:35 -040072
Nicolas Pena2199ab82017-05-11 18:44:29 -040073 context->m_GifGCE = nullptr;
74 if (!gif_read_data(context, &data_size_ptr, 1)) {
75 context->skip_size = skip_size_org;
Nicolas Pena1e5a98a2017-05-03 10:54:23 -040076 return GifDecodeStatus::Unfinished;
Nicolas Penaec3a9e22017-05-02 10:45:35 -040077 }
78 while (*data_size_ptr != GIF_BLOCK_TERMINAL) {
Nicolas Pena2199ab82017-05-11 18:44:29 -040079 if (!gif_read_data(context, &data_ptr, *data_size_ptr) ||
80 !gif_read_data(context, &data_size_ptr, 1)) {
81 context->skip_size = skip_size_org;
Nicolas Pena1e5a98a2017-05-03 10:54:23 -040082 return GifDecodeStatus::Unfinished;
Nicolas Penaec3a9e22017-05-02 10:45:35 -040083 }
Nicolas Penaec3a9e22017-05-02 10:45:35 -040084 }
Nicolas Pena2e2ee0e2017-05-10 14:42:26 -040085 break;
86 }
Nicolas Penaec3a9e22017-05-02 10:45:35 -040087 case GIF_D_STATUS_EXT_GCE: {
Nicolas Penaec3a9e22017-05-02 10:45:35 -040088 GifGCE* gif_gce_ptr = nullptr;
Nicolas Pena2199ab82017-05-11 18:44:29 -040089 if (!gif_read_data(context, reinterpret_cast<uint8_t**>(&gif_gce_ptr), 6))
Nicolas Pena1e5a98a2017-05-03 10:54:23 -040090 return GifDecodeStatus::Unfinished;
Nicolas Penaec3a9e22017-05-02 10:45:35 -040091
Nicolas Pena2199ab82017-05-11 18:44:29 -040092 if (!context->m_GifGCE.get())
93 context->m_GifGCE = pdfium::MakeUnique<GifGCE>();
94 context->m_GifGCE->block_size = gif_gce_ptr->block_size;
95 context->m_GifGCE->gce_flag = gif_gce_ptr->gce_flag;
96 context->m_GifGCE->delay_time = GetWord_LSBFirst(
Nicolas Pena2e2ee0e2017-05-10 14:42:26 -040097 reinterpret_cast<uint8_t*>(&gif_gce_ptr->delay_time));
Nicolas Pena2199ab82017-05-11 18:44:29 -040098 context->m_GifGCE->trans_index = gif_gce_ptr->trans_index;
Nicolas Pena2e2ee0e2017-05-10 14:42:26 -040099 break;
100 }
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400101 default: {
Nicolas Pena2199ab82017-05-11 18:44:29 -0400102 if (context->decode_status == GIF_D_STATUS_EXT_PTE)
103 context->m_GifGCE = nullptr;
104 if (!gif_read_data(context, &data_size_ptr, 1))
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400105 return GifDecodeStatus::Unfinished;
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400106
107 while (*data_size_ptr != GIF_BLOCK_TERMINAL) {
Nicolas Pena2199ab82017-05-11 18:44:29 -0400108 if (!gif_read_data(context, &data_ptr, *data_size_ptr) ||
109 !gif_read_data(context, &data_size_ptr, 1)) {
110 context->skip_size = skip_size_org;
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400111 return GifDecodeStatus::Unfinished;
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400112 }
113 }
114 }
115 }
Nicolas Pena2199ab82017-05-11 18:44:29 -0400116 gif_save_decoding_status(context, GIF_D_STATUS_SIG);
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400117 return GifDecodeStatus::Success;
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400118}
119
Nicolas Pena2199ab82017-05-11 18:44:29 -0400120GifDecodeStatus gif_decode_image_info(CGifContext* context) {
121 if (context->width == 0 || context->height == 0) {
Nicolas Pena6f3593c2017-05-23 19:07:25 -0400122 context->AddError("No Image Header Info");
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400123 return GifDecodeStatus::Error;
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400124 }
Nicolas Pena2199ab82017-05-11 18:44:29 -0400125 uint32_t skip_size_org = context->skip_size;
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400126 GifImageInfo* gif_img_info_ptr = nullptr;
Nicolas Pena2199ab82017-05-11 18:44:29 -0400127 if (!gif_read_data(context, reinterpret_cast<uint8_t**>(&gif_img_info_ptr),
Nicolas Pena2e2ee0e2017-05-10 14:42:26 -0400128 9))
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400129 return GifDecodeStatus::Unfinished;
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400130
Nicolas Pena2e2ee0e2017-05-10 14:42:26 -0400131 auto gif_image = pdfium::MakeUnique<GifImage>();
132 gif_image->m_ImageInfo.left =
133 GetWord_LSBFirst(reinterpret_cast<uint8_t*>(&gif_img_info_ptr->left));
134 gif_image->m_ImageInfo.top =
135 GetWord_LSBFirst(reinterpret_cast<uint8_t*>(&gif_img_info_ptr->top));
136 gif_image->m_ImageInfo.width =
137 GetWord_LSBFirst(reinterpret_cast<uint8_t*>(&gif_img_info_ptr->width));
138 gif_image->m_ImageInfo.height =
139 GetWord_LSBFirst(reinterpret_cast<uint8_t*>(&gif_img_info_ptr->height));
140 gif_image->m_ImageInfo.local_flag = gif_img_info_ptr->local_flag;
141 if (gif_image->m_ImageInfo.left + gif_image->m_ImageInfo.width >
Nicolas Pena2199ab82017-05-11 18:44:29 -0400142 context->width ||
Nicolas Pena2e2ee0e2017-05-10 14:42:26 -0400143 gif_image->m_ImageInfo.top + gif_image->m_ImageInfo.height >
Nicolas Pena2199ab82017-05-11 18:44:29 -0400144 context->height) {
Nicolas Pena6f3593c2017-05-23 19:07:25 -0400145 context->AddError("Image Data Out Of LSD, The File May Be Corrupt");
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400146 return GifDecodeStatus::Error;
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400147 }
148 GifLF* gif_img_info_lf_ptr = (GifLF*)&gif_img_info_ptr->local_flag;
149 if (gif_img_info_lf_ptr->local_pal) {
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400150 int32_t loc_pal_size = (2 << gif_img_info_lf_ptr->pal_bits) * 3;
151 uint8_t* loc_pal_ptr = nullptr;
Nicolas Pena2199ab82017-05-11 18:44:29 -0400152 if (!gif_read_data(context, &loc_pal_ptr, loc_pal_size)) {
153 context->skip_size = skip_size_org;
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400154 return GifDecodeStatus::Unfinished;
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400155 }
Nicolas Pena2e2ee0e2017-05-10 14:42:26 -0400156 gif_image->m_LocalPalettes = std::vector<GifPalette>(loc_pal_size / 3);
157 std::copy(loc_pal_ptr, loc_pal_ptr + loc_pal_size,
158 reinterpret_cast<uint8_t*>(gif_image->m_LocalPalettes.data()));
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400159 }
160 uint8_t* code_size_ptr = nullptr;
Nicolas Pena2199ab82017-05-11 18:44:29 -0400161 if (!gif_read_data(context, &code_size_ptr, 1)) {
162 context->skip_size = skip_size_org;
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400163 return GifDecodeStatus::Unfinished;
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400164 }
Nicolas Pena2e2ee0e2017-05-10 14:42:26 -0400165 gif_image->image_code_size = *code_size_ptr;
Nicolas Pena2199ab82017-05-11 18:44:29 -0400166 context->RecordCurrentPosition(&gif_image->image_data_pos);
167 gif_image->image_data_pos += context->skip_size;
Nicolas Pena2e2ee0e2017-05-10 14:42:26 -0400168 gif_image->m_ImageGCE = nullptr;
Nicolas Pena2199ab82017-05-11 18:44:29 -0400169 if (context->m_GifGCE.get()) {
170 gif_image->m_ImageGCE = std::move(context->m_GifGCE);
171 context->m_GifGCE = nullptr;
Nicolas Pena2e2ee0e2017-05-10 14:42:26 -0400172 }
Nicolas Pena2199ab82017-05-11 18:44:29 -0400173 context->m_Images.push_back(std::move(gif_image));
174 gif_save_decoding_status(context, GIF_D_STATUS_IMG_DATA);
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400175 return GifDecodeStatus::Success;
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400176}
177
Nicolas Pena2199ab82017-05-11 18:44:29 -0400178void gif_decoding_failure_at_tail_cleanup(CGifContext* context,
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400179 GifImage* gif_image_ptr) {
Nicolas Pena2e2ee0e2017-05-10 14:42:26 -0400180 gif_image_ptr->m_ImageRowBuf.clear();
Nicolas Pena2199ab82017-05-11 18:44:29 -0400181 gif_save_decoding_status(context, GIF_D_STATUS_TAIL);
Nicolas Pena6f3593c2017-05-23 19:07:25 -0400182 context->AddError("Decode Image Data Error");
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400183}
184
185} // namespace
186
Nicolas Pena2e2ee0e2017-05-10 14:42:26 -0400187GifImage::GifImage() {}
188
189GifImage::~GifImage() {}
190
tsepezb5e8f142016-03-25 15:18:35 -0700191void CGifLZWDecoder::Input(uint8_t* src_buf, uint32_t src_size) {
Lei Zhang94293682016-01-27 18:27:56 -0800192 next_in = src_buf;
193 avail_in = src_size;
194}
weilif4bb5802016-06-14 17:21:14 -0700195
tsepezb5e8f142016-03-25 15:18:35 -0700196uint32_t CGifLZWDecoder::GetAvailInput() {
Lei Zhang94293682016-01-27 18:27:56 -0800197 return avail_in;
198}
weilif4bb5802016-06-14 17:21:14 -0700199
Dan Sinclair812e96c2017-03-13 16:43:37 -0400200CGifLZWDecoder::CGifLZWDecoder(char* error_ptr)
weilif4bb5802016-06-14 17:21:14 -0700201 : code_size(0),
202 code_size_cur(0),
203 code_clear(0),
204 code_end(0),
205 code_next(0),
206 code_first(0),
207 stack_size(0),
208 code_old(0),
209 next_in(nullptr),
210 avail_in(0),
211 bits_left(0),
212 code_store(0),
213 err_msg_ptr(error_ptr) {}
214
215CGifLZWDecoder::~CGifLZWDecoder() {}
216
Lei Zhang94293682016-01-27 18:27:56 -0800217void CGifLZWDecoder::InitTable(uint8_t code_len) {
218 code_size = code_len;
Nicolas Pena34f8e1f2017-05-15 10:59:07 -0400219 ASSERT(code_size < 13);
Lei Zhang94293682016-01-27 18:27:56 -0800220 code_clear = 1 << code_size;
221 code_end = code_clear + 1;
222 bits_left = 0;
223 code_store = 0;
thestig4997b222016-06-07 10:46:22 -0700224 next_in = nullptr;
Lei Zhang94293682016-01-27 18:27:56 -0800225 avail_in = 0;
226 stack_size = 0;
227 code_first = 0;
228 ClearTable();
229}
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400230
Lei Zhang94293682016-01-27 18:27:56 -0800231void CGifLZWDecoder::ClearTable() {
232 code_size_cur = code_size + 1;
233 code_next = code_end + 1;
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400234 code_old = static_cast<uint16_t>(-1);
Dan Sinclair1c5d0b42017-04-03 15:05:11 -0400235 memset(code_table, 0, sizeof(tag_Table) * GIF_MAX_LZW_CODE);
236 memset(stack, 0, GIF_MAX_LZW_CODE);
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400237 for (uint16_t i = 0; i < code_clear; i++)
238 code_table[i].suffix = static_cast<uint8_t>(i);
Lei Zhang94293682016-01-27 18:27:56 -0800239}
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400240
Nicolas Pena78766092017-05-16 18:30:24 -0400241bool CGifLZWDecoder::DecodeString(uint16_t code) {
Lei Zhang94293682016-01-27 18:27:56 -0800242 stack_size = 0;
Nicolas Pena34f8e1f2017-05-15 10:59:07 -0400243 while (code >= code_clear && code <= code_next) {
Nicolas Pena78766092017-05-16 18:30:24 -0400244 if (code == code_table[code].prefix || stack_size == GIF_MAX_LZW_CODE - 1)
245 return false;
246
Lei Zhang94293682016-01-27 18:27:56 -0800247 stack[GIF_MAX_LZW_CODE - 1 - stack_size++] = code_table[code].suffix;
248 code = code_table[code].prefix;
249 }
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400250 stack[GIF_MAX_LZW_CODE - 1 - stack_size++] = static_cast<uint8_t>(code);
251 code_first = static_cast<uint8_t>(code);
Nicolas Pena78766092017-05-16 18:30:24 -0400252 return true;
Lei Zhang94293682016-01-27 18:27:56 -0800253}
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400254
Tom Sepez62a70f92016-03-21 15:00:20 -0700255void CGifLZWDecoder::AddCode(uint16_t prefix_code, uint8_t append_char) {
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400256 if (code_next == GIF_MAX_LZW_CODE)
Lei Zhang94293682016-01-27 18:27:56 -0800257 return;
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400258
Lei Zhang94293682016-01-27 18:27:56 -0800259 code_table[code_next].prefix = prefix_code;
260 code_table[code_next].suffix = append_char;
261 if (++code_next < GIF_MAX_LZW_CODE) {
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400262 if (code_next >> code_size_cur)
Lei Zhang94293682016-01-27 18:27:56 -0800263 code_size_cur++;
Lei Zhang94293682016-01-27 18:27:56 -0800264 }
265}
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400266
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400267GifDecodeStatus CGifLZWDecoder::Decode(uint8_t* des_buf, uint32_t* des_size) {
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400268 if (*des_size == 0)
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400269 return GifDecodeStatus::InsufficientDestSize;
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400270
tsepezb5e8f142016-03-25 15:18:35 -0700271 uint32_t i = 0;
Lei Zhang94293682016-01-27 18:27:56 -0800272 if (stack_size != 0) {
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400273 if (*des_size < stack_size) {
274 memcpy(des_buf, &stack[GIF_MAX_LZW_CODE - stack_size], *des_size);
275 stack_size -= static_cast<uint16_t>(*des_size);
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400276 return GifDecodeStatus::InsufficientDestSize;
Lei Zhang94293682016-01-27 18:27:56 -0800277 }
Dan Sinclair1c5d0b42017-04-03 15:05:11 -0400278 memcpy(des_buf, &stack[GIF_MAX_LZW_CODE - stack_size], stack_size);
Lei Zhang94293682016-01-27 18:27:56 -0800279 des_buf += stack_size;
280 i += stack_size;
281 stack_size = 0;
282 }
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400283 ASSERT(err_msg_ptr);
284 while (i <= *des_size && (avail_in > 0 || bits_left >= code_size_cur)) {
Lei Zhang94293682016-01-27 18:27:56 -0800285 if (code_size_cur > 12) {
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400286 strncpy(err_msg_ptr, "Code Length Out Of Range", GIF_MAX_ERROR_SIZE - 1);
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400287 return GifDecodeStatus::Error;
Lei Zhang94293682016-01-27 18:27:56 -0800288 }
289 if (avail_in > 0) {
Nicolas Pena13560982017-01-16 13:12:15 -0500290 if (bits_left > 31) {
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400291 strncpy(err_msg_ptr, "Decode Error", GIF_MAX_ERROR_SIZE - 1);
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400292 return GifDecodeStatus::Error;
Nicolas Pena13560982017-01-16 13:12:15 -0500293 }
Nicolas Pena5c1673d2017-01-25 11:09:09 -0500294 pdfium::base::CheckedNumeric<uint32_t> safe_code = *next_in++;
295 safe_code <<= bits_left;
296 safe_code |= code_store;
297 if (!safe_code.IsValid()) {
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400298 strncpy(err_msg_ptr, "Code Store Out Of Range", GIF_MAX_ERROR_SIZE - 1);
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400299 return GifDecodeStatus::Error;
Nicolas Pena5c1673d2017-01-25 11:09:09 -0500300 }
301 code_store = safe_code.ValueOrDie();
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400302 --avail_in;
Lei Zhang94293682016-01-27 18:27:56 -0800303 bits_left += 8;
304 }
305 while (bits_left >= code_size_cur) {
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400306 uint16_t code =
307 static_cast<uint16_t>(code_store) & ((1 << code_size_cur) - 1);
Lei Zhang94293682016-01-27 18:27:56 -0800308 code_store >>= code_size_cur;
309 bits_left -= code_size_cur;
310 if (code == code_clear) {
311 ClearTable();
312 continue;
Lei Zhang94293682016-01-27 18:27:56 -0800313 }
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400314 if (code == code_end) {
315 *des_size = i;
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400316 return GifDecodeStatus::Success;
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400317 }
318 if (code_old != static_cast<uint16_t>(-1)) {
319 if (code_next < GIF_MAX_LZW_CODE) {
320 if (code == code_next) {
321 AddCode(code_old, code_first);
Nicolas Pena78766092017-05-16 18:30:24 -0400322 if (!DecodeString(code)) {
323 strncpy(err_msg_ptr, "String Decoding Error",
324 GIF_MAX_ERROR_SIZE - 1);
325 return GifDecodeStatus::Error;
326 }
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400327 } else if (code > code_next) {
328 strncpy(err_msg_ptr, "Decode Error, Out Of Range",
329 GIF_MAX_ERROR_SIZE - 1);
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400330 return GifDecodeStatus::Error;
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400331 } else {
Nicolas Pena78766092017-05-16 18:30:24 -0400332 if (!DecodeString(code)) {
333 strncpy(err_msg_ptr, "String Decoding Error",
334 GIF_MAX_ERROR_SIZE - 1);
335 return GifDecodeStatus::Error;
336 }
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400337 uint8_t append_char = stack[GIF_MAX_LZW_CODE - stack_size];
338 AddCode(code_old, append_char);
339 }
340 }
341 } else {
Nicolas Pena78766092017-05-16 18:30:24 -0400342 if (!DecodeString(code)) {
343 strncpy(err_msg_ptr, "String Decoding Error", GIF_MAX_ERROR_SIZE - 1);
344 return GifDecodeStatus::Error;
345 }
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400346 }
347 code_old = code;
348 if (i + stack_size > *des_size) {
349 memcpy(des_buf, &stack[GIF_MAX_LZW_CODE - stack_size], *des_size - i);
350 stack_size -= static_cast<uint16_t>(*des_size - i);
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400351 return GifDecodeStatus::InsufficientDestSize;
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400352 }
353 memcpy(des_buf, &stack[GIF_MAX_LZW_CODE - stack_size], stack_size);
354 des_buf += stack_size;
355 i += stack_size;
356 stack_size = 0;
Lei Zhang94293682016-01-27 18:27:56 -0800357 }
358 }
359 if (avail_in == 0) {
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400360 *des_size = i;
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400361 return GifDecodeStatus::Unfinished;
Lei Zhang94293682016-01-27 18:27:56 -0800362 }
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400363 return GifDecodeStatus::Error;
Lei Zhang94293682016-01-27 18:27:56 -0800364}
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400365
Nicolas Pena2199ab82017-05-11 18:44:29 -0400366GifDecodeStatus gif_read_header(CGifContext* context) {
367 if (!context)
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400368 return GifDecodeStatus::Error;
thestig4997b222016-06-07 10:46:22 -0700369
Nicolas Pena2199ab82017-05-11 18:44:29 -0400370 uint32_t skip_size_org = context->skip_size;
thestig4997b222016-06-07 10:46:22 -0700371 GifHeader* gif_header_ptr = nullptr;
Nicolas Pena2199ab82017-05-11 18:44:29 -0400372 if (!gif_read_data(context, reinterpret_cast<uint8_t**>(&gif_header_ptr), 6))
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400373 return GifDecodeStatus::Unfinished;
thestig4997b222016-06-07 10:46:22 -0700374
Dan Sinclair7e7c6492017-04-03 14:50:05 -0400375 if (strncmp(gif_header_ptr->signature, GIF_SIGNATURE, 3) != 0 ||
Lei Zhang94293682016-01-27 18:27:56 -0800376 gif_header_ptr->version[0] != '8' || gif_header_ptr->version[2] != 'a') {
Nicolas Pena6f3593c2017-05-23 19:07:25 -0400377 context->AddError("Not A Gif Image");
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400378 return GifDecodeStatus::Error;
Lei Zhang94293682016-01-27 18:27:56 -0800379 }
thestig4997b222016-06-07 10:46:22 -0700380 GifLSD* gif_lsd_ptr = nullptr;
Nicolas Pena2199ab82017-05-11 18:44:29 -0400381 if (!gif_read_data(context, reinterpret_cast<uint8_t**>(&gif_lsd_ptr), 7)) {
382 context->skip_size = skip_size_org;
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400383 return GifDecodeStatus::Unfinished;
Lei Zhang94293682016-01-27 18:27:56 -0800384 }
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400385 if (reinterpret_cast<GifGF*>(&gif_lsd_ptr->global_flag)->global_pal) {
Nicolas Pena2199ab82017-05-11 18:44:29 -0400386 context->global_pal_num =
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400387 2 << reinterpret_cast<GifGF*>(&gif_lsd_ptr->global_flag)->pal_bits;
Nicolas Pena2199ab82017-05-11 18:44:29 -0400388 int32_t global_pal_size = context->global_pal_num * 3;
thestig4997b222016-06-07 10:46:22 -0700389 uint8_t* global_pal_ptr = nullptr;
Nicolas Pena2199ab82017-05-11 18:44:29 -0400390 if (!gif_read_data(context, &global_pal_ptr, global_pal_size)) {
391 context->skip_size = skip_size_org;
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400392 return GifDecodeStatus::Unfinished;
Lei Zhang94293682016-01-27 18:27:56 -0800393 }
Nicolas Pena2199ab82017-05-11 18:44:29 -0400394 context->global_sort_flag = ((GifGF*)&gif_lsd_ptr->global_flag)->sort_flag;
395 context->global_color_resolution =
Lei Zhang94293682016-01-27 18:27:56 -0800396 ((GifGF*)&gif_lsd_ptr->global_flag)->color_resolution;
Nicolas Pena2199ab82017-05-11 18:44:29 -0400397 context->m_GlobalPalette.resize(global_pal_size / 3);
398 memcpy(context->m_GlobalPalette.data(), global_pal_ptr, global_pal_size);
Lei Zhang94293682016-01-27 18:27:56 -0800399 }
Nicolas Pena2199ab82017-05-11 18:44:29 -0400400 context->width =
Nicolas Pena2e2ee0e2017-05-10 14:42:26 -0400401 (int)GetWord_LSBFirst(reinterpret_cast<uint8_t*>(&gif_lsd_ptr->width));
Nicolas Pena2199ab82017-05-11 18:44:29 -0400402 context->height =
Nicolas Pena2e2ee0e2017-05-10 14:42:26 -0400403 (int)GetWord_LSBFirst(reinterpret_cast<uint8_t*>(&gif_lsd_ptr->height));
Nicolas Pena2199ab82017-05-11 18:44:29 -0400404 context->bc_index = gif_lsd_ptr->bc_index;
405 context->pixel_aspect = gif_lsd_ptr->pixel_aspect;
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400406 return GifDecodeStatus::Success;
Lei Zhang94293682016-01-27 18:27:56 -0800407}
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400408
Nicolas Pena2199ab82017-05-11 18:44:29 -0400409GifDecodeStatus gif_get_frame(CGifContext* context) {
410 if (!context)
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400411 return GifDecodeStatus::Error;
thestig4997b222016-06-07 10:46:22 -0700412
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400413 GifDecodeStatus ret = GifDecodeStatus::Success;
tsepez12f3e4a2016-11-02 15:17:29 -0700414 while (true) {
Nicolas Pena2199ab82017-05-11 18:44:29 -0400415 switch (context->decode_status) {
Lei Zhang94293682016-01-27 18:27:56 -0800416 case GIF_D_STATUS_TAIL:
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400417 return GifDecodeStatus::Success;
Lei Zhang94293682016-01-27 18:27:56 -0800418 case GIF_D_STATUS_SIG: {
thestig4997b222016-06-07 10:46:22 -0700419 uint8_t* sig_ptr = nullptr;
Nicolas Pena2199ab82017-05-11 18:44:29 -0400420 if (!gif_read_data(context, &sig_ptr, 1))
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400421 return GifDecodeStatus::Unfinished;
thestig4997b222016-06-07 10:46:22 -0700422
Lei Zhang94293682016-01-27 18:27:56 -0800423 switch (*sig_ptr) {
424 case GIF_SIG_EXTENSION:
Nicolas Pena2199ab82017-05-11 18:44:29 -0400425 gif_save_decoding_status(context, GIF_D_STATUS_EXT);
Lei Zhang94293682016-01-27 18:27:56 -0800426 continue;
427 case GIF_SIG_IMAGE:
Nicolas Pena2199ab82017-05-11 18:44:29 -0400428 gif_save_decoding_status(context, GIF_D_STATUS_IMG_INFO);
Lei Zhang94293682016-01-27 18:27:56 -0800429 continue;
430 case GIF_SIG_TRAILER:
Nicolas Pena2199ab82017-05-11 18:44:29 -0400431 gif_save_decoding_status(context, GIF_D_STATUS_TAIL);
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400432 return GifDecodeStatus::Success;
Lei Zhang94293682016-01-27 18:27:56 -0800433 default:
Nicolas Pena2199ab82017-05-11 18:44:29 -0400434 if (context->avail_in) {
Nicolas Pena808828c2017-05-09 12:35:19 -0400435 // The Gif File has non_standard Tag!
Nicolas Pena2199ab82017-05-11 18:44:29 -0400436 gif_save_decoding_status(context, GIF_D_STATUS_SIG);
Lei Zhang94293682016-01-27 18:27:56 -0800437 continue;
438 }
Nicolas Pena808828c2017-05-09 12:35:19 -0400439 // The Gif File Doesn't have Trailer Tag!
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400440 return GifDecodeStatus::Success;
Lei Zhang94293682016-01-27 18:27:56 -0800441 }
442 }
443 case GIF_D_STATUS_EXT: {
thestig4997b222016-06-07 10:46:22 -0700444 uint8_t* ext_ptr = nullptr;
Nicolas Pena2199ab82017-05-11 18:44:29 -0400445 if (!gif_read_data(context, &ext_ptr, 1))
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400446 return GifDecodeStatus::Unfinished;
thestig4997b222016-06-07 10:46:22 -0700447
Lei Zhang94293682016-01-27 18:27:56 -0800448 switch (*ext_ptr) {
Lei Zhang94293682016-01-27 18:27:56 -0800449 case GIF_BLOCK_CE:
Nicolas Pena2199ab82017-05-11 18:44:29 -0400450 gif_save_decoding_status(context, GIF_D_STATUS_EXT_CE);
Lei Zhang94293682016-01-27 18:27:56 -0800451 continue;
Lei Zhang94293682016-01-27 18:27:56 -0800452 case GIF_BLOCK_GCE:
Nicolas Pena2199ab82017-05-11 18:44:29 -0400453 gif_save_decoding_status(context, GIF_D_STATUS_EXT_GCE);
Lei Zhang94293682016-01-27 18:27:56 -0800454 continue;
Lei Zhang94293682016-01-27 18:27:56 -0800455 case GIF_BLOCK_PTE:
Nicolas Pena2199ab82017-05-11 18:44:29 -0400456 gif_save_decoding_status(context, GIF_D_STATUS_EXT_PTE);
Lei Zhang94293682016-01-27 18:27:56 -0800457 continue;
Lei Zhang94293682016-01-27 18:27:56 -0800458 default: {
459 int32_t status = GIF_D_STATUS_EXT_UNE;
Lei Zhang94293682016-01-27 18:27:56 -0800460 if (*ext_ptr == GIF_BLOCK_PTE) {
461 status = GIF_D_STATUS_EXT_PTE;
462 }
Nicolas Pena2199ab82017-05-11 18:44:29 -0400463 gif_save_decoding_status(context, status);
Lei Zhang94293682016-01-27 18:27:56 -0800464 continue;
465 }
466 }
467 }
468 case GIF_D_STATUS_IMG_INFO: {
Nicolas Pena2199ab82017-05-11 18:44:29 -0400469 ret = gif_decode_image_info(context);
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400470 if (ret != GifDecodeStatus::Success)
Lei Zhang94293682016-01-27 18:27:56 -0800471 return ret;
Nicolas Pena6f3593c2017-05-23 19:07:25 -0400472
Lei Zhang94293682016-01-27 18:27:56 -0800473 continue;
474 }
475 case GIF_D_STATUS_IMG_DATA: {
thestig4997b222016-06-07 10:46:22 -0700476 uint8_t* data_size_ptr = nullptr;
477 uint8_t* data_ptr = nullptr;
Nicolas Pena2199ab82017-05-11 18:44:29 -0400478 uint32_t skip_size_org = context->skip_size;
479 if (!gif_read_data(context, &data_size_ptr, 1))
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400480 return GifDecodeStatus::Unfinished;
thestig4997b222016-06-07 10:46:22 -0700481
Lei Zhang94293682016-01-27 18:27:56 -0800482 while (*data_size_ptr != GIF_BLOCK_TERMINAL) {
Nicolas Pena2199ab82017-05-11 18:44:29 -0400483 if (!gif_read_data(context, &data_ptr, *data_size_ptr)) {
484 context->skip_size = skip_size_org;
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400485 return GifDecodeStatus::Unfinished;
Lei Zhang94293682016-01-27 18:27:56 -0800486 }
Nicolas Pena2199ab82017-05-11 18:44:29 -0400487 gif_save_decoding_status(context, GIF_D_STATUS_IMG_DATA);
488 skip_size_org = context->skip_size;
489 if (!gif_read_data(context, &data_size_ptr, 1))
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400490 return GifDecodeStatus::Unfinished;
Lei Zhang94293682016-01-27 18:27:56 -0800491 }
Nicolas Pena2199ab82017-05-11 18:44:29 -0400492 gif_save_decoding_status(context, GIF_D_STATUS_SIG);
Lei Zhang94293682016-01-27 18:27:56 -0800493 continue;
494 }
495 default: {
Nicolas Pena2199ab82017-05-11 18:44:29 -0400496 ret = gif_decode_extension(context);
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400497 if (ret != GifDecodeStatus::Success)
Lei Zhang94293682016-01-27 18:27:56 -0800498 return ret;
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400499 break;
Lei Zhang94293682016-01-27 18:27:56 -0800500 }
501 }
502 }
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400503 return GifDecodeStatus::Success;
Lei Zhang94293682016-01-27 18:27:56 -0800504}
Tom Sepez193e6ca2017-03-14 15:53:36 -0700505
Nicolas Pena2199ab82017-05-11 18:44:29 -0400506GifDecodeStatus gif_load_frame(CGifContext* context, int32_t frame_num) {
507 if (!context || !pdfium::IndexInBounds(context->m_Images, frame_num))
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400508 return GifDecodeStatus::Error;
Tom Sepez193e6ca2017-03-14 15:53:36 -0700509
thestig4997b222016-06-07 10:46:22 -0700510 uint8_t* data_size_ptr = nullptr;
511 uint8_t* data_ptr = nullptr;
Nicolas Pena2199ab82017-05-11 18:44:29 -0400512 uint32_t skip_size_org = context->skip_size;
513 GifImage* gif_image_ptr = context->m_Images[frame_num].get();
Nicolas Pena2e2ee0e2017-05-10 14:42:26 -0400514 uint32_t gif_img_row_bytes = gif_image_ptr->m_ImageInfo.width;
Nicolas Pena6b71f222017-01-16 13:27:06 -0500515 if (gif_img_row_bytes == 0) {
Nicolas Pena6f3593c2017-05-23 19:07:25 -0400516 context->AddError("Error Invalid Number of Row Bytes");
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400517 return GifDecodeStatus::Error;
Nicolas Pena6b71f222017-01-16 13:27:06 -0500518 }
Nicolas Pena2199ab82017-05-11 18:44:29 -0400519 if (context->decode_status == GIF_D_STATUS_TAIL) {
Nicolas Pena2e2ee0e2017-05-10 14:42:26 -0400520 gif_image_ptr->m_ImageRowBuf.resize(gif_img_row_bytes);
521 GifGCE* gif_img_gce_ptr = gif_image_ptr->m_ImageGCE.get();
Lei Zhang94293682016-01-27 18:27:56 -0800522 int32_t loc_pal_num =
Nicolas Pena2e2ee0e2017-05-10 14:42:26 -0400523 ((GifLF*)&gif_image_ptr->m_ImageInfo.local_flag)->local_pal
524 ? (2 << ((GifLF*)&gif_image_ptr->m_ImageInfo.local_flag)->pal_bits)
Lei Zhang94293682016-01-27 18:27:56 -0800525 : 0;
Nicolas Pena2199ab82017-05-11 18:44:29 -0400526 context->avail_in = 0;
Nicolas Pena0dc85712017-05-11 15:43:47 -0400527 GifPalette* pLocalPalette = gif_image_ptr->m_LocalPalettes.empty()
528 ? nullptr
529 : gif_image_ptr->m_LocalPalettes.data();
thestig4997b222016-06-07 10:46:22 -0700530 if (!gif_img_gce_ptr) {
Nicolas Pena2199ab82017-05-11 18:44:29 -0400531 bool bRes = context->GetRecordPosition(
Nicolas Pena2e2ee0e2017-05-10 14:42:26 -0400532 gif_image_ptr->image_data_pos, gif_image_ptr->m_ImageInfo.left,
533 gif_image_ptr->m_ImageInfo.top, gif_image_ptr->m_ImageInfo.width,
Nicolas Pena0dc85712017-05-11 15:43:47 -0400534 gif_image_ptr->m_ImageInfo.height, loc_pal_num, pLocalPalette, 0, 0,
535 -1, 0,
Nicolas Pena2e2ee0e2017-05-10 14:42:26 -0400536 (bool)((GifLF*)&gif_image_ptr->m_ImageInfo.local_flag)->interlace);
Lei Zhang94293682016-01-27 18:27:56 -0800537 if (!bRes) {
Nicolas Pena2e2ee0e2017-05-10 14:42:26 -0400538 gif_image_ptr->m_ImageRowBuf.clear();
Nicolas Pena6f3593c2017-05-23 19:07:25 -0400539 context->AddError("Error Read Record Position Data");
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400540 return GifDecodeStatus::Error;
Lei Zhang94293682016-01-27 18:27:56 -0800541 }
542 } else {
Nicolas Pena2199ab82017-05-11 18:44:29 -0400543 bool bRes = context->GetRecordPosition(
Nicolas Pena2e2ee0e2017-05-10 14:42:26 -0400544 gif_image_ptr->image_data_pos, gif_image_ptr->m_ImageInfo.left,
545 gif_image_ptr->m_ImageInfo.top, gif_image_ptr->m_ImageInfo.width,
Nicolas Pena0dc85712017-05-11 15:43:47 -0400546 gif_image_ptr->m_ImageInfo.height, loc_pal_num, pLocalPalette,
Nicolas Pena2e2ee0e2017-05-10 14:42:26 -0400547 (int32_t)gif_image_ptr->m_ImageGCE->delay_time,
548 (bool)((GifCEF*)&gif_image_ptr->m_ImageGCE->gce_flag)->user_input,
549 ((GifCEF*)&gif_image_ptr->m_ImageGCE->gce_flag)->transparency
550 ? (int32_t)gif_image_ptr->m_ImageGCE->trans_index
Lei Zhang94293682016-01-27 18:27:56 -0800551 : -1,
Nicolas Pena2e2ee0e2017-05-10 14:42:26 -0400552 (int32_t)((GifCEF*)&gif_image_ptr->m_ImageGCE->gce_flag)
Lei Zhang94293682016-01-27 18:27:56 -0800553 ->disposal_method,
Nicolas Pena2e2ee0e2017-05-10 14:42:26 -0400554 (bool)((GifLF*)&gif_image_ptr->m_ImageInfo.local_flag)->interlace);
Lei Zhang94293682016-01-27 18:27:56 -0800555 if (!bRes) {
Nicolas Pena2e2ee0e2017-05-10 14:42:26 -0400556 gif_image_ptr->m_ImageRowBuf.clear();
Nicolas Pena6f3593c2017-05-23 19:07:25 -0400557 context->AddError("Error Read Record Position Data");
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400558 return GifDecodeStatus::Error;
Lei Zhang94293682016-01-27 18:27:56 -0800559 }
560 }
Nicolas Pena34f8e1f2017-05-15 10:59:07 -0400561 if (gif_image_ptr->image_code_size >= 13) {
Nicolas Pena2e2ee0e2017-05-10 14:42:26 -0400562 gif_image_ptr->m_ImageRowBuf.clear();
Nicolas Pena6f3593c2017-05-23 19:07:25 -0400563 context->AddError("Error Invalid Code Size");
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400564 return GifDecodeStatus::Error;
Nicolas Pena29a9f872017-01-10 14:00:16 -0500565 }
Nicolas Pena2199ab82017-05-11 18:44:29 -0400566 if (!context->m_ImgDecoder.get())
567 context->m_ImgDecoder =
Tom Sepez5f34d472017-06-01 10:18:53 -0700568 pdfium::MakeUnique<CGifLZWDecoder>(context->m_szLastError);
Nicolas Pena2199ab82017-05-11 18:44:29 -0400569 context->m_ImgDecoder->InitTable(gif_image_ptr->image_code_size);
570 context->img_row_offset = 0;
571 context->img_row_avail_size = 0;
572 context->img_pass_num = 0;
Lei Zhang94293682016-01-27 18:27:56 -0800573 gif_image_ptr->image_row_num = 0;
Nicolas Pena2199ab82017-05-11 18:44:29 -0400574 gif_save_decoding_status(context, GIF_D_STATUS_IMG_DATA);
Lei Zhang94293682016-01-27 18:27:56 -0800575 }
Nicolas Pena2199ab82017-05-11 18:44:29 -0400576 CGifLZWDecoder* img_decoder_ptr = context->m_ImgDecoder.get();
577 if (context->decode_status == GIF_D_STATUS_IMG_DATA) {
578 if (!gif_read_data(context, &data_size_ptr, 1))
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400579 return GifDecodeStatus::Unfinished;
thestig4997b222016-06-07 10:46:22 -0700580
Lei Zhang94293682016-01-27 18:27:56 -0800581 if (*data_size_ptr != GIF_BLOCK_TERMINAL) {
Nicolas Pena2199ab82017-05-11 18:44:29 -0400582 if (!gif_read_data(context, &data_ptr, *data_size_ptr)) {
583 context->skip_size = skip_size_org;
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400584 return GifDecodeStatus::Unfinished;
Lei Zhang94293682016-01-27 18:27:56 -0800585 }
586 img_decoder_ptr->Input(data_ptr, *data_size_ptr);
Nicolas Pena2199ab82017-05-11 18:44:29 -0400587 gif_save_decoding_status(context, GIF_D_STATUS_IMG_DATA);
588 context->img_row_offset += context->img_row_avail_size;
589 context->img_row_avail_size = gif_img_row_bytes - context->img_row_offset;
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400590 GifDecodeStatus ret = img_decoder_ptr->Decode(
Nicolas Pena2199ab82017-05-11 18:44:29 -0400591 gif_image_ptr->m_ImageRowBuf.data() + context->img_row_offset,
592 &context->img_row_avail_size);
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400593 if (ret == GifDecodeStatus::Error) {
Nicolas Pena2199ab82017-05-11 18:44:29 -0400594 gif_decoding_failure_at_tail_cleanup(context, gif_image_ptr);
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400595 return GifDecodeStatus::Error;
Lei Zhang94293682016-01-27 18:27:56 -0800596 }
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400597 while (ret != GifDecodeStatus::Error) {
598 if (ret == GifDecodeStatus::Success) {
Nicolas Pena2199ab82017-05-11 18:44:29 -0400599 context->ReadScanline(gif_image_ptr->image_row_num,
Nicolas Pena2e2ee0e2017-05-10 14:42:26 -0400600 gif_image_ptr->m_ImageRowBuf.data());
601 gif_image_ptr->m_ImageRowBuf.clear();
Nicolas Pena2199ab82017-05-11 18:44:29 -0400602 gif_save_decoding_status(context, GIF_D_STATUS_TAIL);
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400603 return GifDecodeStatus::Success;
Lei Zhang94293682016-01-27 18:27:56 -0800604 }
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400605 if (ret == GifDecodeStatus::Unfinished) {
Lei Zhang94293682016-01-27 18:27:56 -0800606 ASSERT(img_decoder_ptr->GetAvailInput() == 0);
Nicolas Pena2199ab82017-05-11 18:44:29 -0400607 skip_size_org = context->skip_size;
608 if (!gif_read_data(context, &data_size_ptr, 1))
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400609 return GifDecodeStatus::Unfinished;
thestig4997b222016-06-07 10:46:22 -0700610
Lei Zhang94293682016-01-27 18:27:56 -0800611 if (*data_size_ptr != GIF_BLOCK_TERMINAL) {
Nicolas Pena2199ab82017-05-11 18:44:29 -0400612 if (!gif_read_data(context, &data_ptr, *data_size_ptr)) {
613 context->skip_size = skip_size_org;
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400614 return GifDecodeStatus::Unfinished;
Lei Zhang94293682016-01-27 18:27:56 -0800615 }
616 img_decoder_ptr->Input(data_ptr, *data_size_ptr);
Nicolas Pena2199ab82017-05-11 18:44:29 -0400617 gif_save_decoding_status(context, GIF_D_STATUS_IMG_DATA);
618 context->img_row_offset += context->img_row_avail_size;
619 context->img_row_avail_size =
620 gif_img_row_bytes - context->img_row_offset;
Lei Zhang94293682016-01-27 18:27:56 -0800621 ret = img_decoder_ptr->Decode(
Nicolas Pena2199ab82017-05-11 18:44:29 -0400622 gif_image_ptr->m_ImageRowBuf.data() + context->img_row_offset,
623 &context->img_row_avail_size);
Lei Zhang94293682016-01-27 18:27:56 -0800624 }
625 }
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400626 if (ret == GifDecodeStatus::InsufficientDestSize) {
Nicolas Pena2e2ee0e2017-05-10 14:42:26 -0400627 if (((GifLF*)&gif_image_ptr->m_ImageInfo.local_flag)->interlace) {
Nicolas Pena2199ab82017-05-11 18:44:29 -0400628 context->ReadScanline(gif_image_ptr->image_row_num,
Nicolas Pena2e2ee0e2017-05-10 14:42:26 -0400629 gif_image_ptr->m_ImageRowBuf.data());
Lei Zhang94293682016-01-27 18:27:56 -0800630 gif_image_ptr->image_row_num +=
Nicolas Pena2199ab82017-05-11 18:44:29 -0400631 s_gif_interlace_step[context->img_pass_num];
Lei Zhang94293682016-01-27 18:27:56 -0800632 if (gif_image_ptr->image_row_num >=
Nicolas Pena2e2ee0e2017-05-10 14:42:26 -0400633 (int32_t)gif_image_ptr->m_ImageInfo.height) {
Nicolas Pena2199ab82017-05-11 18:44:29 -0400634 context->img_pass_num++;
635 if (context->img_pass_num == FX_ArraySize(s_gif_interlace_step)) {
636 gif_decoding_failure_at_tail_cleanup(context, gif_image_ptr);
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400637 return GifDecodeStatus::Error;
hong_zhang8374fe42016-08-12 15:15:56 -0700638 }
Lei Zhang94293682016-01-27 18:27:56 -0800639 gif_image_ptr->image_row_num =
Nicolas Pena2199ab82017-05-11 18:44:29 -0400640 s_gif_interlace_step[context->img_pass_num] / 2;
Lei Zhang94293682016-01-27 18:27:56 -0800641 }
642 } else {
Nicolas Pena2199ab82017-05-11 18:44:29 -0400643 context->ReadScanline(gif_image_ptr->image_row_num++,
Nicolas Pena2e2ee0e2017-05-10 14:42:26 -0400644 gif_image_ptr->m_ImageRowBuf.data());
Lei Zhang94293682016-01-27 18:27:56 -0800645 }
Nicolas Pena2199ab82017-05-11 18:44:29 -0400646 context->img_row_offset = 0;
647 context->img_row_avail_size = gif_img_row_bytes;
Lei Zhang94293682016-01-27 18:27:56 -0800648 ret = img_decoder_ptr->Decode(
Nicolas Pena2199ab82017-05-11 18:44:29 -0400649 gif_image_ptr->m_ImageRowBuf.data() + context->img_row_offset,
650 &context->img_row_avail_size);
Lei Zhang94293682016-01-27 18:27:56 -0800651 }
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400652 if (ret == GifDecodeStatus::Error) {
Nicolas Pena2199ab82017-05-11 18:44:29 -0400653 gif_decoding_failure_at_tail_cleanup(context, gif_image_ptr);
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400654 return GifDecodeStatus::Error;
Lei Zhang94293682016-01-27 18:27:56 -0800655 }
656 }
657 }
Nicolas Pena2199ab82017-05-11 18:44:29 -0400658 gif_save_decoding_status(context, GIF_D_STATUS_TAIL);
Lei Zhang94293682016-01-27 18:27:56 -0800659 }
Nicolas Pena6f3593c2017-05-23 19:07:25 -0400660 context->AddError("Decode Image Data Error");
Nicolas Pena1e5a98a2017-05-03 10:54:23 -0400661 return GifDecodeStatus::Error;
Lei Zhang94293682016-01-27 18:27:56 -0800662}
thestig4997b222016-06-07 10:46:22 -0700663
Nicolas Pena2199ab82017-05-11 18:44:29 -0400664void gif_input_buffer(CGifContext* context,
Lei Zhang4467dea2016-02-25 12:39:15 -0800665 uint8_t* src_buf,
tsepezb5e8f142016-03-25 15:18:35 -0700666 uint32_t src_size) {
Nicolas Pena2199ab82017-05-11 18:44:29 -0400667 context->next_in = src_buf;
668 context->avail_in = src_size;
669 context->skip_size = 0;
Lei Zhang94293682016-01-27 18:27:56 -0800670}
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400671
Nicolas Pena2199ab82017-05-11 18:44:29 -0400672uint32_t gif_get_avail_input(CGifContext* context, uint8_t** avail_buf_ptr) {
thestig4997b222016-06-07 10:46:22 -0700673 if (avail_buf_ptr) {
674 *avail_buf_ptr = nullptr;
Nicolas Pena2199ab82017-05-11 18:44:29 -0400675 if (context->avail_in > 0)
676 *avail_buf_ptr = context->next_in;
Lei Zhang94293682016-01-27 18:27:56 -0800677 }
Nicolas Pena2199ab82017-05-11 18:44:29 -0400678 return context->avail_in;
Lei Zhang94293682016-01-27 18:27:56 -0800679}
Nicolas Penaec3a9e22017-05-02 10:45:35 -0400680
Nicolas Pena2199ab82017-05-11 18:44:29 -0400681int32_t gif_get_frame_num(CGifContext* context) {
682 return pdfium::CollectionSize<int32_t>(context->m_Images);
Lei Zhang94293682016-01-27 18:27:56 -0800683}