Get rid of longjmp() usage in CFX_BmpDecompressor.

Change CFX_BmpDecompressor::ReadHeader() and friends to return
BmpModule::Status, which is a tri-state, instead of returning a bool and
handling errors with longjmp().

Change-Id: I74d920d582b47832e60a0e00448671c86629a3a7
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/61670
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fxcodec/bmp/bmpmodule.cpp b/core/fxcodec/bmp/bmpmodule.cpp
index d7472a8..78854c4 100644
--- a/core/fxcodec/bmp/bmpmodule.cpp
+++ b/core/fxcodec/bmp/bmpmodule.cpp
@@ -35,11 +35,9 @@
   ASSERT(pAttribute);
 
   auto* ctx = static_cast<CFX_BmpContext*>(pContext);
-  if (setjmp(*ctx->m_Bmp.jmpbuf()))
-    return Status::kFail;
-
-  if (!ctx->m_Bmp.ReadHeader())
-    return Status::kContinue;
+  Status status = ctx->m_Bmp.ReadHeader();
+  if (status != Status::kSuccess)
+    return status;
 
   *width = ctx->m_Bmp.width();
   *height = ctx->m_Bmp.height();
diff --git a/core/fxcodec/bmp/cfx_bmpdecompressor.cpp b/core/fxcodec/bmp/cfx_bmpdecompressor.cpp
index 3adda59..682c68f 100644
--- a/core/fxcodec/bmp/cfx_bmpdecompressor.cpp
+++ b/core/fxcodec/bmp/cfx_bmpdecompressor.cpp
@@ -59,10 +59,6 @@
 
 CFX_BmpDecompressor::~CFX_BmpDecompressor() = default;
 
-void CFX_BmpDecompressor::Error() {
-  longjmp(jmpbuf_, 1);
-}
-
 void CFX_BmpDecompressor::ReadNextScanline() {
   uint32_t row = img_tb_flag_ ? row_num_ : (height_ - 1 - row_num_);
   context_->m_pDelegate->BmpReadScanline(row, out_row_buffer_);
@@ -73,12 +69,15 @@
   return context_->m_pDelegate->BmpInputImagePositionBuf(rcd_pos);
 }
 
-bool CFX_BmpDecompressor::ReadHeader() {
-  if (decode_status_ == DecodeStatus::kHeader && !ReadBmpHeader())
-    return false;
+BmpModule::Status CFX_BmpDecompressor::ReadHeader() {
+  if (decode_status_ == DecodeStatus::kHeader) {
+    BmpModule::Status status = ReadBmpHeader();
+    if (status != BmpModule::Status::kSuccess)
+      return status;
+  }
 
   if (decode_status_ != DecodeStatus::kPal)
-    return true;
+    return BmpModule::Status::kSuccess;
 
   if (compress_flag_ == kBmpBitfields)
     return ReadBmpBitfields();
@@ -86,11 +85,11 @@
   return ReadBmpPalette();
 }
 
-bool CFX_BmpDecompressor::ReadBmpHeader() {
+BmpModule::Status CFX_BmpDecompressor::ReadBmpHeader() {
   BmpFileHeader bmp_header;
   if (!ReadData(reinterpret_cast<uint8_t*>(&bmp_header),
                 sizeof(BmpFileHeader))) {
-    return false;
+    return BmpModule::Status::kContinue;
   }
 
   bmp_header.bfType =
@@ -99,39 +98,34 @@
       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 (bmp_header.bfType != kBmpSignature)
+    return BmpModule::Status::kFail;
 
   size_t pos = input_buffer_->GetPosition();
   if (!ReadData(reinterpret_cast<uint8_t*>(&img_ifh_size_),
                 sizeof(img_ifh_size_))) {
-    return false;
+    return BmpModule::Status::kContinue;
   }
   if (!input_buffer_->Seek(pos))
-    return false;
+    return BmpModule::Status::kContinue;
 
   img_ifh_size_ =
       FXDWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&img_ifh_size_));
   pal_type_ = 0;
-  if (!ReadBmpHeaderIfh())
-    return false;
+  BmpModule::Status status = ReadBmpHeaderIfh();
+  if (status != BmpModule::Status::kSuccess)
+    return status;
 
-  if (!ReadBmpHeaderDimensions()) {
-    Error();
-    NOTREACHED();
-  }
-  return true;
+  return ReadBmpHeaderDimensions();
 }
 
