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