summaryrefslogtreecommitdiff
path: root/core/fxcodec/lgif/fx_gif.cpp
diff options
context:
space:
mode:
authorRyan Harrison <rharrison@chromium.org>2017-09-22 10:53:34 -0400
committerChromium commit bot <commit-bot@chromium.org>2017-09-22 15:03:06 +0000
commit73bed4ef57444a2ea066d532a8a82b230fd206d9 (patch)
tree05b9a588ea3daa1e4ef997d47c9d9a0d200019ff /core/fxcodec/lgif/fx_gif.cpp
parent0150a5455829ede62017bc24ed9c4bcdc1cafef2 (diff)
downloadpdfium-73bed4ef57444a2ea066d532a8a82b230fd206d9.tar.xz
Fix crash when rendering invalid GIF
The core fix in this CL is a change to how LWZ decompression works, so that when the min code table size and the color palette size are different, color codes after the end of the defined color palette are considered errors. This CL also introduces a bunch of tweaks to the call return path, since there were multiple locations where the GIF decode failing status was being dropped on the floor, so the end widget would have a bitmap with the default colour in it, instead of nothing. BUG=chromium:616671 Change-Id: Id6f40d552dc24650c91e9903f710ff2fa63bc774 Reviewed-on: https://pdfium-review.googlesource.com/14630 Commit-Queue: Ryan Harrison <rharrison@chromium.org> Reviewed-by: dsinclair <dsinclair@chromium.org>
Diffstat (limited to 'core/fxcodec/lgif/fx_gif.cpp')
-rw-r--r--core/fxcodec/lgif/fx_gif.cpp32
1 files changed, 21 insertions, 11 deletions
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;