-bool CFX_BmpDecompressor::ReadBmpHeaderIfh() {
+BmpModule::Status 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;
+      return BmpModule::Status::kContinue;
     }
 
     width_ = FXWORD_GET_LSBFIRST(
@@ -142,14 +136,14 @@
         reinterpret_cast<uint8_t*>(&bmp_core_header.bcBitCount));
     compress_flag_ = kBmpRgb;
     img_tb_flag_ = false;
-    return true;
+    return BmpModule::Status::kSuccess;
   }
 
   if (img_ifh_size_ == kBmpInfoHeaderSize) {
     BmpInfoHeader bmp_info_header;
     if (!ReadData(reinterpret_cast<uint8_t*>(&bmp_info_header),
                   sizeof(BmpInfoHeader))) {
-      return false;
+      return BmpModule::Status::kContinue;
     }
 
     width_ = FXDWORD_GET_LSBFIRST(
@@ -166,33 +160,27 @@
         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)));
-    if (!SetHeight(signed_height)) {
-      Error();
-      NOTREACHED();
-    }
-    return true;
+    if (!SetHeight(signed_height))
+      return BmpModule::Status::kFail;
+    return BmpModule::Status::kSuccess;
   }
 
-  if (img_ifh_size_ <= sizeof(BmpInfoHeader)) {
-    Error();
-    NOTREACHED();
-  }
+  if (img_ifh_size_ <= sizeof(BmpInfoHeader))
+    return BmpModule::Status::kFail;
 
   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;
+    return BmpModule::Status::kContinue;
   }
 
   new_pos += img_ifh_size_;
-  if (!new_pos.IsValid()) {
-    Error();
-    NOTREACHED();
-  }
+  if (!new_pos.IsValid())
+    return BmpModule::Status::kFail;
 
   if (!input_buffer_->Seek(new_pos.ValueOrDie()))
-    return false;
+    return BmpModule::Status::kContinue;
 
   uint16_t bi_planes;
   width_ = FXDWORD_GET_LSBFIRST(
@@ -211,21 +199,17 @@
       reinterpret_cast<uint8_t*>(&bmp_info_header.biXPelsPerMeter));
   dpi_y_ = FXDWORD_GET_LSBFIRST(
       reinterpret_cast<uint8_t*>(&bmp_info_header.biYPelsPerMeter));
-  if (!SetHeight(signed_height)) {
-    Error();
-    NOTREACHED();
-  }
-  if (compress_flag_ != kBmpRgb || bi_planes != 1 || color_used_ != 0) {
-    Error();
-    NOTREACHED();
-  }
-  return true;
+  if (!SetHeight(signed_height))
+    return BmpModule::Status::kFail;
+  if (compress_flag_ != kBmpRgb || bi_planes != 1 || color_used_ != 0)
+    return BmpModule::Status::kFail;
+  return BmpModule::Status::kSuccess;
 }
 
