From e2df5b7305df66efbd81232d911615af60624ae3 Mon Sep 17 00:00:00 2001 From: Ryan Harrison Date: Tue, 26 Sep 2017 15:39:10 -0400 Subject: Move LZW decoder out of fx_gif CGifLZWDecoder has been moved out into its own file, name changed to CFX_LZWDecoder, member variable names updated, creation pattern changed, and unit tests added. Wrt the creation pattern, there is no longer a constructor and 2 initialization methods that need to be called. Instead all of the initialization is done as part of the constructor. A wrapper has been added for generating a std::unique_ptr, so that params can be validated. BUG=pdfium:900,pdfium:901,pdfium:903,pdfium:904 Change-Id: Idcbe773f7fb18b08e64d5a89bfd87d4801332c53 Reviewed-on: https://pdfium-review.googlesource.com/14814 Reviewed-by: Tom Sepez Commit-Queue: Ryan Harrison --- core/fxcodec/lgif/fx_gif.cpp | 181 ------------------------------------------- 1 file changed, 181 deletions(-) (limited to 'core/fxcodec/lgif/fx_gif.cpp') diff --git a/core/fxcodec/lgif/fx_gif.cpp b/core/fxcodec/lgif/fx_gif.cpp index 6e1c26ed12..db0744a6bb 100644 --- a/core/fxcodec/lgif/fx_gif.cpp +++ b/core/fxcodec/lgif/fx_gif.cpp @@ -26,184 +26,3 @@ static_assert(sizeof(GifLSD) == 7, "GifLSD should have a size of 7"); GifImage::GifImage() {} GifImage::~GifImage() {} - -void CGifLZWDecoder::Input(uint8_t* src_buf, uint32_t src_size) { - next_in = src_buf; - avail_in = src_size; -} - -uint32_t CGifLZWDecoder::GetAvailInput() { - return avail_in; -} - -CGifLZWDecoder::CGifLZWDecoder(char* error_ptr) - : code_size(0), - code_size_cur(0), - code_clear(0), - code_end(0), - code_next(0), - code_first(0), - stack_size(0), - code_old(0), - next_in(nullptr), - avail_in(0), - bits_left(0), - code_store(0), - err_msg_ptr(error_ptr) {} - -CGifLZWDecoder::~CGifLZWDecoder() {} - -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; - next_in = nullptr; - avail_in = 0; - stack_size = 0; - code_first = 0; - ClearTable(); -} - -void CGifLZWDecoder::ClearTable() { - code_size_cur = code_size + 1; - code_next = code_end + 1; - code_old = static_cast(-1); - memset(code_table, 0, sizeof(tag_Table) * GIF_MAX_LZW_CODE); - memset(stack, 0, GIF_MAX_LZW_CODE); - for (uint16_t i = 0; i < code_clear; i++) - code_table[i].suffix = static_cast(i); -} - -bool CGifLZWDecoder::DecodeString(uint16_t code) { - stack_size = 0; - while (code >= code_clear && code <= code_next) { - if (code == code_table[code].prefix || stack_size == GIF_MAX_LZW_CODE - 1) - return false; - - 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(code); - code_first = static_cast(code); - return true; -} - -void CGifLZWDecoder::AddCode(uint16_t prefix_code, uint8_t append_char) { - if (code_next == GIF_MAX_LZW_CODE) - return; - - code_table[code_next].prefix = prefix_code; - code_table[code_next].suffix = append_char; - if (++code_next < GIF_MAX_LZW_CODE) { - if (code_next >> code_size_cur) - code_size_cur++; - } -} - -GifDecodeStatus CGifLZWDecoder::Decode(uint8_t* des_buf, uint32_t* des_size) { - if (*des_size == 0) - return GifDecodeStatus::InsufficientDestSize; - - uint32_t i = 0; - if (stack_size != 0) { - if (*des_size < stack_size) { - memcpy(des_buf, &stack[GIF_MAX_LZW_CODE - stack_size], *des_size); - stack_size -= static_cast(*des_size); - return GifDecodeStatus::InsufficientDestSize; - } - memcpy(des_buf, &stack[GIF_MAX_LZW_CODE - stack_size], stack_size); - des_buf += stack_size; - i += stack_size; - stack_size = 0; - } - ASSERT(err_msg_ptr); - while (i <= *des_size && (avail_in > 0 || bits_left >= code_size_cur)) { - 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; - } - if (avail_in > 0) { - if (bits_left > 31) { - strncpy(err_msg_ptr, "Decode Error", GIF_MAX_ERROR_SIZE - 1); - return GifDecodeStatus::Error; - } - pdfium::base::CheckedNumeric safe_code = *next_in++; - safe_code <<= bits_left; - safe_code |= code_store; - if (!safe_code.IsValid()) { - strncpy(err_msg_ptr, "Code Store Out Of Range", GIF_MAX_ERROR_SIZE - 1); - return GifDecodeStatus::Error; - } - code_store = safe_code.ValueOrDie(); - --avail_in; - bits_left += 8; - } - while (bits_left >= code_size_cur) { - uint16_t code = - static_cast(code_store) & ((1 << code_size_cur) - 1); - code_store >>= code_size_cur; - bits_left -= code_size_cur; - if (code == code_clear) { - ClearTable(); - continue; - } - if (code == code_end) { - *des_size = i; - return GifDecodeStatus::Success; - } - if (code_old != static_cast(-1)) { - if (code_next < GIF_MAX_LZW_CODE) { - if (code == code_next) { - AddCode(code_old, code_first); - if (!DecodeString(code)) { - strncpy(err_msg_ptr, "String Decoding Error", - GIF_MAX_ERROR_SIZE - 1); - return GifDecodeStatus::Error; - } - } else if (code > code_next) { - strncpy(err_msg_ptr, "Decode Error, Out Of Range", - GIF_MAX_ERROR_SIZE - 1); - return GifDecodeStatus::Error; - } else { - if (!DecodeString(code)) { - strncpy(err_msg_ptr, "String Decoding Error", - GIF_MAX_ERROR_SIZE - 1); - return GifDecodeStatus::Error; - } - uint8_t append_char = stack[GIF_MAX_LZW_CODE - stack_size]; - AddCode(code_old, append_char); - } - } - } else { - if (!DecodeString(code)) { - strncpy(err_msg_ptr, "String Decoding Error", GIF_MAX_ERROR_SIZE - 1); - return GifDecodeStatus::Error; - } - } - code_old = code; - if (i + stack_size > *des_size) { - memcpy(des_buf, &stack[GIF_MAX_LZW_CODE - stack_size], *des_size - i); - stack_size -= static_cast(*des_size - i); - return GifDecodeStatus::InsufficientDestSize; - } - memcpy(des_buf, &stack[GIF_MAX_LZW_CODE - stack_size], stack_size); - des_buf += stack_size; - i += stack_size; - stack_size = 0; - } - } - if (avail_in == 0) { - *des_size = i; - return GifDecodeStatus::Unfinished; - } - return GifDecodeStatus::Error; -} -- cgit v1.2.3