Fix signedness of height in BMP decoder
Change-Id: I8a17739538a9ecd63d713007550177579c0b72f0
Reviewed-on: https://pdfium-review.googlesource.com/6731
Commit-Queue: dsinclair <dsinclair@chromium.org>
Reviewed-by: dsinclair <dsinclair@chromium.org>
diff --git a/core/fxcodec/codec/ccodec_bmpmodule.cpp b/core/fxcodec/codec/ccodec_bmpmodule.cpp
index 3709196..1c81124 100644
--- a/core/fxcodec/codec/ccodec_bmpmodule.cpp
+++ b/core/fxcodec/codec/ccodec_bmpmodule.cpp
@@ -51,7 +51,7 @@
*width = ctx->m_Bmp.width;
*height = ctx->m_Bmp.height;
- *tb_flag = false;
+ *tb_flag = ctx->m_Bmp.imgTB_flag;
*components = ctx->m_Bmp.components;
*pal_num = ctx->m_Bmp.pal_num;
*pal_pp = ctx->m_Bmp.pal_ptr;
diff --git a/core/fxcodec/lbmp/fx_bmp.cpp b/core/fxcodec/lbmp/fx_bmp.cpp
index 62ae681..a4b97ef 100644
--- a/core/fxcodec/lbmp/fx_bmp.cpp
+++ b/core/fxcodec/lbmp/fx_bmp.cpp
@@ -43,6 +43,7 @@
out_row_bytes(0),
bitCounts(0),
color_used(0),
+ imgTB_flag(false),
pal_num(0),
pal_type(0),
pal_ptr(nullptr),
@@ -125,6 +126,7 @@
bitCounts = GetWord_LSBFirst(
reinterpret_cast<uint8_t*>(&bmp_core_header_ptr->bcBitCount));
compress_flag = BMP_RGB;
+ imgTB_flag = false;
} break;
case kBmpInfoHeaderSize: {
BmpInfoHeaderPtr bmp_info_header_ptr = nullptr;
@@ -133,7 +135,8 @@
return 2;
}
width = GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biWidth);
- height = GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biHeight);
+ int32_t signed_height =
+ GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biHeight);
bitCounts =
GetWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biBitCount);
compress_flag =
@@ -144,6 +147,16 @@
(uint8_t*)&bmp_info_header_ptr->biXPelsPerMeter);
dpi_y = (int32_t)GetDWord_LSBFirst(
(uint8_t*)&bmp_info_header_ptr->biYPelsPerMeter);
+ if (signed_height < 0) {
+ if (signed_height == std::numeric_limits<int>::min()) {
+ Error("Unsupported height");
+ NOTREACHED();
+ }
+ height = -signed_height;
+ imgTB_flag = true;
+ } else {
+ height = signed_height;
+ }
} break;
default: {
if (img_ifh_size >
@@ -155,7 +168,8 @@
}
uint16_t biPlanes;
width = GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biWidth);
- height = GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biHeight);
+ int32_t signed_height =
+ GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biHeight);
bitCounts =
GetWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biBitCount);
compress_flag =
@@ -167,6 +181,16 @@
(uint8_t*)&bmp_info_header_ptr->biXPelsPerMeter);
dpi_y = GetDWord_LSBFirst(
(uint8_t*)&bmp_info_header_ptr->biYPelsPerMeter);
+ if (signed_height < 0) {
+ if (signed_height == std::numeric_limits<int>::min()) {
+ Error("Unsupported height");
+ NOTREACHED();
+ }
+ height = -signed_height;
+ imgTB_flag = true;
+ } else {
+ height = signed_height;
+ }
if (compress_flag == BMP_RGB && biPlanes == 1 && color_used == 0)
break;
}
@@ -402,7 +426,8 @@
if (!ValidateColorIndex(byte))
return 0;
}
- ReadScanline(height - 1 - row_num++, out_row_buffer);
+ ReadScanline(imgTB_flag ? row_num++ : (height - 1 - row_num++),
+ out_row_buffer);
}
SaveDecodingStatus(BMP_D_STATUS_TAIL);
return 1;
@@ -430,7 +455,8 @@
Error("The Bmp File Is Corrupt");
NOTREACHED();
}
- ReadScanline(height - 1 - row_num++, out_row_buffer);
+ ReadScanline(imgTB_flag ? row_num++ : (height - 1 - row_num++),
+ out_row_buffer);
col_num = 0;
std::fill(out_row_buffer.begin(), out_row_buffer.end(), 0);
SaveDecodingStatus(BMP_D_STATUS_DATA);
@@ -438,7 +464,8 @@
}
case RLE_EOI: {
if (row_num < height) {
- ReadScanline(height - 1 - row_num++, out_row_buffer);
+ ReadScanline(imgTB_flag ? row_num++ : (height - 1 - row_num++),
+ out_row_buffer);
}
SaveDecodingStatus(BMP_D_STATUS_TAIL);
return 1;
@@ -457,7 +484,8 @@
}
while (row_num < bmp_row_num_next) {
std::fill(out_row_buffer.begin(), out_row_buffer.end(), 0);
- ReadScanline(height - 1 - row_num++, out_row_buffer);
+ ReadScanline(imgTB_flag ? row_num++ : (height - 1 - row_num++),
+ out_row_buffer);
}
} break;
default: {
@@ -528,7 +556,8 @@
Error("The Bmp File Is Corrupt");
NOTREACHED();
}
- ReadScanline(height - 1 - row_num++, out_row_buffer);
+ ReadScanline(imgTB_flag ? row_num++ : (height - 1 - row_num++),
+ out_row_buffer);
col_num = 0;
std::fill(out_row_buffer.begin(), out_row_buffer.end(), 0);
SaveDecodingStatus(BMP_D_STATUS_DATA);
@@ -536,7 +565,8 @@
}
case RLE_EOI: {
if (row_num < height) {
- ReadScanline(height - 1 - row_num++, out_row_buffer);
+ ReadScanline(imgTB_flag ? row_num++ : (height - 1 - row_num++),
+ out_row_buffer);
}
SaveDecodingStatus(BMP_D_STATUS_TAIL);
return 1;
@@ -555,7 +585,8 @@
}
while (row_num < bmp_row_num_next) {
std::fill(out_row_buffer.begin(), out_row_buffer.end(), 0);
- ReadScanline(height - 1 - row_num++, out_row_buffer);
+ ReadScanline(imgTB_flag ? row_num++ : (height - 1 - row_num++),
+ out_row_buffer);
}
} break;
default: {
diff --git a/core/fxcodec/lbmp/fx_bmp.h b/core/fxcodec/lbmp/fx_bmp.h
index bf5e94f..e304020 100644
--- a/core/fxcodec/lbmp/fx_bmp.h
+++ b/core/fxcodec/lbmp/fx_bmp.h
@@ -95,6 +95,7 @@
size_t out_row_bytes;
uint16_t bitCounts;
uint32_t color_used;
+ bool imgTB_flag;
int32_t pal_num;
int32_t pal_type;
uint32_t* pal_ptr;