summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/fxcodec/gif/cfx_gifcontext.cpp290
-rw-r--r--core/fxcodec/gif/cfx_gifcontext.h8
-rw-r--r--core/fxcodec/gif/cfx_gifcontext_unittest.cpp145
3 files changed, 217 insertions, 226 deletions
diff --git a/core/fxcodec/gif/cfx_gifcontext.cpp b/core/fxcodec/gif/cfx_gifcontext.cpp
index 3bc9546f70..44c2c654f0 100644
--- a/core/fxcodec/gif/cfx_gifcontext.cpp
+++ b/core/fxcodec/gif/cfx_gifcontext.cpp
@@ -27,10 +27,7 @@ CFX_GifContext::CFX_GifContext(CCodec_GifModule* gif_module,
global_pal_exp_(0),
img_row_offset_(0),
img_row_avail_size_(0),
- avail_in_(0),
decode_status_(GIF_D_STATUS_SIG),
- skip_size_(0),
- next_in_(nullptr),
width_(0),
height_(0),
bc_index_(0),
@@ -80,11 +77,11 @@ CFX_GifDecodeStatus CFX_GifContext::GetFrame() {
case GIF_D_STATUS_TAIL:
return CFX_GifDecodeStatus::Success;
case GIF_D_STATUS_SIG: {
- uint8_t* signature = nullptr;
- if (!ReadData(&signature, 1))
+ uint8_t signature;
+ if (!ReadData(&signature, sizeof(signature)))
return CFX_GifDecodeStatus::Unfinished;
- switch (*signature) {
+ switch (signature) {
case GIF_SIG_EXTENSION:
SaveDecodingStatus(GIF_D_STATUS_EXT);
continue;
@@ -95,7 +92,7 @@ CFX_GifDecodeStatus CFX_GifContext::GetFrame() {
SaveDecodingStatus(GIF_D_STATUS_TAIL);
return CFX_GifDecodeStatus::Success;
default:
- if (avail_in_) {
+ if (!input_buffer_->IsEOF()) {
// The Gif File has non_standard Tag!
SaveDecodingStatus(GIF_D_STATUS_SIG);
continue;
@@ -105,11 +102,11 @@ CFX_GifDecodeStatus CFX_GifContext::GetFrame() {
}
}
case GIF_D_STATUS_EXT: {
- uint8_t* extension = nullptr;
- if (!ReadData(&extension, 1))
+ uint8_t extension;
+ if (!ReadData(&extension, sizeof(extension)))
return CFX_GifDecodeStatus::Unfinished;
- switch (*extension) {
+ switch (extension) {
case GIF_BLOCK_CE:
SaveDecodingStatus(GIF_D_STATUS_EXT_CE);
continue;
@@ -121,7 +118,7 @@ CFX_GifDecodeStatus CFX_GifContext::GetFrame() {
continue;
default: {
int32_t status = GIF_D_STATUS_EXT_UNE;
- if (*extension == GIF_BLOCK_PTE) {
+ if (extension == GIF_BLOCK_PTE) {
status = GIF_D_STATUS_EXT_PTE;
}
SaveDecodingStatus(status);
@@ -137,23 +134,27 @@ CFX_GifDecodeStatus CFX_GifContext::GetFrame() {
continue;
}
case GIF_D_STATUS_IMG_DATA: {
- uint8_t* img_data_size = nullptr;
- uint8_t* img_data = nullptr;
- uint32_t skip_size_org = skip_size_;
- if (!ReadData(&img_data_size, 1))
+ uint8_t img_data_size;
+ size_t read_marker = input_buffer_->GetPosition();
+
+ if (!ReadData(&img_data_size, sizeof(img_data_size)))
return CFX_GifDecodeStatus::Unfinished;
- while (*img_data_size != GIF_BLOCK_TERMINAL) {
- if (!ReadData(&img_data, *img_data_size)) {
- skip_size_ = skip_size_org;
+ while (img_data_size != GIF_BLOCK_TERMINAL) {
+ if (!input_buffer_->Seek(input_buffer_->GetPosition() +
+ img_data_size)) {
+ input_buffer_->Seek(read_marker);
return CFX_GifDecodeStatus::Unfinished;
}
+ // This saving of the scan state on partial reads is why
+ // ScanForTerminalMarker() cannot be used here.
SaveDecodingStatus(GIF_D_STATUS_IMG_DATA);
- skip_size_org = skip_size_;
- if (!ReadData(&img_data_size, 1))
+ read_marker = input_buffer_->GetPosition();
+ if (!ReadData(&img_data_size, sizeof(img_data_size)))
return CFX_GifDecodeStatus::Unfinished;
}
+
SaveDecodingStatus(GIF_D_STATUS_SIG);
continue;
}
@@ -172,9 +173,6 @@ CFX_GifDecodeStatus CFX_GifContext::LoadFrame(int32_t frame_num) {
if (!pdfium::IndexInBounds(images_, frame_num))
return CFX_GifDecodeStatus::Error;
- uint8_t* img_data_size = nullptr;
- uint8_t* img_data = nullptr;
- uint32_t skip_size_org = skip_size_;
CFX_GifImage* gif_image = images_[static_cast<size_t>(frame_num)].get();
if (gif_image->image_info.height == 0)
return CFX_GifDecodeStatus::Error;
@@ -190,7 +188,6 @@ CFX_GifDecodeStatus CFX_GifContext::LoadFrame(int32_t frame_num) {
gif_image->image_info.local_flags.local_pal
? (2 << gif_image->image_info.local_flags.pal_bits)
: 0;
- avail_in_ = 0;
CFX_GifPalette* pLocalPalette = gif_image->local_palettes.empty()
? nullptr
: gif_image->local_palettes.data();
@@ -234,13 +231,18 @@ CFX_GifDecodeStatus CFX_GifContext::LoadFrame(int32_t frame_num) {
SaveDecodingStatus(GIF_D_STATUS_IMG_DATA);
}
+ uint8_t img_data_size;
+ std::vector<uint8_t> img_data;
+ size_t read_marker = input_buffer_->GetPosition();
+
if (decode_status_ == GIF_D_STATUS_IMG_DATA) {
- if (!ReadData(&img_data_size, 1))
+ if (!ReadData(&img_data_size, sizeof(img_data_size)))
return CFX_GifDecodeStatus::Unfinished;
- if (*img_data_size != GIF_BLOCK_TERMINAL) {
- if (!ReadData(&img_data, *img_data_size)) {
- skip_size_ = skip_size_org;
+ if (img_data_size != GIF_BLOCK_TERMINAL) {
+ img_data.resize(img_data_size);
+ if (!ReadData(img_data.data(), img_data_size)) {
+ input_buffer_->Seek(read_marker);
return CFX_GifDecodeStatus::Unfinished;
}
@@ -255,7 +257,7 @@ CFX_GifDecodeStatus CFX_GifContext::LoadFrame(int32_t frame_num) {
CFX_GifDecodeStatus ret =
lzw_decompressor_.get()
? lzw_decompressor_->Decode(
- img_data, *img_data_size,
+ img_data.data(), img_data_size,
gif_image->row_buffer.data() + img_row_offset_,
&img_row_avail_size_)
: CFX_GifDecodeStatus::Error;
@@ -263,6 +265,7 @@ CFX_GifDecodeStatus CFX_GifContext::LoadFrame(int32_t frame_num) {
DecodingFailureAtTailCleanup(gif_image);
return CFX_GifDecodeStatus::Error;
}
+
while (ret != CFX_GifDecodeStatus::Error) {
if (ret == CFX_GifDecodeStatus::Success) {
ReadScanline(gif_image->row_num, gif_image->row_buffer.data());
@@ -270,16 +273,19 @@ CFX_GifDecodeStatus CFX_GifContext::LoadFrame(int32_t frame_num) {
SaveDecodingStatus(GIF_D_STATUS_TAIL);
return CFX_GifDecodeStatus::Success;
}
+
if (ret == CFX_GifDecodeStatus::Unfinished) {
- skip_size_org = skip_size_;
- if (!ReadData(&img_data_size, 1))
+ read_marker = input_buffer_->GetPosition();
+ if (!ReadData(&img_data_size, sizeof(img_data_size)))
return CFX_GifDecodeStatus::Unfinished;
- if (*img_data_size != GIF_BLOCK_TERMINAL) {
- if (!ReadData(&img_data, *img_data_size)) {
- skip_size_ = skip_size_org;
+ if (img_data_size != GIF_BLOCK_TERMINAL) {
+ img_data.resize(img_data_size);
+ if (!ReadData(img_data.data(), img_data_size)) {
+ input_buffer_->Seek(read_marker);
return CFX_GifDecodeStatus::Unfinished;
}
+
if (!lzw_decompressor_.get())
lzw_decompressor_ = CFX_LZWDecompressor::Create(
!gif_image->local_palettes.empty()
@@ -291,12 +297,13 @@ CFX_GifDecodeStatus CFX_GifContext::LoadFrame(int32_t frame_num) {
img_row_avail_size_ = gif_img_row_bytes - img_row_offset_;
ret = lzw_decompressor_.get()
? lzw_decompressor_->Decode(
- img_data, *img_data_size,
+ img_data.data(), img_data_size,
gif_image->row_buffer.data() + img_row_offset_,
&img_row_avail_size_)
: CFX_GifDecodeStatus::Error;
}
}
+
if (ret == CFX_GifDecodeStatus::InsufficientDestSize) {
if (gif_image->image_info.local_flags.interlace) {
ReadScanline(gif_image->row_num, gif_image->row_buffer.data());
@@ -317,11 +324,12 @@ CFX_GifDecodeStatus CFX_GifContext::LoadFrame(int32_t frame_num) {
img_row_avail_size_ = gif_img_row_bytes;
ret = lzw_decompressor_.get()
? lzw_decompressor_->Decode(
- img_data, *img_data_size,
+ img_data.data(), img_data_size,
gif_image->row_buffer.data() + img_row_offset_,
&img_row_avail_size_)
: CFX_GifDecodeStatus::Error;
}
+
if (ret == CFX_GifDecodeStatus::InsufficientDestSize ||
ret == CFX_GifDecodeStatus::Error) {
DecodingFailureAtTailCleanup(gif_image);
@@ -335,163 +343,140 @@ CFX_GifDecodeStatus CFX_GifContext::LoadFrame(int32_t frame_num) {
}
void CFX_GifContext::SetInputBuffer(uint8_t* src_buf, uint32_t src_size) {
- next_in_ = src_buf;
- avail_in_ = src_size;
- skip_size_ = 0;
+ input_buffer_ =
+ pdfium::MakeRetain<CFX_MemoryStream>(src_buf, src_size, false);
}
uint32_t CFX_GifContext::GetAvailInput(uint8_t** avail_buf) const {
+ if (!input_buffer_)
+ return 0;
+
+ FX_FILESIZE available_size =
+ input_buffer_->GetSize() - input_buffer_->GetPosition();
if (avail_buf) {
*avail_buf = nullptr;
- if (avail_in_ > 0)
- *avail_buf = next_in_;
+ if (available_size > 0)
+ *avail_buf = input_buffer_->GetBuffer() + available_size;
}
- return avail_in_;
+
+ return available_size;
}
-uint8_t* CFX_GifContext::ReadData(uint8_t** dest_buf_pp, uint32_t data_size) {
- if (!next_in_)
- return nullptr;
- if (avail_in_ <= skip_size_)
- return nullptr;
- if (!dest_buf_pp)
- return nullptr;
- if (data_size == 0)
- return nullptr;
- if (avail_in_ - skip_size_ < data_size)
- return nullptr;
-
- *dest_buf_pp = next_in_ + skip_size_;
- skip_size_ += data_size;
- return *dest_buf_pp;
+bool CFX_GifContext::ReadData(uint8_t* dest, uint32_t size) {
+ if (!input_buffer_ || !dest)
+ return false;
+
+ size_t read_marker = input_buffer_->GetPosition();
+ size_t read = input_buffer_->ReadBlock(dest, size);
+ if (read < size) {
+ input_buffer_->Seek(read_marker);
+ return false;
+ }
+
+ return true;
}
CFX_GifDecodeStatus CFX_GifContext::ReadGifSignature() {
- CFX_GifHeader* header = nullptr;
- uint32_t skip_size_org = skip_size_;
- if (!ReadData(reinterpret_cast<uint8_t**>(&header), 6)) {
- skip_size_ = skip_size_org;
+ CFX_GifHeader header;
+ if (!ReadData(reinterpret_cast<uint8_t*>(&header), 6))
return CFX_GifDecodeStatus::Unfinished;
- }
- if (strncmp(header->signature, kGifSignature87, 6) != 0 &&
- strncmp(header->signature, kGifSignature89, 6) != 0)
+ if (strncmp(header.signature, kGifSignature87, 6) != 0 &&
+ strncmp(header.signature, kGifSignature89, 6) != 0) {
return CFX_GifDecodeStatus::Error;
+ }
return CFX_GifDecodeStatus::Success;
}
CFX_GifDecodeStatus CFX_GifContext::ReadLogicalScreenDescriptor() {
- CFX_GifLocalScreenDescriptor* lsd = nullptr;
- uint32_t skip_size_org = skip_size_;
- if (!ReadData(reinterpret_cast<uint8_t**>(&lsd), 7)) {
- skip_size_ = skip_size_org;
+ CFX_GifLocalScreenDescriptor lsd;
+ size_t read_marker = input_buffer_->GetPosition();
+
+ if (!ReadData(reinterpret_cast<uint8_t*>(&lsd), sizeof(lsd)))
return CFX_GifDecodeStatus::Unfinished;
- }
- if (lsd->global_flags.global_pal) {
- uint32_t palette_count = unsigned(2 << lsd->global_flags.pal_bits);
- if (lsd->bc_index >= palette_count)
+ if (lsd.global_flags.global_pal) {
+ uint32_t palette_count = unsigned(2 << lsd.global_flags.pal_bits);
+ if (lsd.bc_index >= palette_count)
return CFX_GifDecodeStatus::Error;
- bc_index_ = lsd->bc_index;
+ bc_index_ = lsd.bc_index;
- uint32_t palette_size = palette_count * 3u;
- uint8_t* palette = nullptr;
- if (!ReadData(&palette, palette_size)) {
- skip_size_ = skip_size_org;
+ uint32_t palette_size = palette_count * sizeof(CFX_GifPalette);
+ std::vector<CFX_GifPalette> palette(palette_count);
+ if (!ReadData(reinterpret_cast<uint8_t*>(palette.data()), palette_size)) {
+ // Roll back the read for the LSD
+ input_buffer_->Seek(read_marker);
return CFX_GifDecodeStatus::Unfinished;
}
- global_pal_exp_ = lsd->global_flags.pal_bits;
- global_sort_flag_ = lsd->global_flags.sort_flag;
- global_color_resolution_ = lsd->global_flags.color_resolution;
- global_palette_.resize(palette_count);
- memcpy(global_palette_.data(), palette, palette_size);
+ global_pal_exp_ = lsd.global_flags.pal_bits;
+ global_sort_flag_ = lsd.global_flags.sort_flag;
+ global_color_resolution_ = lsd.global_flags.color_resolution;
+ std::swap(global_palette_, palette);
}
width_ = static_cast<int>(
- FXWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&lsd->width)));
+ FXWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&lsd.width)));
height_ = static_cast<int>(
- FXWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&lsd->height)));
+ FXWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&lsd.height)));
- pixel_aspect_ = lsd->pixel_aspect;
+ pixel_aspect_ = lsd.pixel_aspect;
return CFX_GifDecodeStatus::Success;
}
void CFX_GifContext::SaveDecodingStatus(int32_t status) {
decode_status_ = status;
- next_in_ += skip_size_;
- avail_in_ -= skip_size_;
- skip_size_ = 0;
}
CFX_GifDecodeStatus CFX_GifContext::DecodeExtension() {
- uint8_t* data_size = nullptr;
- uint8_t* data_buf = nullptr;
- uint32_t skip_size_org = skip_size_;
+ size_t read_marker = input_buffer_->GetPosition();
+
switch (decode_status_) {
case GIF_D_STATUS_EXT_CE: {
- if (!ReadData(&data_size, 1)) {
- skip_size_ = skip_size_org;
+ if (!ScanForTerminalMarker()) {
+ input_buffer_->Seek(read_marker);
return CFX_GifDecodeStatus::Unfinished;
}
-
- while (*data_size != GIF_BLOCK_TERMINAL) {
- if (!ReadData(&data_buf, *data_size) || !ReadData(&data_size, 1)) {
- skip_size_ = skip_size_org;
- return CFX_GifDecodeStatus::Unfinished;
- }
- }
break;
}
case GIF_D_STATUS_EXT_PTE: {
- CFX_GifPlainTextExtension* gif_pte = nullptr;
- if (!ReadData(reinterpret_cast<uint8_t**>(&gif_pte), 13))
+ CFX_GifPlainTextExtension gif_pte;
+ if (!ReadData(reinterpret_cast<uint8_t*>(&gif_pte), sizeof(gif_pte)))
return CFX_GifDecodeStatus::Unfinished;
graphic_control_extension_ = nullptr;
- if (!ReadData(&data_size, 1)) {
- skip_size_ = skip_size_org;
+ if (!ScanForTerminalMarker()) {
+ input_buffer_->Seek(read_marker);
return CFX_GifDecodeStatus::Unfinished;
}
-
- while (*data_size != GIF_BLOCK_TERMINAL) {
- if (!ReadData(&data_buf, *data_size) || !ReadData(&data_size, 1)) {
- skip_size_ = skip_size_org;
- return CFX_GifDecodeStatus::Unfinished;
- }
- }
break;
}
case GIF_D_STATUS_EXT_GCE: {
- CFX_GifGraphicControlExtension* gif_gce = nullptr;
- if (!ReadData(reinterpret_cast<uint8_t**>(&gif_gce), 6))
+ CFX_GifGraphicControlExtension gif_gce;
+ if (!ReadData(reinterpret_cast<uint8_t*>(&gif_gce), sizeof(gif_gce)))
return CFX_GifDecodeStatus::Unfinished;
if (!graphic_control_extension_.get())
graphic_control_extension_ =
pdfium::MakeUnique<CFX_GifGraphicControlExtension>();
- graphic_control_extension_->block_size = gif_gce->block_size;
- graphic_control_extension_->gce_flags = gif_gce->gce_flags;
+ graphic_control_extension_->block_size = gif_gce.block_size;
+ graphic_control_extension_->gce_flags = gif_gce.gce_flags;
graphic_control_extension_->delay_time =
- FXWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&gif_gce->delay_time));
- graphic_control_extension_->trans_index = gif_gce->trans_index;
+ FXWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&gif_gce.delay_time));
+ graphic_control_extension_->trans_index = gif_gce.trans_index;
break;
}
default: {
if (decode_status_ == GIF_D_STATUS_EXT_PTE)
graphic_control_extension_ = nullptr;
- if (!ReadData(&data_size, 1))
+ if (!ScanForTerminalMarker()) {
+ input_buffer_->Seek(read_marker);
return CFX_GifDecodeStatus::Unfinished;
-
- while (*data_size != GIF_BLOCK_TERMINAL) {
- if (!ReadData(&data_buf, *data_size) || !ReadData(&data_size, 1)) {
- skip_size_ = skip_size_org;
- return CFX_GifDecodeStatus::Unfinished;
- }
}
}
}
+
SaveDecodingStatus(GIF_D_STATUS_SIG);
return CFX_GifDecodeStatus::Success;
}
@@ -500,49 +485,48 @@ CFX_GifDecodeStatus CFX_GifContext::DecodeImageInfo() {
if (width_ <= 0 || height_ <= 0)
return CFX_GifDecodeStatus::Error;
- uint32_t skip_size_org = skip_size_;
- CFX_CFX_GifImageInfo* img_info = nullptr;
- if (!ReadData(reinterpret_cast<uint8_t**>(&img_info), 9))
+ size_t read_marker = input_buffer_->GetPosition();
+ CFX_CFX_GifImageInfo img_info;
+ if (!ReadData(reinterpret_cast<uint8_t*>(&img_info), sizeof(img_info)))
return CFX_GifDecodeStatus::Unfinished;
auto gif_image = pdfium::MakeUnique<CFX_GifImage>();
gif_image->image_info.left =
- FXWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&img_info->left));
+ FXWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&img_info.left));
gif_image->image_info.top =
- FXWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&img_info->top));
+ FXWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&img_info.top));
gif_image->image_info.width =
- FXWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&img_info->width));
+ FXWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&img_info.width));
gif_image->image_info.height =
- FXWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&img_info->height));
- gif_image->image_info.local_flags = img_info->local_flags;
+ FXWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&img_info.height));
+ gif_image->image_info.local_flags = img_info.local_flags;
if (gif_image->image_info.left + gif_image->image_info.width > width_ ||
gif_image->image_info.top + gif_image->image_info.height > height_)
return CFX_GifDecodeStatus::Error;
- CFX_GifLocalFlags* gif_img_info_lf = &img_info->local_flags;
+ CFX_GifLocalFlags* gif_img_info_lf = &img_info.local_flags;
if (gif_img_info_lf->local_pal) {
gif_image->local_pallette_exp = gif_img_info_lf->pal_bits;
- uint32_t loc_pal_size = unsigned(2 << gif_img_info_lf->pal_bits) * 3u;
- uint8_t* loc_pal = nullptr;
- if (!ReadData(&loc_pal, loc_pal_size)) {
- skip_size_ = skip_size_org;
+ uint32_t loc_pal_count = unsigned(2 << gif_img_info_lf->pal_bits);
+ std::vector<CFX_GifPalette> loc_pal(loc_pal_count);
+ if (!ReadData(reinterpret_cast<uint8_t*>(loc_pal.data()),
+ loc_pal_count * sizeof(CFX_GifPalette))) {
+ input_buffer_->Seek(read_marker);
return CFX_GifDecodeStatus::Unfinished;
}
- gif_image->local_palettes = std::vector<CFX_GifPalette>(loc_pal_size / 3);
- std::copy(loc_pal, loc_pal + loc_pal_size,
- reinterpret_cast<uint8_t*>(gif_image->local_palettes.data()));
+ gif_image->local_palettes = std::move(loc_pal);
}
- uint8_t* code_size = nullptr;
- if (!ReadData(&code_size, 1)) {
- skip_size_ = skip_size_org;
+ uint8_t code_size;
+ if (!ReadData(&code_size, sizeof(code_size))) {
+ input_buffer_->Seek(read_marker);
return CFX_GifDecodeStatus::Unfinished;
}
- gif_image->code_exp = *code_size;
+ gif_image->code_exp = code_size;
RecordCurrentPosition(&gif_image->data_pos);
- gif_image->data_pos += skip_size_;
+ gif_image->data_pos += input_buffer_->GetPosition();
gif_image->image_GCE = nullptr;
if (graphic_control_extension_.get()) {
if (graphic_control_extension_->gce_flags.transparency) {
@@ -567,3 +551,19 @@ void CFX_GifContext::DecodingFailureAtTailCleanup(CFX_GifImage* gif_image) {
gif_image->row_buffer.clear();
SaveDecodingStatus(GIF_D_STATUS_TAIL);
}
+
+bool CFX_GifContext::ScanForTerminalMarker() {
+ uint8_t data_size;
+
+ if (!ReadData(&data_size, sizeof(data_size)))
+ return false;
+
+ while (data_size != GIF_BLOCK_TERMINAL) {
+ if (!input_buffer_->Seek(input_buffer_->GetPosition() + data_size) ||
+ !ReadData(&data_size, sizeof(data_size))) {
+ return false;
+ }
+ }
+
+ return true;
+}
diff --git a/core/fxcodec/gif/cfx_gifcontext.h b/core/fxcodec/gif/cfx_gifcontext.h
index 597af73764..d9bcf4950d 100644
--- a/core/fxcodec/gif/cfx_gifcontext.h
+++ b/core/fxcodec/gif/cfx_gifcontext.h
@@ -13,6 +13,7 @@
#include "core/fxcodec/codec/ccodec_gifmodule.h"
#include "core/fxcodec/gif/cfx_gif.h"
#include "core/fxcodec/gif/cfx_lzwdecompressor.h"
+#include "core/fxcrt/cfx_memorystream.h"
#include "core/fxcrt/fx_string.h"
#include "core/fxcrt/unowned_ptr.h"
@@ -49,11 +50,8 @@ class CFX_GifContext : public CCodec_GifModule::Context {
uint8_t global_pal_exp_;
uint32_t img_row_offset_;
uint32_t img_row_avail_size_;
- uint32_t avail_in_;
int32_t decode_status_;
- uint32_t skip_size_;
std::unique_ptr<CFX_GifGraphicControlExtension> graphic_control_extension_;
- uint8_t* next_in_;
std::vector<std::unique_ptr<CFX_GifImage>> images_;
std::unique_ptr<CFX_LZWDecompressor> lzw_decompressor_;
int width_;
@@ -65,15 +63,17 @@ class CFX_GifContext : public CCodec_GifModule::Context {
uint8_t img_pass_num_;
protected:
- uint8_t* ReadData(uint8_t** dest_buf_pp, uint32_t data_size);
+ bool ReadData(uint8_t* dest, uint32_t size);
CFX_GifDecodeStatus ReadGifSignature();
CFX_GifDecodeStatus ReadLogicalScreenDescriptor();
+ RetainPtr<CFX_MemoryStream> input_buffer_;
private:
void SaveDecodingStatus(int32_t status);
CFX_GifDecodeStatus DecodeExtension();
CFX_GifDecodeStatus DecodeImageInfo();
void DecodingFailureAtTailCleanup(CFX_GifImage* gif_image);
+ bool ScanForTerminalMarker();
};
#endif // CORE_FXCODEC_GIF_CFX_GIFCONTEXT_H_
diff --git a/core/fxcodec/gif/cfx_gifcontext_unittest.cpp b/core/fxcodec/gif/cfx_gifcontext_unittest.cpp
index c5d3ac90c7..20aa6913d0 100644
--- a/core/fxcodec/gif/cfx_gifcontext_unittest.cpp
+++ b/core/fxcodec/gif/cfx_gifcontext_unittest.cpp
@@ -17,93 +17,76 @@ class CFX_GifContextForTest : public CFX_GifContext {
using CFX_GifContext::ReadData;
using CFX_GifContext::ReadGifSignature;
using CFX_GifContext::ReadLogicalScreenDescriptor;
+
+ CFX_MemoryStream* InputBuffer() const { return input_buffer_.Get(); }
};
TEST(CFX_GifContext, SetInputBuffer) {
CFX_GifContextForTest context(nullptr, nullptr);
context.SetInputBuffer(nullptr, 0);
- EXPECT_EQ(nullptr, context.next_in_);
- EXPECT_EQ(0u, context.avail_in_);
- EXPECT_EQ(0u, context.skip_size_);
+ EXPECT_EQ(nullptr, context.InputBuffer()->GetBuffer());
+ EXPECT_EQ(0, context.InputBuffer()->GetSize());
+ EXPECT_EQ(0, context.InputBuffer()->GetPosition());
context.SetInputBuffer(nullptr, 100);
- EXPECT_EQ(nullptr, context.next_in_);
- EXPECT_EQ(100u, context.avail_in_);
- EXPECT_EQ(0u, context.skip_size_);
+ EXPECT_EQ(nullptr, context.InputBuffer()->GetBuffer());
+ EXPECT_EQ(100, context.InputBuffer()->GetSize());
+ EXPECT_EQ(0, context.InputBuffer()->GetPosition());
uint8_t buffer[] = {0x00, 0x01, 0x02};
context.SetInputBuffer(buffer, 0);
- EXPECT_EQ(buffer, context.next_in_);
- EXPECT_EQ(0u, context.avail_in_);
- EXPECT_EQ(0u, context.skip_size_);
+ EXPECT_EQ(buffer, context.InputBuffer()->GetBuffer());
+ EXPECT_EQ(0, context.InputBuffer()->GetSize());
+ EXPECT_EQ(0, context.InputBuffer()->GetPosition());
context.SetInputBuffer(buffer, 3);
- EXPECT_EQ(buffer, context.next_in_);
- EXPECT_EQ(3u, context.avail_in_);
- EXPECT_EQ(0u, context.skip_size_);
+ EXPECT_EQ(buffer, context.InputBuffer()->GetBuffer());
+ EXPECT_EQ(3, context.InputBuffer()->GetSize());
+ EXPECT_EQ(0, context.InputBuffer()->GetPosition());
context.SetInputBuffer(buffer, 100);
- EXPECT_EQ(buffer, context.next_in_);
- EXPECT_EQ(100u, context.avail_in_);
- EXPECT_EQ(0u, context.skip_size_);
+ EXPECT_EQ(buffer, context.InputBuffer()->GetBuffer());
+ EXPECT_EQ(100, context.InputBuffer()->GetSize());
+ EXPECT_EQ(0, context.InputBuffer()->GetPosition());
}
TEST(CFX_GifContext, ReadData) {
CFX_GifContextForTest context(nullptr, nullptr);
context.SetInputBuffer(nullptr, 0);
- EXPECT_EQ(nullptr, context.ReadData(nullptr, 0));
- EXPECT_EQ(nullptr, context.ReadData(nullptr, 10));
+ EXPECT_FALSE(context.ReadData(nullptr, 0));
+ EXPECT_FALSE(context.ReadData(nullptr, 10));
- uint8_t* dest_buffer = nullptr;
- EXPECT_EQ(nullptr,
- context.ReadData(reinterpret_cast<uint8_t**>(&dest_buffer), 0));
- EXPECT_EQ(nullptr,
- context.ReadData(reinterpret_cast<uint8_t**>(&dest_buffer), 10));
+ std::vector<uint8_t> dest_buffer;
+ EXPECT_FALSE(context.ReadData(dest_buffer.data(), 0));
+ EXPECT_FALSE(context.ReadData(dest_buffer.data(), 10));
uint8_t src_buffer[] = {0x00, 0x01, 0x02, 0x03, 0x04,
0x05, 0x06, 0x07, 0x08, 0x09};
context.SetInputBuffer(src_buffer, 0);
- EXPECT_EQ(nullptr,
- context.ReadData(reinterpret_cast<uint8_t**>(&dest_buffer), 10));
- EXPECT_EQ(reinterpret_cast<uint8_t*>(src_buffer), context.next_in_);
- EXPECT_EQ(0u, context.avail_in_);
- EXPECT_EQ(0u, context.skip_size_);
-
- dest_buffer = nullptr;
- context.SetInputBuffer(src_buffer, 10);
- EXPECT_EQ(src_buffer,
- context.ReadData(reinterpret_cast<uint8_t**>(&dest_buffer), 10));
- EXPECT_EQ(reinterpret_cast<uint8_t*>(src_buffer), dest_buffer);
- EXPECT_EQ(src_buffer, context.next_in_);
- EXPECT_EQ(10u, context.avail_in_);
- EXPECT_EQ(10u, context.skip_size_);
-
- dest_buffer = nullptr;
- context.SetInputBuffer(src_buffer, 10);
- EXPECT_EQ(src_buffer,
- context.ReadData(reinterpret_cast<uint8_t**>(&dest_buffer), 5));
- EXPECT_EQ(reinterpret_cast<uint8_t*>(src_buffer), dest_buffer);
- EXPECT_EQ(src_buffer, context.next_in_);
- EXPECT_EQ(10u, context.avail_in_);
- EXPECT_EQ(5u, context.skip_size_);
-
- dest_buffer = nullptr;
- EXPECT_EQ(src_buffer + 5,
- context.ReadData(reinterpret_cast<uint8_t**>(&dest_buffer), 5));
- EXPECT_EQ(reinterpret_cast<uint8_t*>(src_buffer + 5), dest_buffer);
- EXPECT_EQ(src_buffer, context.next_in_);
- EXPECT_EQ(10u, context.avail_in_);
- EXPECT_EQ(10u, context.skip_size_);
-
- dest_buffer = nullptr;
- EXPECT_EQ(nullptr,
- context.ReadData(reinterpret_cast<uint8_t**>(&dest_buffer), 5));
- EXPECT_EQ(nullptr, dest_buffer);
- EXPECT_EQ(src_buffer, context.next_in_);
- EXPECT_EQ(10u, context.avail_in_);
- EXPECT_EQ(10u, context.skip_size_);
+ dest_buffer.resize(sizeof(src_buffer));
+ EXPECT_FALSE(context.ReadData(dest_buffer.data(), sizeof(src_buffer)));
+
+ context.SetInputBuffer(src_buffer, 1);
+ EXPECT_FALSE(context.ReadData(dest_buffer.data(), sizeof(src_buffer)));
+ EXPECT_EQ(0, context.InputBuffer()->GetPosition());
+ EXPECT_FALSE(context.ReadData(nullptr, sizeof(src_buffer)));
+ EXPECT_FALSE(context.ReadData(nullptr, 1));
+ EXPECT_TRUE(context.ReadData(dest_buffer.data(), 1));
+ EXPECT_EQ(src_buffer[0], dest_buffer[0]);
+
+ context.SetInputBuffer(src_buffer, sizeof(src_buffer));
+ EXPECT_FALSE(context.ReadData(nullptr, sizeof(src_buffer)));
+ EXPECT_TRUE(context.ReadData(dest_buffer.data(), sizeof(src_buffer)));
+ for (size_t i = 0; i < sizeof(src_buffer); i++)
+ EXPECT_EQ(src_buffer[i], dest_buffer[i]);
+
+ context.SetInputBuffer(src_buffer, sizeof(src_buffer));
+ for (size_t i = 0; i < sizeof(src_buffer); i++) {
+ EXPECT_TRUE(context.ReadData(dest_buffer.data(), 1));
+ EXPECT_EQ(src_buffer[i], dest_buffer[0]);
+ }
}
TEST(CFX_GifContext, ReadGifSignature) {
@@ -113,48 +96,48 @@ TEST(CFX_GifContext, ReadGifSignature) {
uint8_t data[1];
context.SetInputBuffer(data, 0);
EXPECT_EQ(CFX_GifDecodeStatus::Unfinished, context.ReadGifSignature());
- EXPECT_EQ(0u, context.skip_size_);
+ EXPECT_EQ(0, context.InputBuffer()->GetPosition());
}
// Make sure testing the entire signature
{
uint8_t data[] = {'G', 'I', 'F'};
context.SetInputBuffer(data, sizeof(data));
EXPECT_EQ(CFX_GifDecodeStatus::Unfinished, context.ReadGifSignature());
- EXPECT_EQ(0u, context.skip_size_);
+ EXPECT_EQ(0, context.InputBuffer()->GetPosition());
}
{
uint8_t data[] = {'N', 'O', 'T', 'G', 'I', 'F'};
context.SetInputBuffer(data, sizeof(data));
EXPECT_EQ(CFX_GifDecodeStatus::Error, context.ReadGifSignature());
- EXPECT_EQ(6u, context.skip_size_);
+ EXPECT_EQ(6, context.InputBuffer()->GetPosition());
}
// Make sure not matching GIF8*a
{
uint8_t data[] = {'G', 'I', 'F', '8', '0', 'a'};
context.SetInputBuffer(data, sizeof(data));
EXPECT_EQ(CFX_GifDecodeStatus::Error, context.ReadGifSignature());
- EXPECT_EQ(6u, context.skip_size_);
+ EXPECT_EQ(6, context.InputBuffer()->GetPosition());
}
// Make sure not matching GIF**a
{
uint8_t data[] = {'G', 'I', 'F', '9', '2', 'a'};
context.SetInputBuffer(data, sizeof(data));
EXPECT_EQ(CFX_GifDecodeStatus::Error, context.ReadGifSignature());
- EXPECT_EQ(6u, context.skip_size_);
+ EXPECT_EQ(6, context.InputBuffer()->GetPosition());
}
// One valid signature
{
uint8_t data[] = {'G', 'I', 'F', '8', '7', 'a'};
context.SetInputBuffer(data, sizeof(data));
EXPECT_EQ(CFX_GifDecodeStatus::Success, context.ReadGifSignature());
- EXPECT_EQ(6u, context.skip_size_);
+ EXPECT_EQ(6, context.InputBuffer()->GetPosition());
}
// The other valid signature
{
uint8_t data[] = {'G', 'I', 'F', '8', '9', 'a'};
context.SetInputBuffer(data, sizeof(data));
EXPECT_EQ(CFX_GifDecodeStatus::Success, context.ReadGifSignature());
- EXPECT_EQ(6u, context.skip_size_);
+ EXPECT_EQ(6, context.InputBuffer()->GetPosition());
}
}
@@ -175,7 +158,8 @@ TEST(CFX_GifContext, ReadLocalScreenDescriptor) {
EXPECT_EQ(CFX_GifDecodeStatus::Success,
context.ReadLogicalScreenDescriptor());
- EXPECT_EQ(sizeof(CFX_GifLocalScreenDescriptor), context.skip_size_);
+ EXPECT_EQ(sizeof(CFX_GifLocalScreenDescriptor),
+ static_cast<size_t>(context.InputBuffer()->GetPosition()));
EXPECT_EQ(0, context.width_);
EXPECT_EQ(0, context.height_);
EXPECT_EQ(0u, context.bc_index_);
@@ -190,7 +174,8 @@ TEST(CFX_GifContext, ReadLocalScreenDescriptor) {
EXPECT_EQ(CFX_GifDecodeStatus::Success,
context.ReadLogicalScreenDescriptor());
- EXPECT_EQ(sizeof(CFX_GifLocalScreenDescriptor), context.skip_size_);
+ EXPECT_EQ(sizeof(CFX_GifLocalScreenDescriptor),
+ static_cast<size_t>(context.InputBuffer()->GetPosition()));
EXPECT_EQ(0x000A, context.width_);
EXPECT_EQ(0x0F00, context.height_);
EXPECT_EQ(0u, context.bc_index_); // bc_index_ is 0 if no global palette
@@ -205,7 +190,7 @@ TEST(CFX_GifContext, ReadLocalScreenDescriptor) {
EXPECT_EQ(CFX_GifDecodeStatus::Unfinished,
context.ReadLogicalScreenDescriptor());
- EXPECT_EQ(0u, context.skip_size_);
+ EXPECT_EQ(0, context.InputBuffer()->GetPosition());
}
// LSD with global palette
{
@@ -219,7 +204,8 @@ TEST(CFX_GifContext, ReadLocalScreenDescriptor) {
EXPECT_EQ(CFX_GifDecodeStatus::Success,
context.ReadLogicalScreenDescriptor());
- EXPECT_EQ(sizeof(data), context.skip_size_);
+ EXPECT_EQ(sizeof(data),
+ static_cast<size_t>(context.InputBuffer()->GetPosition()));
EXPECT_EQ(0x000A, context.width_);
EXPECT_EQ(0x0F00, context.height_);
EXPECT_EQ(1u, context.bc_index_);
@@ -246,7 +232,8 @@ TEST(CFX_GifContext, ReadHeader) {
EXPECT_EQ(CFX_GifDecodeStatus::Error, context.ReadHeader());
- EXPECT_EQ(sizeof(data.signature), context.skip_size_);
+ EXPECT_EQ(sizeof(data.signature),
+ static_cast<size_t>(context.InputBuffer()->GetPosition()));
}
// Short after signature
{
@@ -256,7 +243,8 @@ TEST(CFX_GifContext, ReadHeader) {
EXPECT_EQ(CFX_GifDecodeStatus::Unfinished, context.ReadHeader());
- EXPECT_EQ(sizeof(signature), context.skip_size_);
+ EXPECT_EQ(sizeof(signature),
+ static_cast<size_t>(context.InputBuffer()->GetPosition()));
}
// Success without global palette
{
@@ -269,7 +257,8 @@ TEST(CFX_GifContext, ReadHeader) {
EXPECT_EQ(CFX_GifDecodeStatus::Success, context.ReadHeader());
- EXPECT_EQ(sizeof(data), context.skip_size_);
+ EXPECT_EQ(sizeof(data),
+ static_cast<size_t>(context.InputBuffer()->GetPosition()));
EXPECT_EQ(0x000A, context.width_);
EXPECT_EQ(0x0F00, context.height_);
EXPECT_EQ(0u, context.bc_index_); // bc_index_ is 0 if no global palette
@@ -286,7 +275,8 @@ TEST(CFX_GifContext, ReadHeader) {
EXPECT_EQ(CFX_GifDecodeStatus::Unfinished, context.ReadHeader());
- EXPECT_EQ(sizeof(data.signature), context.skip_size_);
+ EXPECT_EQ(sizeof(data.signature),
+ static_cast<size_t>(context.InputBuffer()->GetPosition()));
}
// Success with global palette
{
@@ -301,7 +291,8 @@ TEST(CFX_GifContext, ReadHeader) {
EXPECT_EQ(CFX_GifDecodeStatus::Success, context.ReadHeader());
- EXPECT_EQ(sizeof(data), context.skip_size_);
+ EXPECT_EQ(sizeof(data),
+ static_cast<size_t>(context.InputBuffer()->GetPosition()));
EXPECT_EQ(0x000A, context.width_);
EXPECT_EQ(0x0F00, context.height_);
EXPECT_EQ(1u, context.bc_index_);