Gif: Detect string decoding errors
This CL adds some checks to make sure the DecodeString method does not go out
out control:
If code is equal to code_table[code].prefix, it will try to loop forever.
Even if that's not the case, avoid reading a negative position from the stack.
Bug: chromium:722672
Change-Id: I638f91542ba21f3a9915198fef853cc3cf94f4f1
Reviewed-on: https://pdfium-review.googlesource.com/5513
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Nicolás Peña <npm@chromium.org>
diff --git a/core/fxcodec/lgif/fx_gif.cpp b/core/fxcodec/lgif/fx_gif.cpp
index 0b56f3a..5e257cc 100644
--- a/core/fxcodec/lgif/fx_gif.cpp
+++ b/core/fxcodec/lgif/fx_gif.cpp
@@ -242,14 +242,18 @@
code_table[i].suffix = static_cast<uint8_t>(i);
}
-void CGifLZWDecoder::DecodeString(uint16_t code) {
+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;
}
stack[GIF_MAX_LZW_CODE - 1 - stack_size++] = static_cast<uint8_t>(code);
code_first = static_cast<uint8_t>(code);
+ return true;
}
void CGifLZWDecoder::AddCode(uint16_t prefix_code, uint8_t append_char) {
@@ -319,19 +323,30 @@
if (code_next < GIF_MAX_LZW_CODE) {
if (code == code_next) {
AddCode(code_old, code_first);
- DecodeString(code);
+ 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 {
- DecodeString(code);
+ 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 {
- DecodeString(code);
+ 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) {
diff --git a/core/fxcodec/lgif/fx_gif.h b/core/fxcodec/lgif/fx_gif.h
index 5df1f81..d7cd5d8 100644
--- a/core/fxcodec/lgif/fx_gif.h
+++ b/core/fxcodec/lgif/fx_gif.h
@@ -142,7 +142,7 @@
private:
void ClearTable();
void AddCode(uint16_t prefix_code, uint8_t append_char);
- void DecodeString(uint16_t code);
+ bool DecodeString(uint16_t code);
uint8_t code_size;
uint8_t code_size_cur;