-bool CFX_BmpDecompressor::ReadBmpHeaderDimensions() {
+BmpModule::Status CFX_BmpDecompressor::ReadBmpHeaderDimensions() {
   if (width_ > kBmpMaxImageDimension || height_ > kBmpMaxImageDimension ||
       compress_flag_ > kBmpBitfields) {
-    return false;
+    return BmpModule::Status::kFail;
   }
 
   switch (bit_counts_) {
@@ -235,17 +219,17 @@
     case 16:
     case 24: {
       if (color_used_ > 1U << bit_counts_)
-        return false;
+        return BmpModule::Status::kFail;
       break;
     }
     case 32:
       break;
     default:
-      return false;
+      return BmpModule::Status::kFail;
   }
   FX_SAFE_UINT32 stride = CalculatePitch32(bit_counts_, width_);
   if (!stride.IsValid())
-    return false;
+    return BmpModule::Status::kFail;
 
   src_row_bytes_ = stride.ValueOrDie();
   switch (bit_counts_) {
@@ -254,7 +238,7 @@
     case 8:
       stride = CalculatePitch32(8, width_);
       if (!stride.IsValid())
-        return false;
+        return BmpModule::Status::kFail;
       out_row_bytes_ = stride.ValueOrDie();
       components_ = 1;
       break;
@@ -262,7 +246,7 @@
     case 24:
       stride = CalculatePitch32(24, width_);
       if (!stride.IsValid())
-        return false;
+        return BmpModule::Status::kFail;
       out_row_bytes_ = stride.ValueOrDie();
       components_ = 3;
       break;
@@ -274,37 +258,34 @@
   out_row_buffer_.clear();
 
   if (out_row_bytes_ <= 0)
-    return false;
+    return BmpModule::Status::kFail;
 
   out_row_buffer_.resize(out_row_bytes_);
   SaveDecodingStatus(DecodeStatus::kPal);
-  return true;
+  return BmpModule::Status::kSuccess;
 }
 
-bool CFX_BmpDecompressor::ReadBmpBitfields() {
-  if (bit_counts_ != 16 && bit_counts_ != 32) {
-    Error();
-    NOTREACHED();
-  }
+BmpModule::Status CFX_BmpDecompressor::ReadBmpBitfields() {
+  if (bit_counts_ != 16 && bit_counts_ != 32)
+    return BmpModule::Status::kFail;
 
   uint32_t masks[3];
   if (!ReadData(reinterpret_cast<uint8_t*>(masks), sizeof(masks)))
-    return false;
+    return BmpModule::Status::kContinue;
 
   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();
+    return BmpModule::Status::kFail;
   }
   header_offset_ = std::max(header_offset_, 26 + img_ifh_size_);
   SaveDecodingStatus(DecodeStatus::kDataPre);
-  return true;
+  return BmpModule::Status::kSuccess;
 }
 
-bool CFX_BmpDecompressor::ReadBmpPalette() {
+BmpModule::Status CFX_BmpDecompressor::ReadBmpPalette() {
   if (bit_counts_ == 16) {
     mask_red_ = 0x7C00;
     mask_green_ = 0x03E0;
@@ -319,7 +300,7 @@
     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))
-      return false;
+      return BmpModule::Status::kContinue;
 
     palette_.resize(pal_num_);
     int32_t src_pal_index = 0;
@@ -340,7 +321,7 @@
   header_offset_ = std::max(
       header_offset_, 14 + img_ifh_size_ + pal_num_ * (pal_type_ ? 3 : 4));
   SaveDecodingStatus(DecodeStatus::kDataPre);
-  return true;
+  return BmpModule::Status::kSuccess;
 }
 
 bool CFX_BmpDecompressor::ValidateFlag() const {
diff --git a/core/fxcodec/bmp/cfx_bmpdecompressor.h b/core/fxcodec/bmp/cfx_bmpdecompressor.h
index e9761b5..3f4e2d8 100644
--- a/core/fxcodec/bmp/cfx_bmpdecompressor.h
+++ b/core/fxcodec/bmp/cfx_bmpdecompressor.h
@@ -7,8 +7,6 @@
 #ifndef CORE_FXCODEC_BMP_CFX_BMPDECOMPRESSOR_H_
 #define CORE_FXCODEC_BMP_CFX_BMPDECOMPRESSOR_H_
 
-#include <setjmp.h>
-
 #include <vector>
 
 #include "core/fxcodec/bmp/bmpmodule.h"
@@ -27,13 +25,11 @@
   explicit CFX_BmpDecompressor(CFX_BmpContext* context);
   ~CFX_BmpDecompressor();
 
-  void Error();
   BmpModule::Status DecodeImage();
-  bool ReadHeader();
+  BmpModule::Status ReadHeader();
   void SetInputBuffer(RetainPtr<CFX_CodecMemory> codec_memory);
   FX_FILESIZE GetAvailInput() const;
 
-  jmp_buf* jmpbuf() { return &jmpbuf_; }
   const std::vector<uint32_t>* palette() const { return &palette_; }
   uint32_t width() const { return width_; }
   uint32_t height() const { return height_; }
@@ -52,11 +48,11 @@
     kTail,
   };
 
-  bool ReadBmpHeader();
-  bool ReadBmpHeaderIfh();
-  bool ReadBmpHeaderDimensions();
-  bool ReadBmpBitfields();
-  bool ReadBmpPalette();
+  BmpModule::Status ReadBmpHeader();
+  BmpModule::Status ReadBmpHeaderIfh();
+  BmpModule::Status ReadBmpHeaderDimensions();
+  BmpModule::Status ReadBmpBitfields();
+  BmpModule::Status ReadBmpPalette();
   bool GetDataPosition(uint32_t cur_pos);
   void ReadNextScanline();
   BmpModule::Status DecodeRGB();
@@ -68,7 +64,6 @@
   bool ValidateFlag() const;
   bool SetHeight(int32_t signed_height);
 
-  jmp_buf jmpbuf_;
   UnownedPtr<CFX_BmpContext> const context_;
   std::vector<uint8_t> out_row_buffer_;
   std::vector<uint32_t> palette_;