Break apart CFX_BmpDecompressor::ReadHeader().
Split it into several smaller methods.
Change-Id: I10f518be006f6e19ad569be00cd1184468433f1e
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/56052
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fxcodec/bmp/cfx_bmpdecompressor.cpp b/core/fxcodec/bmp/cfx_bmpdecompressor.cpp
index 4bba1b4..32362da 100644
--- a/core/fxcodec/bmp/cfx_bmpdecompressor.cpp
+++ b/core/fxcodec/bmp/cfx_bmpdecompressor.cpp
@@ -72,218 +72,228 @@
}
bool CFX_BmpDecompressor::ReadHeader() {
- if (decode_status_ == DecodeStatus::kHeader) {
- BmpFileHeader bmp_header;
- if (!ReadData(reinterpret_cast<uint8_t*>(&bmp_header),
- sizeof(BmpFileHeader))) {
- return false;
- }
+ if (decode_status_ == DecodeStatus::kHeader && !ReadBmpHeader())
+ return false;
- bmp_header.bfType =
- FXWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&bmp_header.bfType));
- bmp_header.bfOffBits =
- FXDWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&bmp_header.bfOffBits));
- data_size_ =
- FXDWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&bmp_header.bfSize));
- if (bmp_header.bfType != kBmpSignature) {
- Error();
- NOTREACHED();
- }
-
- if (!ReadData(reinterpret_cast<uint8_t*>(&img_ifh_size_),
- sizeof(img_ifh_size_))) {
- return false;
- }
-
- img_ifh_size_ =
- FXDWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&img_ifh_size_));
- pal_type_ = 0;
- switch (img_ifh_size_) {
- case kBmpCoreHeaderSize: {
- pal_type_ = 1;
- BmpCoreHeader bmp_core_header;
- if (!ReadData(reinterpret_cast<uint8_t*>(&bmp_core_header),
- sizeof(BmpCoreHeader))) {
- return false;
- }
-
- width_ = FXWORD_GET_LSBFIRST(
- reinterpret_cast<uint8_t*>(&bmp_core_header.bcWidth));
- height_ = FXWORD_GET_LSBFIRST(
- reinterpret_cast<uint8_t*>(&bmp_core_header.bcHeight));
- bit_counts_ = FXWORD_GET_LSBFIRST(
- reinterpret_cast<uint8_t*>(&bmp_core_header.bcBitCount));
- compress_flag_ = kBmpRgb;
- img_tb_flag_ = false;
- break;
- }
- case kBmpInfoHeaderSize: {
- BmpInfoHeader bmp_info_header;
- if (!ReadData(reinterpret_cast<uint8_t*>(&bmp_info_header),
- sizeof(BmpInfoHeader))) {
- return false;
- }
-
- width_ = FXDWORD_GET_LSBFIRST(
- reinterpret_cast<uint8_t*>(&bmp_info_header.biWidth));
- int32_t signed_height = FXDWORD_GET_LSBFIRST(
- reinterpret_cast<uint8_t*>(&bmp_info_header.biHeight));
- bit_counts_ = FXWORD_GET_LSBFIRST(
- reinterpret_cast<uint8_t*>(&bmp_info_header.biBitCount));
- compress_flag_ = FXDWORD_GET_LSBFIRST(
- reinterpret_cast<uint8_t*>(&bmp_info_header.biCompression));
- color_used_ = FXDWORD_GET_LSBFIRST(
- reinterpret_cast<uint8_t*>(&bmp_info_header.biClrUsed));
- dpi_x_ = static_cast<int32_t>(FXDWORD_GET_LSBFIRST(
- reinterpret_cast<uint8_t*>(&bmp_info_header.biXPelsPerMeter)));
- dpi_y_ = static_cast<int32_t>(FXDWORD_GET_LSBFIRST(
- reinterpret_cast<uint8_t*>(&bmp_info_header.biYPelsPerMeter)));
- SetHeight(signed_height);
- break;
- }
- default: {
- if (img_ifh_size_ <= sizeof(BmpInfoHeader)) {
- Error();
- NOTREACHED();
- }
-
- FX_SAFE_SIZE_T new_pos = input_buffer_->GetPosition();
- BmpInfoHeader bmp_info_header;
- if (!ReadData(reinterpret_cast<uint8_t*>(&bmp_info_header),
- sizeof(bmp_info_header))) {
- return false;
- }
-
- new_pos += img_ifh_size_;
- if (!new_pos.IsValid()) {
- Error();
- NOTREACHED();
- }
-
- if (!input_buffer_->Seek(new_pos.ValueOrDie()))
- return false;
-
- uint16_t bi_planes;
- width_ = FXDWORD_GET_LSBFIRST(
- reinterpret_cast<uint8_t*>(&bmp_info_header.biWidth));
- int32_t signed_height = FXDWORD_GET_LSBFIRST(
- reinterpret_cast<uint8_t*>(&bmp_info_header.biHeight));
- bit_counts_ = FXWORD_GET_LSBFIRST(
- reinterpret_cast<uint8_t*>(&bmp_info_header.biBitCount));
- compress_flag_ = FXDWORD_GET_LSBFIRST(
- reinterpret_cast<uint8_t*>(&bmp_info_header.biCompression));
- color_used_ = FXDWORD_GET_LSBFIRST(
- reinterpret_cast<uint8_t*>(&bmp_info_header.biClrUsed));
- bi_planes = FXWORD_GET_LSBFIRST(
- reinterpret_cast<uint8_t*>(&bmp_info_header.biPlanes));
- dpi_x_ = FXDWORD_GET_LSBFIRST(
- reinterpret_cast<uint8_t*>(&bmp_info_header.biXPelsPerMeter));
- dpi_y_ = FXDWORD_GET_LSBFIRST(
- reinterpret_cast<uint8_t*>(&bmp_info_header.biYPelsPerMeter));
- SetHeight(signed_height);
- if (compress_flag_ != kBmpRgb || bi_planes != 1 || color_used_ != 0) {
- Error();
- NOTREACHED();
- }
- break;
- }
- }
-
- if (width_ > kBmpMaxImageDimension || height_ > kBmpMaxImageDimension ||
- compress_flag_ > kBmpBitfields) {
- Error();
- NOTREACHED();
- }
-
- switch (bit_counts_) {
- case 1:
- case 4:
- case 8:
- case 16:
- case 24: {
- if (color_used_ > 1U << bit_counts_) {
- Error();
- NOTREACHED();
- }
- break;
- }
- case 32:
- break;
- default:
- Error();
- NOTREACHED();
- break;
- }
- FX_SAFE_UINT32 stride = CalculatePitch32(bit_counts_, width_);
- if (!stride.IsValid()) {
- Error();
- NOTREACHED();
- }
-
- src_row_bytes_ = stride.ValueOrDie();
- switch (bit_counts_) {
- case 1:
- case 4:
- case 8:
- stride = CalculatePitch32(8, width_);
- if (!stride.IsValid()) {
- Error();
- NOTREACHED();
- }
- out_row_bytes_ = stride.ValueOrDie();
- components_ = 1;
- break;
- case 16:
- case 24:
- stride = CalculatePitch32(24, width_);
- if (!stride.IsValid()) {
- Error();
- NOTREACHED();
- }
- out_row_bytes_ = stride.ValueOrDie();
- components_ = 3;
- break;
- case 32:
- out_row_bytes_ = src_row_bytes_;
- components_ = 4;
- break;
- }
- out_row_buffer_.clear();
-
- if (out_row_bytes_ <= 0) {
- Error();
- NOTREACHED();
- }
-
- out_row_buffer_.resize(out_row_bytes_);
- SaveDecodingStatus(DecodeStatus::kPal);
- }
if (decode_status_ != DecodeStatus::kPal)
return true;
- if (compress_flag_ == kBmpBitfields) {
- if (bit_counts_ != 16 && bit_counts_ != 32) {
- Error();
- NOTREACHED();
- }
+ if (compress_flag_ == kBmpBitfields)
+ return ReadBmpBitfields();
- uint32_t masks[3];
- if (!ReadData(reinterpret_cast<uint8_t*>(masks), sizeof(masks)))
+ return ReadBmpPalette();
+}
+
+bool CFX_BmpDecompressor::ReadBmpHeader() {
+ BmpFileHeader bmp_header;
+ if (!ReadData(reinterpret_cast<uint8_t*>(&bmp_header),
+ sizeof(BmpFileHeader))) {
+ return false;
+ }
+
+ bmp_header.bfType =
+ FXWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&bmp_header.bfType));
+ bmp_header.bfOffBits =
+ FXDWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&bmp_header.bfOffBits));
+ data_size_ =
+ FXDWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&bmp_header.bfSize));
+ if (bmp_header.bfType != kBmpSignature) {
+ Error();
+ NOTREACHED();
+ }
+
+ if (!ReadData(reinterpret_cast<uint8_t*>(&img_ifh_size_),
+ sizeof(img_ifh_size_))) {
+ return false;
+ }
+
+ img_ifh_size_ =
+ FXDWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&img_ifh_size_));
+ pal_type_ = 0;
+ if (!ReadBmpHeaderIfh())
+ return false;
+
+ if (!ReadBmpHeaderDimensions()) {
+ Error();
+ NOTREACHED();
+ }
+ return true;
+}
+
+bool CFX_BmpDecompressor::ReadBmpHeaderIfh() {
+ if (img_ifh_size_ == kBmpCoreHeaderSize) {
+ pal_type_ = 1;
+ BmpCoreHeader bmp_core_header;
+ if (!ReadData(reinterpret_cast<uint8_t*>(&bmp_core_header),
+ sizeof(BmpCoreHeader))) {
return false;
-
- mask_red_ = FXDWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&masks[0]));
- mask_green_ = FXDWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&masks[1]));
- mask_blue_ = FXDWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&masks[2]));
- if (mask_red_ & mask_green_ || mask_red_ & mask_blue_ ||
- mask_green_ & mask_blue_) {
- Error();
- NOTREACHED();
}
- header_offset_ = std::max(header_offset_, 26 + img_ifh_size_);
- SaveDecodingStatus(DecodeStatus::kDataPre);
+
+ width_ = FXWORD_GET_LSBFIRST(
+ reinterpret_cast<uint8_t*>(&bmp_core_header.bcWidth));
+ height_ = FXWORD_GET_LSBFIRST(
+ reinterpret_cast<uint8_t*>(&bmp_core_header.bcHeight));
+ bit_counts_ = FXWORD_GET_LSBFIRST(
+ reinterpret_cast<uint8_t*>(&bmp_core_header.bcBitCount));
+ compress_flag_ = kBmpRgb;
+ img_tb_flag_ = false;
return true;
}
+ if (img_ifh_size_ == kBmpInfoHeaderSize) {
+ BmpInfoHeader bmp_info_header;
+ if (!ReadData(reinterpret_cast<uint8_t*>(&bmp_info_header),
+ sizeof(BmpInfoHeader))) {
+ return false;
+ }
+
+ width_ = FXDWORD_GET_LSBFIRST(
+ reinterpret_cast<uint8_t*>(&bmp_info_header.biWidth));
+ int32_t signed_height = FXDWORD_GET_LSBFIRST(
+ reinterpret_cast<uint8_t*>(&bmp_info_header.biHeight));
+ bit_counts_ = FXWORD_GET_LSBFIRST(
+ reinterpret_cast<uint8_t*>(&bmp_info_header.biBitCount));
+ compress_flag_ = FXDWORD_GET_LSBFIRST(
+ reinterpret_cast<uint8_t*>(&bmp_info_header.biCompression));
+ color_used_ = FXDWORD_GET_LSBFIRST(
+ reinterpret_cast<uint8_t*>(&bmp_info_header.biClrUsed));
+ dpi_x_ = static_cast<int32_t>(FXDWORD_GET_LSBFIRST(
+ reinterpret_cast<uint8_t*>(&bmp_info_header.biXPelsPerMeter)));
+ dpi_y_ = static_cast<int32_t>(FXDWORD_GET_LSBFIRST(
+ reinterpret_cast<uint8_t*>(&bmp_info_header.biYPelsPerMeter)));
+ SetHeight(signed_height);
+ return true;
+ }
+
+ if (img_ifh_size_ <= sizeof(BmpInfoHeader)) {
+ Error();
+ NOTREACHED();
+ }
+
+ FX_SAFE_SIZE_T new_pos = input_buffer_->GetPosition();
+ BmpInfoHeader bmp_info_header;
+ if (!ReadData(reinterpret_cast<uint8_t*>(&bmp_info_header),
+ sizeof(bmp_info_header))) {
+ return false;
+ }
+
+ new_pos += img_ifh_size_;
+ if (!new_pos.IsValid()) {
+ Error();
+ NOTREACHED();
+ }
+
+ if (!input_buffer_->Seek(new_pos.ValueOrDie()))
+ return false;
+
+ uint16_t bi_planes;
+ width_ = FXDWORD_GET_LSBFIRST(
+ reinterpret_cast<uint8_t*>(&bmp_info_header.biWidth));
+ int32_t signed_height = FXDWORD_GET_LSBFIRST(
+ reinterpret_cast<uint8_t*>(&bmp_info_header.biHeight));
+ bit_counts_ = FXWORD_GET_LSBFIRST(
+ reinterpret_cast<uint8_t*>(&bmp_info_header.biBitCount));
+ compress_flag_ = FXDWORD_GET_LSBFIRST(
+ reinterpret_cast<uint8_t*>(&bmp_info_header.biCompression));
+ color_used_ = FXDWORD_GET_LSBFIRST(
+ reinterpret_cast<uint8_t*>(&bmp_info_header.biClrUsed));
+ bi_planes = FXWORD_GET_LSBFIRST(
+ reinterpret_cast<uint8_t*>(&bmp_info_header.biPlanes));
+ dpi_x_ = FXDWORD_GET_LSBFIRST(
+ reinterpret_cast<uint8_t*>(&bmp_info_header.biXPelsPerMeter));
+ dpi_y_ = FXDWORD_GET_LSBFIRST(
+ reinterpret_cast<uint8_t*>(&bmp_info_header.biYPelsPerMeter));
+ SetHeight(signed_height);
+ if (compress_flag_ != kBmpRgb || bi_planes != 1 || color_used_ != 0) {
+ Error();
+ NOTREACHED();
+ }
+ return true;
+}
+
+bool CFX_BmpDecompressor::ReadBmpHeaderDimensions() {
+ if (width_ > kBmpMaxImageDimension || height_ > kBmpMaxImageDimension ||
+ compress_flag_ > kBmpBitfields) {
+ return false;
+ }
+
+ switch (bit_counts_) {
+ case 1:
+ case 4:
+ case 8:
+ case 16:
+ case 24: {
+ if (color_used_ > 1U << bit_counts_)
+ return false;
+ break;
+ }
+ case 32:
+ break;
+ default:
+ return false;
+ }
+ FX_SAFE_UINT32 stride = CalculatePitch32(bit_counts_, width_);
+ if (!stride.IsValid())
+ return false;
+
+ src_row_bytes_ = stride.ValueOrDie();
+ switch (bit_counts_) {
+ case 1:
+ case 4:
+ case 8:
+ stride = CalculatePitch32(8, width_);
+ if (!stride.IsValid())
+ return false;
+ out_row_bytes_ = stride.ValueOrDie();
+ components_ = 1;
+ break;
+ case 16:
+ case 24:
+ stride = CalculatePitch32(24, width_);
+ if (!stride.IsValid())
+ return false;
+ out_row_bytes_ = stride.ValueOrDie();
+ components_ = 3;
+ break;
+ case 32:
+ out_row_bytes_ = src_row_bytes_;
+ components_ = 4;
+ break;
+ }
+ out_row_buffer_.clear();
+
+ if (out_row_bytes_ <= 0)
+ return false;
+
+ out_row_buffer_.resize(out_row_bytes_);
+ SaveDecodingStatus(DecodeStatus::kPal);
+ return true;
+}
+
+bool CFX_BmpDecompressor::ReadBmpBitfields() {
+ if (bit_counts_ != 16 && bit_counts_ != 32) {
+ Error();
+ NOTREACHED();
+ }
+
+ uint32_t masks[3];
+ if (!ReadData(reinterpret_cast<uint8_t*>(masks), sizeof(masks)))
+ return false;
+
+ mask_red_ = FXDWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&masks[0]));
+ mask_green_ = FXDWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&masks[1]));
+ mask_blue_ = FXDWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&masks[2]));
+ if (mask_red_ & mask_green_ || mask_red_ & mask_blue_ ||
+ mask_green_ & mask_blue_) {
+ Error();
+ NOTREACHED();
+ }
+ header_offset_ = std::max(header_offset_, 26 + img_ifh_size_);
+ SaveDecodingStatus(DecodeStatus::kDataPre);
+ return true;
+}
+
+bool CFX_BmpDecompressor::ReadBmpPalette() {
if (bit_counts_ == 16) {
mask_red_ = 0x7C00;
mask_green_ = 0x03E0;
@@ -297,9 +307,8 @@
uint32_t src_pal_size = pal_num_ * (pal_type_ ? 3 : 4);
std::vector<uint8_t> src_pal(src_pal_size);
uint8_t* src_pal_data = src_pal.data();
- if (!ReadData(src_pal_data, src_pal_size)) {
+ if (!ReadData(src_pal_data, src_pal_size))
return false;
- }
palette_.resize(pal_num_);
int32_t src_pal_index = 0;
diff --git a/core/fxcodec/bmp/cfx_bmpdecompressor.h b/core/fxcodec/bmp/cfx_bmpdecompressor.h
index 223ab63..eb987b2 100644
--- a/core/fxcodec/bmp/cfx_bmpdecompressor.h
+++ b/core/fxcodec/bmp/cfx_bmpdecompressor.h
@@ -48,6 +48,11 @@
kTail,
};
+ bool ReadBmpHeader();
+ bool ReadBmpHeaderIfh();
+ bool ReadBmpHeaderDimensions();
+ bool ReadBmpBitfields();
+ bool ReadBmpPalette();
bool GetDataPosition(uint32_t cur_pos);
void ReadNextScanline();
int32_t DecodeRGB();