summaryrefslogtreecommitdiff
path: root/core/fxcodec/lgif
diff options
context:
space:
mode:
Diffstat (limited to 'core/fxcodec/lgif')
-rw-r--r--core/fxcodec/lgif/cgifcontext.cpp2
-rw-r--r--core/fxcodec/lgif/cgifcontext.h2
-rw-r--r--core/fxcodec/lgif/fx_gif.cpp32
-rw-r--r--core/fxcodec/lgif/fx_gif.h7
4 files changed, 28 insertions, 15 deletions
diff --git a/core/fxcodec/lgif/cgifcontext.cpp b/core/fxcodec/lgif/cgifcontext.cpp
index e57e978218..4dc663644c 100644
--- a/core/fxcodec/lgif/cgifcontext.cpp
+++ b/core/fxcodec/lgif/cgifcontext.cpp
@@ -17,7 +17,7 @@ CGifContext::CGifContext(CCodec_GifModule* gif_module,
CCodec_GifModule::Delegate* pDelegate)
: m_pModule(gif_module),
m_pDelegate(pDelegate),
- global_pal_num(0),
+ global_pal_exp(0),
img_row_offset(0),
img_row_avail_size(0),
avail_in(0),
diff --git a/core/fxcodec/lgif/cgifcontext.h b/core/fxcodec/lgif/cgifcontext.h
index d85243711d..71cf2bc75e 100644
--- a/core/fxcodec/lgif/cgifcontext.h
+++ b/core/fxcodec/lgif/cgifcontext.h
@@ -40,7 +40,7 @@ class CGifContext : public CCodec_GifModule::Context {
UnownedPtr<CCodec_GifModule> m_pModule;
UnownedPtr<CCodec_GifModule::Delegate> m_pDelegate;
std::vector<GifPalette> m_GlobalPalette;
- int32_t global_pal_num;
+ uint8_t global_pal_exp;
uint32_t img_row_offset;
uint32_t img_row_avail_size;
uint32_t avail_in;
diff --git a/core/fxcodec/lgif/fx_gif.cpp b/core/fxcodec/lgif/fx_gif.cpp
index 18385c3bdd..ea78259420 100644
--- a/core/fxcodec/lgif/fx_gif.cpp
+++ b/core/fxcodec/lgif/fx_gif.cpp
@@ -147,6 +147,7 @@ GifDecodeStatus gif_decode_image_info(CGifContext* context) {
}
GifLF* gif_img_info_lf_ptr = (GifLF*)&gif_img_info_ptr->local_flag;
if (gif_img_info_lf_ptr->local_pal) {
+ gif_image->local_pallette_exp = gif_img_info_lf_ptr->pal_bits;
int32_t loc_pal_size = (2 << gif_img_info_lf_ptr->pal_bits) * 3;
uint8_t* loc_pal_ptr = nullptr;
if (!gif_read_data(context, &loc_pal_ptr, loc_pal_size)) {
@@ -162,7 +163,7 @@ GifDecodeStatus gif_decode_image_info(CGifContext* context) {
context->skip_size = skip_size_org;
return GifDecodeStatus::Unfinished;
}
- gif_image->image_code_size = *code_size_ptr;
+ gif_image->image_code_exp = *code_size_ptr;
context->RecordCurrentPosition(&gif_image->image_data_pos);
gif_image->image_data_pos += context->skip_size;
gif_image->m_ImageGCE = nullptr;
@@ -214,10 +215,13 @@ CGifLZWDecoder::CGifLZWDecoder(char* error_ptr)
CGifLZWDecoder::~CGifLZWDecoder() {}
-void CGifLZWDecoder::InitTable(uint8_t code_len) {
- code_size = code_len;
- ASSERT(code_size < 13);
- code_clear = 1 << code_size;
+void CGifLZWDecoder::InitTable(uint8_t color_exp, uint8_t code_exp) {
+ // TODO(rharrison): Refactor all of this, so that initializing the table with
+ // bad values will kill the decompress.
+ ASSERT(code_exp <= GIF_MAX_LZW_EXP);
+ code_color_end = std::min(2 << color_exp, 1 << code_exp);
+ code_size = code_exp;
+ code_clear = 1 << code_exp;
code_end = code_clear + 1;
bits_left = 0;
code_store = 0;
@@ -247,6 +251,9 @@ bool CGifLZWDecoder::DecodeString(uint16_t code) {
stack[GIF_MAX_LZW_CODE - 1 - stack_size++] = code_table[code].suffix;
code = code_table[code].prefix;
}
+ if (code >= code_color_end)
+ return false;
+
stack[GIF_MAX_LZW_CODE - 1 - stack_size++] = static_cast<uint8_t>(code);
code_first = static_cast<uint8_t>(code);
return true;
@@ -282,7 +289,7 @@ GifDecodeStatus CGifLZWDecoder::Decode(uint8_t* des_buf, uint32_t* des_size) {
}
ASSERT(err_msg_ptr);
while (i <= *des_size && (avail_in > 0 || bits_left >= code_size_cur)) {
- if (code_size_cur > 12) {
+ if (code_size_cur > GIF_MAX_LZW_EXP) {
strncpy(err_msg_ptr, "Code Length Out Of Range", GIF_MAX_ERROR_SIZE - 1);
return GifDecodeStatus::Error;
}
@@ -383,9 +390,9 @@ GifDecodeStatus gif_read_header(CGifContext* context) {
return GifDecodeStatus::Unfinished;
}
if (reinterpret_cast<GifGF*>(&gif_lsd_ptr->global_flag)->global_pal) {
- context->global_pal_num =
- 2 << reinterpret_cast<GifGF*>(&gif_lsd_ptr->global_flag)->pal_bits;
- int32_t global_pal_size = context->global_pal_num * 3;
+ context->global_pal_exp =
+ reinterpret_cast<GifGF*>(&gif_lsd_ptr->global_flag)->pal_bits;
+ int32_t global_pal_size = (2 << context->global_pal_exp) * 3;
uint8_t* global_pal_ptr = nullptr;
if (!gif_read_data(context, &global_pal_ptr, global_pal_size)) {
context->skip_size = skip_size_org;
@@ -558,7 +565,7 @@ GifDecodeStatus gif_load_frame(CGifContext* context, int32_t frame_num) {
return GifDecodeStatus::Error;
}
}
- if (gif_image_ptr->image_code_size >= 13) {
+ if (gif_image_ptr->image_code_exp > GIF_MAX_LZW_EXP) {
gif_image_ptr->m_ImageRowBuf.clear();
context->AddError("Error Invalid Code Size");
return GifDecodeStatus::Error;
@@ -566,7 +573,10 @@ GifDecodeStatus gif_load_frame(CGifContext* context, int32_t frame_num) {
if (!context->m_ImgDecoder.get())
context->m_ImgDecoder =
pdfium::MakeUnique<CGifLZWDecoder>(context->m_szLastError);
- context->m_ImgDecoder->InitTable(gif_image_ptr->image_code_size);
+ context->m_ImgDecoder->InitTable(!gif_image_ptr->m_LocalPalettes.empty()
+ ? gif_image_ptr->local_pallette_exp
+ : context->global_pal_exp,
+ gif_image_ptr->image_code_exp);
context->img_row_offset = 0;
context->img_row_avail_size = 0;
context->img_pass_num = 0;
diff --git a/core/fxcodec/lgif/fx_gif.h b/core/fxcodec/lgif/fx_gif.h
index fd95aba17a..bddb22b30c 100644
--- a/core/fxcodec/lgif/fx_gif.h
+++ b/core/fxcodec/lgif/fx_gif.h
@@ -21,6 +21,7 @@ class CGifContext;
#define GIF_BLOCK_CE 0xFE
#define GIF_BLOCK_AE 0xFF
#define GIF_BLOCK_TERMINAL 0x00
+#define GIF_MAX_LZW_EXP 12
#define GIF_MAX_LZW_CODE 4096
#define GIF_DATA_BLOCK 255
#define GIF_MAX_ERROR_SIZE 256
@@ -116,7 +117,8 @@ class GifImage {
std::vector<GifPalette> m_LocalPalettes;
std::vector<uint8_t> m_ImageRowBuf;
GifImageInfo m_ImageInfo;
- uint8_t image_code_size;
+ uint8_t local_pallette_exp;
+ uint8_t image_code_exp;
uint32_t image_data_pos;
int32_t image_row_num;
};
@@ -131,7 +133,7 @@ class CGifLZWDecoder {
explicit CGifLZWDecoder(char* error_ptr);
~CGifLZWDecoder();
- void InitTable(uint8_t code_len);
+ void InitTable(uint8_t color_exp, uint8_t code_exp);
GifDecodeStatus Decode(uint8_t* des_buf, uint32_t* des_size);
void Input(uint8_t* src_buf, uint32_t src_size);
uint32_t GetAvailInput();
@@ -143,6 +145,7 @@ class CGifLZWDecoder {
uint8_t code_size;
uint8_t code_size_cur;
+ uint16_t code_color_end;
uint16_t code_clear;
uint16_t code_end;
uint16_t code_next;