1 // Copyright 2018 The PDFium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "core/fxcodec/bmp/cfx_bmpdecompressor.h"
8
9 #include <stdint.h>
10
11 #include <algorithm>
12 #include <limits>
13 #include <utility>
14
15 #include "core/fxcodec/bmp/cfx_bmpcontext.h"
16 #include "core/fxcodec/cfx_codec_memory.h"
17 #include "core/fxcrt/byteorder.h"
18 #include "core/fxcrt/compiler_specific.h"
19 #include "core/fxcrt/data_vector.h"
20 #include "core/fxcrt/fx_safe_types.h"
21 #include "core/fxcrt/numerics/safe_math.h"
22 #include "core/fxcrt/span_util.h"
23 #include "core/fxcrt/stl_util.h"
24 #include "core/fxge/calculate_pitch.h"
25
26 namespace fxcodec {
27
28 namespace {
29
30 constexpr size_t kBmpCoreHeaderSize = 12;
31 constexpr size_t kBmpInfoHeaderSize = 40;
32
33 static_assert(sizeof(BmpCoreHeader) == kBmpCoreHeaderSize,
34 "BmpCoreHeader has wrong size");
35 static_assert(sizeof(BmpInfoHeader) == kBmpInfoHeaderSize,
36 "BmpInfoHeader has wrong size");
37
38 constexpr uint16_t kBmpSignature = 0x4D42;
39 constexpr uint8_t kRleMarker = 0;
40 constexpr uint8_t kRleEol = 0;
41 constexpr uint8_t kRleEoi = 1;
42 constexpr uint8_t kRleDelta = 2;
43 constexpr uint32_t kBmpRgb = 0L;
44 constexpr uint32_t kBmpRle8 = 1L;
45 constexpr uint32_t kBmpRle4 = 2L;
46 constexpr uint32_t kBmpBitfields = 3L;
47
48 // Limit of image dimension. Use the same limit as the JBIG2 codecs.
49 constexpr uint32_t kBmpMaxImageDimension = 65535;
50
HalfRoundUp(uint8_t value)51 uint8_t HalfRoundUp(uint8_t value) {
52 uint16_t value16 = value;
53 return static_cast<uint8_t>((value16 + 1) / 2);
54 }
55
56 } // namespace
57
CFX_BmpDecompressor(const CFX_BmpContext * context)58 CFX_BmpDecompressor::CFX_BmpDecompressor(const CFX_BmpContext* context)
59 : context_(context) {}
60
61 CFX_BmpDecompressor::~CFX_BmpDecompressor() = default;
62
ReadNextScanline()63 void CFX_BmpDecompressor::ReadNextScanline() {
64 uint32_t row = img_tb_flag_ ? row_num_ : (height_ - 1 - row_num_);
65 context_->m_pDelegate->BmpReadScanline(row, out_row_buffer_);
66 ++row_num_;
67 }
68
GetDataPosition(uint32_t rcd_pos)69 bool CFX_BmpDecompressor::GetDataPosition(uint32_t rcd_pos) {
70 return context_->m_pDelegate->BmpInputImagePositionBuf(rcd_pos);
71 }
72
ReadHeader()73 BmpDecoder::Status CFX_BmpDecompressor::ReadHeader() {
74 if (decode_status_ == DecodeStatus::kHeader) {
75 BmpDecoder::Status status = ReadBmpHeader();
76 if (status != BmpDecoder::Status::kSuccess)
77 return status;
78 }
79
80 if (decode_status_ != DecodeStatus::kPal)
81 return BmpDecoder::Status::kSuccess;
82
83 if (compress_flag_ == kBmpBitfields)
84 return ReadBmpBitfields();
85
86 return ReadBmpPalette();
87 }
88
ReadBmpHeader()89 BmpDecoder::Status CFX_BmpDecompressor::ReadBmpHeader() {
90 BmpFileHeader bmp_header;
91 if (!ReadAllOrNone(
92 pdfium::as_writable_bytes(pdfium::span_from_ref(bmp_header)))) {
93 return BmpDecoder::Status::kContinue;
94 }
95
96 bmp_header.bfType = fxcrt::FromLE16(bmp_header.bfType);
97 data_offset_ = fxcrt::FromLE32(bmp_header.bfOffBits);
98 data_size_ = fxcrt::FromLE32(bmp_header.bfSize);
99 if (bmp_header.bfType != kBmpSignature)
100 return BmpDecoder::Status::kFail;
101
102 size_t pos = input_buffer_->GetPosition();
103 if (!ReadAllOrNone(
104 pdfium::as_writable_bytes(pdfium::span_from_ref(img_ifh_size_)))) {
105 return BmpDecoder::Status::kContinue;
106 }
107 if (!input_buffer_->Seek(pos))
108 return BmpDecoder::Status::kFail;
109
110 img_ifh_size_ = fxcrt::FromLE32(img_ifh_size_);
111 pal_type_ = PalType::kNew;
112 BmpDecoder::Status status = ReadBmpHeaderIfh();
113 if (status != BmpDecoder::Status::kSuccess)
114 return status;
115
116 return ReadBmpHeaderDimensions();
117 }
118
ReadBmpHeaderIfh()119 BmpDecoder::Status CFX_BmpDecompressor::ReadBmpHeaderIfh() {
120 if (img_ifh_size_ == kBmpCoreHeaderSize) {
121 pal_type_ = PalType::kOld;
122 BmpCoreHeader bmp_core_header;
123 if (!ReadAllOrNone(pdfium::as_writable_bytes(
124 pdfium::span_from_ref(bmp_core_header)))) {
125 return BmpDecoder::Status::kContinue;
126 }
127
128 width_ = fxcrt::FromLE16(bmp_core_header.bcWidth);
129 height_ = fxcrt::FromLE16(bmp_core_header.bcHeight);
130 bit_counts_ = fxcrt::FromLE16(bmp_core_header.bcBitCount);
131 compress_flag_ = kBmpRgb;
132 img_tb_flag_ = false;
133 return BmpDecoder::Status::kSuccess;
134 }
135
136 if (img_ifh_size_ == kBmpInfoHeaderSize) {
137 BmpInfoHeader bmp_info_header;
138 if (!ReadAllOrNone(pdfium::as_writable_bytes(
139 pdfium::span_from_ref(bmp_info_header)))) {
140 return BmpDecoder::Status::kContinue;
141 }
142
143 width_ = fxcrt::FromLE32(bmp_info_header.biWidth);
144 bit_counts_ = fxcrt::FromLE16(bmp_info_header.biBitCount);
145 compress_flag_ = fxcrt::FromLE32(bmp_info_header.biCompression);
146 color_used_ = fxcrt::FromLE32(bmp_info_header.biClrUsed);
147 dpi_x_ =
148 static_cast<int32_t>(fxcrt::FromLE32(bmp_info_header.biXPelsPerMeter));
149 dpi_y_ =
150 static_cast<int32_t>(fxcrt::FromLE32(bmp_info_header.biYPelsPerMeter));
151
152 int32_t signed_height = fxcrt::FromLE32(bmp_info_header.biHeight);
153 if (!SetHeight(signed_height)) {
154 return BmpDecoder::Status::kFail;
155 }
156 return BmpDecoder::Status::kSuccess;
157 }
158
159 if (img_ifh_size_ <= sizeof(BmpInfoHeader))
160 return BmpDecoder::Status::kFail;
161
162 FX_SAFE_SIZE_T new_pos = input_buffer_->GetPosition();
163 BmpInfoHeader bmp_info_header;
164 if (!ReadAllOrNone(
165 pdfium::as_writable_bytes(pdfium::span_from_ref(bmp_info_header)))) {
166 return BmpDecoder::Status::kContinue;
167 }
168
169 new_pos += img_ifh_size_;
170 if (!new_pos.IsValid())
171 return BmpDecoder::Status::kFail;
172
173 if (!input_buffer_->Seek(new_pos.ValueOrDie()))
174 return BmpDecoder::Status::kContinue;
175
176 width_ = fxcrt::FromLE32(bmp_info_header.biWidth);
177 bit_counts_ = fxcrt::FromLE16(bmp_info_header.biBitCount);
178 compress_flag_ = fxcrt::FromLE32(bmp_info_header.biCompression);
179 color_used_ = fxcrt::FromLE32(bmp_info_header.biClrUsed);
180 dpi_x_ = fxcrt::FromLE32(bmp_info_header.biXPelsPerMeter);
181 dpi_y_ = fxcrt::FromLE32(bmp_info_header.biYPelsPerMeter);
182
183 int32_t signed_height = fxcrt::FromLE32(bmp_info_header.biHeight);
184 if (!SetHeight(signed_height)) {
185 return BmpDecoder::Status::kFail;
186 }
187 uint16_t bi_planes = fxcrt::FromLE16(bmp_info_header.biPlanes);
188 if (compress_flag_ != kBmpRgb || bi_planes != 1 || color_used_ != 0) {
189 return BmpDecoder::Status::kFail;
190 }
191 return BmpDecoder::Status::kSuccess;
192 }
193
ReadBmpHeaderDimensions()194 BmpDecoder::Status CFX_BmpDecompressor::ReadBmpHeaderDimensions() {
195 if (width_ > kBmpMaxImageDimension || height_ > kBmpMaxImageDimension ||
196 compress_flag_ > kBmpBitfields) {
197 return BmpDecoder::Status::kFail;
198 }
199
200 switch (bit_counts_) {
201 case 1:
202 case 4:
203 case 8:
204 case 16:
205 case 24: {
206 if (color_used_ > 1U << bit_counts_)
207 return BmpDecoder::Status::kFail;
208 break;
209 }
210 case 32:
211 break;
212 default:
213 return BmpDecoder::Status::kFail;
214 }
215 std::optional<uint32_t> stride = fxge::CalculatePitch32(bit_counts_, width_);
216 if (!stride.has_value())
217 return BmpDecoder::Status::kFail;
218
219 src_row_bytes_ = stride.value();
220 switch (bit_counts_) {
221 case 1:
222 case 4:
223 case 8:
224 stride = fxge::CalculatePitch32(8, width_);
225 if (!stride.has_value())
226 return BmpDecoder::Status::kFail;
227 out_row_bytes_ = stride.value();
228 components_ = 1;
229 break;
230 case 16:
231 case 24:
232 stride = fxge::CalculatePitch32(24, width_);
233 if (!stride.has_value())
234 return BmpDecoder::Status::kFail;
235 out_row_bytes_ = stride.value();
236 components_ = 3;
237 break;
238 case 32:
239 out_row_bytes_ = src_row_bytes_;
240 components_ = 4;
241 break;
242 }
243 out_row_buffer_.clear();
244
245 if (out_row_bytes_ <= 0)
246 return BmpDecoder::Status::kFail;
247
248 out_row_buffer_.resize(out_row_bytes_);
249 SaveDecodingStatus(DecodeStatus::kPal);
250 return BmpDecoder::Status::kSuccess;
251 }
252
ReadBmpBitfields()253 BmpDecoder::Status CFX_BmpDecompressor::ReadBmpBitfields() {
254 if (bit_counts_ != 16 && bit_counts_ != 32)
255 return BmpDecoder::Status::kFail;
256
257 uint32_t masks[3];
258 if (!ReadAllOrNone(pdfium::as_writable_byte_span(masks))) {
259 return BmpDecoder::Status::kContinue;
260 }
261
262 mask_red_ = fxcrt::FromLE32(masks[0]);
263 mask_green_ = fxcrt::FromLE32(masks[1]);
264 mask_blue_ = fxcrt::FromLE32(masks[2]);
265 if (mask_red_ & mask_green_ || mask_red_ & mask_blue_ ||
266 mask_green_ & mask_blue_) {
267 return BmpDecoder::Status::kFail;
268 }
269 header_offset_ = std::max(header_offset_, 26 + img_ifh_size_);
270 SaveDecodingStatus(DecodeStatus::kDataPre);
271 return BmpDecoder::Status::kSuccess;
272 }
273
ReadBmpPalette()274 BmpDecoder::Status CFX_BmpDecompressor::ReadBmpPalette() {
275 if (bit_counts_ == 16) {
276 mask_red_ = 0x7C00;
277 mask_green_ = 0x03E0;
278 mask_blue_ = 0x001F;
279 }
280 uint32_t palette_entries = 0;
281 if (bit_counts_ < 16) {
282 palette_entries = 1 << bit_counts_;
283 if (color_used_ != 0) {
284 palette_entries = color_used_;
285 }
286 size_t pal_bytes = palette_entries * PaletteChannelCount();
287 DataVector<uint8_t> src_pal(pal_bytes);
288 if (!ReadAllOrNone(src_pal))
289 return BmpDecoder::Status::kContinue;
290
291 palette_.resize(palette_entries);
292 if (pal_type_ == PalType::kOld) {
293 auto src_pal_data =
294 fxcrt::reinterpret_span<FX_BGR_STRUCT<uint8_t>, uint8_t>(src_pal);
295 for (auto& dest : palette_) {
296 const auto& entry = src_pal_data.front();
297 dest = ArgbEncode(0x00, entry.red, entry.green, entry.blue);
298 src_pal_data = src_pal_data.subspan(1);
299 }
300 } else {
301 auto src_pal_data =
302 fxcrt::reinterpret_span<FX_BGRA_STRUCT<uint8_t>, uint8_t>(src_pal);
303 for (auto& dest : palette_) {
304 const auto& entry = src_pal_data.front();
305 dest = ArgbEncode(entry.alpha, entry.red, entry.green, entry.blue);
306 src_pal_data = src_pal_data.subspan(1);
307 }
308 }
309 }
310 header_offset_ =
311 std::max(header_offset_,
312 14 + img_ifh_size_ + palette_entries * PaletteChannelCount());
313 SaveDecodingStatus(DecodeStatus::kDataPre);
314 return BmpDecoder::Status::kSuccess;
315 }
316
ValidateFlag() const317 bool CFX_BmpDecompressor::ValidateFlag() const {
318 switch (compress_flag_) {
319 case kBmpRgb:
320 case kBmpBitfields:
321 case kBmpRle8:
322 case kBmpRle4:
323 return true;
324 default:
325 return false;
326 }
327 }
328
DecodeImage()329 BmpDecoder::Status CFX_BmpDecompressor::DecodeImage() {
330 if (decode_status_ == DecodeStatus::kDataPre) {
331 // In order to tolerate certain corrupt BMP files, use the header offset if
332 // the data offset would point into the header.
333 data_offset_ = std::max(header_offset_, data_offset_);
334
335 input_buffer_->Seek(input_buffer_->GetSize());
336 if (!GetDataPosition(data_offset_)) {
337 decode_status_ = DecodeStatus::kTail;
338 return BmpDecoder::Status::kFail;
339 }
340
341 row_num_ = 0;
342 SaveDecodingStatus(DecodeStatus::kData);
343 }
344 if (decode_status_ != DecodeStatus::kData || !ValidateFlag())
345 return BmpDecoder::Status::kFail;
346
347 switch (compress_flag_) {
348 case kBmpRgb:
349 case kBmpBitfields:
350 return DecodeRGB();
351 case kBmpRle8:
352 return DecodeRLE8();
353 case kBmpRle4:
354 return DecodeRLE4();
355 default:
356 return BmpDecoder::Status::kFail;
357 }
358 }
359
ValidateColorIndex(uint8_t val) const360 bool CFX_BmpDecompressor::ValidateColorIndex(uint8_t val) const {
361 return val < palette_.size();
362 }
363
DecodeRGB()364 BmpDecoder::Status CFX_BmpDecompressor::DecodeRGB() {
365 DataVector<uint8_t> dest_buf(src_row_bytes_);
366 while (row_num_ < height_) {
367 size_t idx = 0;
368 if (!ReadAllOrNone(dest_buf))
369 return BmpDecoder::Status::kContinue;
370
371 SaveDecodingStatus(DecodeStatus::kData);
372 switch (bit_counts_) {
373 case 1: {
374 for (uint32_t col = 0; col < width_; ++col) {
375 uint8_t index =
376 dest_buf[col >> 3] & (0x80 >> (col % 8)) ? 0x01 : 0x00;
377 if (!ValidateColorIndex(index))
378 return BmpDecoder::Status::kFail;
379 out_row_buffer_[idx++] = index;
380 }
381 break;
382 }
383 case 4: {
384 for (uint32_t col = 0; col < width_; ++col) {
385 uint8_t index = (col & 0x01) ? (dest_buf[col >> 1] & 0x0F)
386 : ((dest_buf[col >> 1] & 0xF0) >> 4);
387 if (!ValidateColorIndex(index))
388 return BmpDecoder::Status::kFail;
389 out_row_buffer_[idx++] = index;
390 }
391 break;
392 }
393 case 8: {
394 for (uint32_t col = 0; col < width_; ++col) {
395 uint8_t index = dest_buf[col];
396 if (!ValidateColorIndex(index))
397 return BmpDecoder::Status::kFail;
398 out_row_buffer_[idx++] = index;
399 }
400 break;
401 }
402 case 16: {
403 auto buf =
404 fxcrt::reinterpret_span<uint16_t>(pdfium::make_span(dest_buf));
405 uint8_t blue_bits = 0;
406 uint8_t green_bits = 0;
407 uint8_t red_bits = 0;
408 for (int32_t i = 0; i < 16; i++) {
409 if ((mask_blue_ >> i) & 0x01)
410 blue_bits++;
411 if ((mask_green_ >> i) & 0x01)
412 green_bits++;
413 if ((mask_red_ >> i) & 0x01)
414 red_bits++;
415 }
416 green_bits += blue_bits;
417 red_bits += green_bits;
418 if (blue_bits > 8 || green_bits < 8 || red_bits < 8)
419 return BmpDecoder::Status::kContinue;
420 blue_bits = 8 - blue_bits;
421 green_bits -= 8;
422 red_bits -= 8;
423 for (uint32_t col = 0; col < width_; ++col) {
424 buf.front() = fxcrt::FromLE16(buf.front());
425 out_row_buffer_[idx++] =
426 static_cast<uint8_t>((buf.front() & mask_blue_) << blue_bits);
427 out_row_buffer_[idx++] =
428 static_cast<uint8_t>((buf.front() & mask_green_) >> green_bits);
429 out_row_buffer_[idx++] =
430 static_cast<uint8_t>((buf.front() & mask_red_) >> red_bits);
431 buf = buf.subspan(1);
432 }
433 break;
434 }
435 case 24:
436 case 32:
437 // TODO(crbug.com/pdfium/1901): Apply bitfields.
438 fxcrt::Copy(pdfium::make_span(dest_buf).first(src_row_bytes_),
439 out_row_buffer_);
440 idx += src_row_bytes_;
441 break;
442 }
443 ReadNextScanline();
444 }
445 SaveDecodingStatus(DecodeStatus::kTail);
446 return BmpDecoder::Status::kSuccess;
447 }
448
DecodeRLE8()449 BmpDecoder::Status CFX_BmpDecompressor::DecodeRLE8() {
450 uint8_t first_part;
451 col_num_ = 0;
452 while (true) {
453 if (!ReadAllOrNone(pdfium::span_from_ref(first_part))) {
454 return BmpDecoder::Status::kContinue;
455 }
456
457 switch (first_part) {
458 case kRleMarker: {
459 if (!ReadAllOrNone(pdfium::span_from_ref(first_part))) {
460 return BmpDecoder::Status::kContinue;
461 }
462
463 switch (first_part) {
464 case kRleEol: {
465 if (row_num_ >= height_) {
466 SaveDecodingStatus(DecodeStatus::kTail);
467 return BmpDecoder::Status::kFail;
468 }
469
470 ReadNextScanline();
471 col_num_ = 0;
472 fxcrt::Fill(out_row_buffer_, 0);
473 SaveDecodingStatus(DecodeStatus::kData);
474 continue;
475 }
476 case kRleEoi: {
477 if (row_num_ < height_)
478 ReadNextScanline();
479 SaveDecodingStatus(DecodeStatus::kTail);
480 return BmpDecoder::Status::kSuccess;
481 }
482 case kRleDelta: {
483 uint8_t delta[2];
484 if (!ReadAllOrNone(delta))
485 return BmpDecoder::Status::kContinue;
486
487 col_num_ += delta[0];
488 size_t bmp_row_num__next = row_num_ + delta[1];
489 if (col_num_ >= out_row_bytes_ || bmp_row_num__next >= height_)
490 return BmpDecoder::Status::kFail;
491
492 while (row_num_ < bmp_row_num__next) {
493 fxcrt::Fill(out_row_buffer_, 0);
494 ReadNextScanline();
495 }
496 break;
497 }
498 default: {
499 int32_t avail_size =
500 pdfium::checked_cast<int32_t>(out_row_bytes_ - col_num_);
501 if (!avail_size || static_cast<int32_t>(first_part) > avail_size)
502 return BmpDecoder::Status::kFail;
503
504 size_t second_part_size =
505 first_part & 1 ? first_part + 1 : first_part;
506 DataVector<uint8_t> second_part(second_part_size);
507 if (!ReadAllOrNone(second_part))
508 return BmpDecoder::Status::kContinue;
509
510 fxcrt::Copy(pdfium::make_span(second_part).first(first_part),
511 pdfium::make_span(out_row_buffer_).subspan(col_num_));
512
513 for (size_t i = col_num_; i < col_num_ + first_part; ++i) {
514 if (!ValidateColorIndex(out_row_buffer_[i]))
515 return BmpDecoder::Status::kFail;
516 }
517 col_num_ += first_part;
518 }
519 }
520 break;
521 }
522 default: {
523 int32_t avail_size =
524 pdfium::checked_cast<int32_t>(out_row_bytes_ - col_num_);
525 if (!avail_size || static_cast<int32_t>(first_part) > avail_size)
526 return BmpDecoder::Status::kFail;
527
528 uint8_t second_part;
529 if (!ReadAllOrNone(pdfium::span_from_ref(second_part))) {
530 return BmpDecoder::Status::kContinue;
531 }
532
533 fxcrt::Fill(
534 pdfium::make_span(out_row_buffer_).subspan(col_num_, first_part),
535 second_part);
536
537 if (!ValidateColorIndex(out_row_buffer_[col_num_]))
538 return BmpDecoder::Status::kFail;
539 col_num_ += first_part;
540 }
541 }
542 }
543 }
544
DecodeRLE4()545 BmpDecoder::Status CFX_BmpDecompressor::DecodeRLE4() {
546 uint8_t first_part;
547 col_num_ = 0;
548 while (true) {
549 if (!ReadAllOrNone(pdfium::span_from_ref(first_part))) {
550 return BmpDecoder::Status::kContinue;
551 }
552
553 switch (first_part) {
554 case kRleMarker: {
555 if (!ReadAllOrNone(pdfium::span_from_ref(first_part))) {
556 return BmpDecoder::Status::kContinue;
557 }
558
559 switch (first_part) {
560 case kRleEol: {
561 if (row_num_ >= height_) {
562 SaveDecodingStatus(DecodeStatus::kTail);
563 return BmpDecoder::Status::kFail;
564 }
565
566 ReadNextScanline();
567 col_num_ = 0;
568 fxcrt::Fill(out_row_buffer_, 0);
569 SaveDecodingStatus(DecodeStatus::kData);
570 continue;
571 }
572 case kRleEoi: {
573 if (row_num_ < height_)
574 ReadNextScanline();
575 SaveDecodingStatus(DecodeStatus::kTail);
576 return BmpDecoder::Status::kSuccess;
577 }
578 case kRleDelta: {
579 uint8_t delta[2];
580 if (!ReadAllOrNone(delta))
581 return BmpDecoder::Status::kContinue;
582
583 col_num_ += delta[0];
584 size_t bmp_row_num__next = row_num_ + delta[1];
585 if (col_num_ >= out_row_bytes_ || bmp_row_num__next >= height_)
586 return BmpDecoder::Status::kFail;
587
588 while (row_num_ < bmp_row_num__next) {
589 fxcrt::Fill(out_row_buffer_, 0);
590 ReadNextScanline();
591 }
592 break;
593 }
594 default: {
595 int32_t avail_size =
596 pdfium::checked_cast<int32_t>(out_row_bytes_ - col_num_);
597 if (!avail_size)
598 return BmpDecoder::Status::kFail;
599 uint8_t size = HalfRoundUp(first_part);
600 if (static_cast<int32_t>(first_part) > avail_size) {
601 if (size + (col_num_ >> 1) > src_row_bytes_)
602 return BmpDecoder::Status::kFail;
603
604 first_part = avail_size - 1;
605 }
606 size_t second_part_size = size & 1 ? size + 1 : size;
607 DataVector<uint8_t> second_part(second_part_size);
608 uint8_t* second_part_data = second_part.data();
609 if (!ReadAllOrNone(second_part))
610 return BmpDecoder::Status::kContinue;
611
612 for (uint8_t i = 0; i < first_part; i++) {
613 uint8_t color = (i & 0x01)
614 ? UNSAFE_TODO((*second_part_data++ & 0x0F))
615 : (*second_part_data & 0xF0) >> 4;
616 if (!ValidateColorIndex(color)) {
617 return BmpDecoder::Status::kFail;
618 }
619 out_row_buffer_[col_num_++] = color;
620 }
621 }
622 }
623 break;
624 }
625 default: {
626 int32_t avail_size =
627 pdfium::checked_cast<int32_t>(out_row_bytes_ - col_num_);
628 if (!avail_size)
629 return BmpDecoder::Status::kFail;
630
631 if (static_cast<int32_t>(first_part) > avail_size) {
632 uint8_t size = HalfRoundUp(first_part);
633 if (size + (col_num_ >> 1) > src_row_bytes_)
634 return BmpDecoder::Status::kFail;
635
636 first_part = avail_size - 1;
637 }
638 uint8_t second_part;
639 if (!ReadAllOrNone(pdfium::span_from_ref(second_part))) {
640 return BmpDecoder::Status::kContinue;
641 }
642
643 for (uint8_t i = 0; i < first_part; i++) {
644 uint8_t second_byte = second_part;
645 second_byte =
646 i & 0x01 ? (second_byte & 0x0F) : (second_byte & 0xF0) >> 4;
647 if (!ValidateColorIndex(second_byte))
648 return BmpDecoder::Status::kFail;
649
650 out_row_buffer_[col_num_++] = second_byte;
651 }
652 }
653 }
654 }
655 }
656
ReadAllOrNone(pdfium::span<uint8_t> buf)657 bool CFX_BmpDecompressor::ReadAllOrNone(pdfium::span<uint8_t> buf) {
658 if (!input_buffer_)
659 return false;
660
661 size_t original_position = input_buffer_->GetPosition();
662 size_t read = input_buffer_->ReadBlock(buf);
663 if (read < buf.size()) {
664 input_buffer_->Seek(original_position);
665 return false;
666 }
667
668 return true;
669 }
670
SaveDecodingStatus(DecodeStatus status)671 void CFX_BmpDecompressor::SaveDecodingStatus(DecodeStatus status) {
672 decode_status_ = status;
673 }
674
SetInputBuffer(RetainPtr<CFX_CodecMemory> codec_memory)675 void CFX_BmpDecompressor::SetInputBuffer(
676 RetainPtr<CFX_CodecMemory> codec_memory) {
677 input_buffer_ = std::move(codec_memory);
678 }
679
GetAvailInput() const680 FX_FILESIZE CFX_BmpDecompressor::GetAvailInput() const {
681 if (!input_buffer_)
682 return 0;
683
684 return input_buffer_->GetSize() - input_buffer_->GetPosition();
685 }
686
SetHeight(int32_t signed_height)687 bool CFX_BmpDecompressor::SetHeight(int32_t signed_height) {
688 if (signed_height >= 0) {
689 height_ = signed_height;
690 return true;
691 }
692 if (signed_height != std::numeric_limits<int>::min()) {
693 height_ = -signed_height;
694 img_tb_flag_ = true;
695 return true;
696 }
697 return false;
698 }
699
700 } // namespace fxcodec
701