summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLei Zhang <thestig@chromium.org>2017-03-13 17:13:51 -0700
committerChromium commit bot <commit-bot@chromium.org>2017-03-15 01:37:08 +0000
commit6e0b25b9456871be5d2e6dcb418cc6daac04ff7a (patch)
treebc9fe4bc17c865004c10eb8399693dede3e14a09
parent4d67473d6ce55ad6361dae84b00283445f148f37 (diff)
downloadpdfium-6e0b25b9456871be5d2e6dcb418cc6daac04ff7a.tar.xz
Fix an integer underflow in the BMP decoder.
Make RLE error handling more consistent. BUG=chromium:700576 Change-Id: I37290ede666ba3e0a697d9d6eb209f869a07293d Reviewed-on: https://pdfium-review.googlesource.com/2990 Reviewed-by: Tom Sepez <tsepez@chromium.org> Commit-Queue: Lei Zhang <thestig@chromium.org>
-rw-r--r--core/fxcodec/lbmp/fx_bmp.cpp69
1 files changed, 41 insertions, 28 deletions
diff --git a/core/fxcodec/lbmp/fx_bmp.cpp b/core/fxcodec/lbmp/fx_bmp.cpp
index c31886dcfd..73a62d4192 100644
--- a/core/fxcodec/lbmp/fx_bmp.cpp
+++ b/core/fxcodec/lbmp/fx_bmp.cpp
@@ -25,6 +25,12 @@ void SetDWord_LSBFirst(uint8_t* p, uint32_t v) {
p[2] = (uint8_t)(v >> 16);
p[3] = (uint8_t)(v >> 24);
}
+
+uint8_t HalfRoundUp(uint8_t value) {
+ uint16_t value16 = value;
+ return static_cast<uint8_t>((value16 + 1) / 2);
+}
+
} // namespace
uint16_t GetWord_LSBFirst(uint8_t* p) {
@@ -52,9 +58,7 @@ void bmp_destroy_decompress(bmp_decompress_struct_pp bmp_ptr_ptr) {
bmp_decompress_struct_p bmp_ptr = *bmp_ptr_ptr;
*bmp_ptr_ptr = nullptr;
- if (bmp_ptr->out_row_buffer) {
- FX_Free(bmp_ptr->out_row_buffer);
- }
+ FX_Free(bmp_ptr->out_row_buffer);
FX_Free(bmp_ptr->pal_ptr);
FX_Free(bmp_ptr->bmp_header_ptr);
FX_Free(bmp_ptr);
@@ -221,6 +225,7 @@ int32_t bmp_read_header(bmp_decompress_struct_p bmp_ptr) {
break;
}
FX_Free(bmp_ptr->out_row_buffer);
+ bmp_ptr->out_row_buffer = nullptr;
if (bmp_ptr->out_row_bytes <= 0) {
bmp_error(bmp_ptr, "The Bmp File Is Corrupt");
@@ -462,8 +467,9 @@ int32_t bmp_decode_rle8(bmp_decompress_struct_p bmp_ptr) {
}
} break;
default: {
- if ((int32_t)(*first_byte_ptr) >
- bmp_ptr->src_row_bytes - bmp_ptr->col_num) {
+ int32_t avail_size = bmp_ptr->out_row_bytes - bmp_ptr->col_num;
+ if (!avail_size ||
+ static_cast<int32_t>(*first_byte_ptr) > avail_size) {
bmp_error(bmp_ptr, "The Bmp File Is Corrupt");
return 0;
}
@@ -480,15 +486,15 @@ int32_t bmp_decode_rle8(bmp_decompress_struct_p bmp_ptr) {
}
} break;
default: {
+ int32_t avail_size = bmp_ptr->out_row_bytes - bmp_ptr->col_num;
+ if (!avail_size || static_cast<int32_t>(*first_byte_ptr) > avail_size) {
+ bmp_error(bmp_ptr, "The Bmp File Is Corrupt");
+ return 0;
+ }
if (!bmp_read_data(bmp_ptr, &second_byte_ptr, 1)) {
bmp_ptr->skip_size = skip_size_org;
return 2;
}
- if ((int32_t)(*first_byte_ptr) >
- bmp_ptr->src_row_bytes - bmp_ptr->col_num) {
- bmp_error(bmp_ptr, "The Bmp File Is Corrupt");
- return 0;
- }
FXSYS_memset(bmp_ptr->out_row_buffer + bmp_ptr->col_num,
*second_byte_ptr, *first_byte_ptr);
bmp_ptr->col_num += (int32_t)(*first_byte_ptr);
@@ -498,6 +504,7 @@ int32_t bmp_decode_rle8(bmp_decompress_struct_p bmp_ptr) {
bmp_error(bmp_ptr, "Any Uncontrol Error");
return 0;
}
+
int32_t bmp_decode_rle4(bmp_decompress_struct_p bmp_ptr) {
uint8_t* first_byte_ptr = nullptr;
uint8_t* second_byte_ptr = nullptr;
@@ -564,14 +571,18 @@ int32_t bmp_decode_rle4(bmp_decompress_struct_p bmp_ptr) {
}
} break;
default: {
- uint8_t size = (uint8_t)(((uint16_t)(*first_byte_ptr) + 1) >> 1);
- if ((int32_t)*first_byte_ptr >=
- bmp_ptr->out_row_bytes - bmp_ptr->col_num) {
+ int32_t avail_size = bmp_ptr->out_row_bytes - bmp_ptr->col_num;
+ if (!avail_size) {
+ bmp_error(bmp_ptr, "The Bmp File Is Corrupt");
+ return 0;
+ }
+ uint8_t size = HalfRoundUp(*first_byte_ptr);
+ if (static_cast<int32_t>(*first_byte_ptr) > avail_size) {
if (size + (bmp_ptr->col_num >> 1) > bmp_ptr->src_row_bytes) {
bmp_error(bmp_ptr, "The Bmp File Is Corrupt");
return 0;
}
- *first_byte_ptr = bmp_ptr->out_row_bytes - bmp_ptr->col_num - 1;
+ *first_byte_ptr = avail_size - 1;
}
if (!bmp_read_data(bmp_ptr, &second_byte_ptr,
size & 1 ? size + 1 : size)) {
@@ -591,27 +602,28 @@ int32_t bmp_decode_rle4(bmp_decompress_struct_p bmp_ptr) {
}
} break;
default: {
- if (!bmp_read_data(bmp_ptr, &second_byte_ptr, 1)) {
- bmp_ptr->skip_size = skip_size_org;
- return 2;
+ int32_t avail_size = bmp_ptr->out_row_bytes - bmp_ptr->col_num;
+ if (!avail_size) {
+ bmp_error(bmp_ptr, "The Bmp File Is Corrupt");
+ return 0;
}
- if ((int32_t)*first_byte_ptr >
- bmp_ptr->out_row_bytes - bmp_ptr->col_num) {
- uint8_t size = (uint8_t)(((uint16_t)(*first_byte_ptr) + 1) >> 1);
+ if (static_cast<int32_t>(*first_byte_ptr) > avail_size) {
+ uint8_t size = HalfRoundUp(*first_byte_ptr);
if (size + (bmp_ptr->col_num >> 1) > bmp_ptr->src_row_bytes) {
bmp_error(bmp_ptr, "The Bmp File Is Corrupt");
return 0;
}
- *first_byte_ptr = bmp_ptr->out_row_bytes - bmp_ptr->col_num - 1;
+ *first_byte_ptr = avail_size - 1;
+ }
+ if (!bmp_read_data(bmp_ptr, &second_byte_ptr, 1)) {
+ bmp_ptr->skip_size = skip_size_org;
+ return 2;
}
for (uint8_t i = 0; i < *first_byte_ptr; i++) {
- if (i & 0x01) {
- *(bmp_ptr->out_row_buffer + bmp_ptr->col_num++) =
- (*second_byte_ptr & 0x0F);
- } else {
- *(bmp_ptr->out_row_buffer + bmp_ptr->col_num++) =
- ((*second_byte_ptr & 0xF0) >> 4);
- }
+ uint8_t second_byte = *second_byte_ptr;
+ second_byte =
+ i & 0x01 ? (second_byte & 0x0F) : (second_byte & 0xF0) >> 4;
+ *(bmp_ptr->out_row_buffer + bmp_ptr->col_num++) = second_byte;
}
}
}
@@ -619,6 +631,7 @@ int32_t bmp_decode_rle4(bmp_decompress_struct_p bmp_ptr) {
bmp_error(bmp_ptr, "Any Uncontrol Error");
return 0;
}
+
uint8_t* bmp_read_data(bmp_decompress_struct_p bmp_ptr,
uint8_t** des_buf_pp,
uint32_t data_size) {