Only validate indexes for paletted BMPs
Validates palette indexes only for BMP images with indexed color depths
(1, 4, or 8 bits); 24-bit and 32-bit images use direct color.
Fixed: pdfium:1168
Change-Id: I4f2a30f8ad5e32ef07e82f18e8323ee92bd78481
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/98670
Commit-Queue: K. Moon <kmoon@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fxcodec/bmp/cfx_bmpdecompressor.cpp b/core/fxcodec/bmp/cfx_bmpdecompressor.cpp
index bc2b2e8..6af1ecf 100644
--- a/core/fxcodec/bmp/cfx_bmpdecompressor.cpp
+++ b/core/fxcodec/bmp/cfx_bmpdecompressor.cpp
@@ -377,16 +377,31 @@
SaveDecodingStatus(DecodeStatus::kData);
switch (bit_counts_) {
case 1: {
- for (uint32_t col = 0; col < width_; ++col)
- out_row_buffer_[idx++] =
+ for (uint32_t col = 0; col < width_; ++col) {
+ uint8_t index =
dest_buf[col >> 3] & (0x80 >> (col % 8)) ? 0x01 : 0x00;
+ if (!ValidateColorIndex(index))
+ return BmpDecoder::Status::kFail;
+ out_row_buffer_[idx++] = index;
+ }
break;
}
case 4: {
for (uint32_t col = 0; col < width_; ++col) {
- out_row_buffer_[idx++] = (col & 0x01)
- ? (dest_buf[col >> 1] & 0x0F)
+ uint8_t index = (col & 0x01) ? (dest_buf[col >> 1] & 0x0F)
: ((dest_buf[col >> 1] & 0xF0) >> 4);
+ if (!ValidateColorIndex(index))
+ return BmpDecoder::Status::kFail;
+ out_row_buffer_[idx++] = index;
+ }
+ break;
+ }
+ case 8: {
+ for (uint32_t col = 0; col < width_; ++col) {
+ uint8_t index = dest_buf[col];
+ if (!ValidateColorIndex(index))
+ return BmpDecoder::Status::kFail;
+ out_row_buffer_[idx++] = index;
}
break;
}
@@ -421,19 +436,15 @@
}
break;
}
- case 8:
case 24:
case 32:
+ // TODO(crbug.com/pdfium/1901): Apply bitfields.
uint8_t* dest_buf_data = dest_buf.data();
std::copy(dest_buf_data, dest_buf_data + src_row_bytes_,
out_row_buffer_.begin());
idx += src_row_bytes_;
break;
}
- for (uint8_t byte : out_row_buffer_) {
- if (!ValidateColorIndex(byte))
- return BmpDecoder::Status::kFail;
- }
ReadNextScanline();
}
SaveDecodingStatus(DecodeStatus::kTail);
diff --git a/core/fxcodec/progressive_decoder_unittest.cpp b/core/fxcodec/progressive_decoder_unittest.cpp
index ed5c4de..33c20fa 100644
--- a/core/fxcodec/progressive_decoder_unittest.cpp
+++ b/core/fxcodec/progressive_decoder_unittest.cpp
@@ -109,6 +109,70 @@
status = DecodeToBitmap(decoder, bitmap);
EXPECT_EQ(FXCODEC_STATUS::kError, status);
}
+
+TEST(ProgressiveDecoder, Direct24Bmp) {
+ static constexpr uint8_t kInput[] = {
+ 0x42, 0x4d, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00,
+ 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x80, 0x40, 0x00};
+
+ ProgressiveDecoder decoder;
+
+ auto source = pdfium::MakeRetain<CFX_ReadOnlySpanStream>(kInput);
+ CFX_DIBAttribute attr;
+ FXCODEC_STATUS status =
+ decoder.LoadImageInfo(source, FXCODEC_IMAGE_BMP, &attr, true);
+ ASSERT_EQ(FXCODEC_STATUS::kFrameReady, status);
+
+ ASSERT_EQ(1, decoder.GetWidth());
+ ASSERT_EQ(1, decoder.GetHeight());
+
+ auto bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
+ bitmap->Create(decoder.GetWidth(), decoder.GetHeight(), FXDIB_Format::kRgb);
+
+ size_t frames;
+ std::tie(status, frames) = decoder.GetFrames();
+ ASSERT_EQ(FXCODEC_STATUS::kDecodeReady, status);
+ ASSERT_EQ(1u, frames);
+
+ status = DecodeToBitmap(decoder, bitmap);
+ EXPECT_EQ(FXCODEC_STATUS::kDecodeFinished, status);
+ EXPECT_THAT(bitmap->GetScanline(0), ElementsAre(0xc0, 0x80, 0x40, 0x00));
+}
+
+TEST(ProgressiveDecoder, Direct32Bmp) {
+ static constexpr uint8_t kInput[] = {
+ 0x42, 0x4d, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00,
+ 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x80, 0x40, 0xff};
+
+ ProgressiveDecoder decoder;
+
+ auto source = pdfium::MakeRetain<CFX_ReadOnlySpanStream>(kInput);
+ CFX_DIBAttribute attr;
+ FXCODEC_STATUS status =
+ decoder.LoadImageInfo(source, FXCODEC_IMAGE_BMP, &attr, true);
+ ASSERT_EQ(FXCODEC_STATUS::kFrameReady, status);
+
+ ASSERT_EQ(1, decoder.GetWidth());
+ ASSERT_EQ(1, decoder.GetHeight());
+
+ auto bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
+ bitmap->Create(decoder.GetWidth(), decoder.GetHeight(), FXDIB_Format::kRgb);
+
+ size_t frames;
+ std::tie(status, frames) = decoder.GetFrames();
+ ASSERT_EQ(FXCODEC_STATUS::kDecodeReady, status);
+ ASSERT_EQ(1u, frames);
+
+ status = DecodeToBitmap(decoder, bitmap);
+ EXPECT_EQ(FXCODEC_STATUS::kDecodeFinished, status);
+ EXPECT_THAT(bitmap->GetScanline(0), ElementsAre(0xc0, 0x80, 0x40, 0x00));
+}
#endif // PDF_ENABLE_XFA_BMP
#ifdef PDF_ENABLE_XFA_GIF