Change JpegModule::LoadInfo() to return an optional struct.

Return the image info in a struct, instead of 5 separate out parameters.
Fix some nits in JpegModule code as well.

Change-Id: I0df5f112cb962733355dc41a18d005f015b68db8
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/65774
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/page/cpdf_dib.cpp b/core/fpdfapi/page/cpdf_dib.cpp
index 1a79a2f..9bb2fb5 100644
--- a/core/fpdfapi/page/cpdf_dib.cpp
+++ b/core/fpdfapi/page/cpdf_dib.cpp
@@ -549,26 +549,28 @@
   if (m_pDecoder)
     return true;
 
-  bool bTransform = false;
-  int comps;
-  int bpc;
-  if (!pJpegModule->LoadInfo(src_span, &m_Width, &m_Height, &comps, &bpc,
-                             &bTransform)) {
+  Optional<JpegModule::JpegImageInfo> info_opt =
+      pJpegModule->LoadInfo(src_span);
+  if (!info_opt.has_value())
     return false;
-  }
-  if (!CPDF_Image::IsValidJpegComponent(comps) ||
-      !CPDF_Image::IsValidJpegBitsPerComponent(bpc)) {
+
+  const JpegModule::JpegImageInfo& info = info_opt.value();
+  m_Width = info.width;
+  m_Height = info.height;
+
+  if (!CPDF_Image::IsValidJpegComponent(info.num_components) ||
+      !CPDF_Image::IsValidJpegBitsPerComponent(info.bits_per_components)) {
     return false;
   }
 
-  if (m_nComponents == static_cast<uint32_t>(comps)) {
-    m_bpc = bpc;
-    m_pDecoder = pJpegModule->CreateDecoder(src_span, m_Width, m_Height,
-                                            m_nComponents, bTransform);
+  if (m_nComponents == static_cast<uint32_t>(info.num_components)) {
+    m_bpc = info.bits_per_components;
+    m_pDecoder = pJpegModule->CreateDecoder(
+        src_span, m_Width, m_Height, m_nComponents, info.color_transform);
     return true;
   }
 
-  m_nComponents = static_cast<uint32_t>(comps);
+  m_nComponents = static_cast<uint32_t>(info.num_components);
   m_CompData.clear();
   if (m_pColorSpace) {
     uint32_t colorspace_comps = m_pColorSpace->CountComponents();
@@ -607,9 +609,9 @@
   if (!GetDecodeAndMaskArray(&m_bDefaultDecode, &m_bColorKey))
     return false;
 
-  m_bpc = bpc;
+  m_bpc = info.bits_per_components;
   m_pDecoder = pJpegModule->CreateDecoder(src_span, m_Width, m_Height,
-                                          m_nComponents, bTransform);
+                                          m_nComponents, info.color_transform);
   return true;
 }
 
diff --git a/core/fpdfapi/page/cpdf_image.cpp b/core/fpdfapi/page/cpdf_image.cpp
index fb109eb..5fbb154 100644
--- a/core/fpdfapi/page/cpdf_image.cpp
+++ b/core/fpdfapi/page/cpdf_image.cpp
@@ -83,29 +83,28 @@
 
 RetainPtr<CPDF_Dictionary> CPDF_Image::InitJPEG(
     pdfium::span<uint8_t> src_span) {
-  int32_t width;
-  int32_t height;
-  int32_t num_comps;
-  int32_t bits;
-  bool color_trans;
-  if (!fxcodec::ModuleMgr::GetInstance()->GetJpegModule()->LoadInfo(
-          src_span, &width, &height, &num_comps, &bits, &color_trans)) {
+  Optional<JpegModule::JpegImageInfo> info_opt =
+      fxcodec::ModuleMgr::GetInstance()->GetJpegModule()->LoadInfo(src_span);
+  if (!info_opt.has_value())
+    return nullptr;
+
+  const JpegModule::JpegImageInfo& info = info_opt.value();
+  if (!IsValidJpegComponent(info.num_components) ||
+      !IsValidJpegBitsPerComponent(info.bits_per_components)) {
     return nullptr;
   }
-  if (!IsValidJpegComponent(num_comps) || !IsValidJpegBitsPerComponent(bits))
-    return nullptr;
 
   auto pDict = m_pDocument->New<CPDF_Dictionary>();
   pDict->SetNewFor<CPDF_Name>("Type", "XObject");
   pDict->SetNewFor<CPDF_Name>("Subtype", "Image");
-  pDict->SetNewFor<CPDF_Number>("Width", width);
-  pDict->SetNewFor<CPDF_Number>("Height", height);
+  pDict->SetNewFor<CPDF_Number>("Width", info.width);
+  pDict->SetNewFor<CPDF_Number>("Height", info.height);
   const char* csname = nullptr;
-  if (num_comps == 1) {
+  if (info.num_components == 1) {
     csname = "DeviceGray";
-  } else if (num_comps == 3) {
+  } else if (info.num_components == 3) {
     csname = "DeviceRGB";
-  } else if (num_comps == 4) {
+  } else if (info.num_components == 4) {
     csname = "DeviceCMYK";
     CPDF_Array* pDecode = pDict->SetNewFor<CPDF_Array>("Decode");
     for (int n = 0; n < 4; n++) {
@@ -114,16 +113,16 @@
     }
   }
   pDict->SetNewFor<CPDF_Name>("ColorSpace", csname);
-  pDict->SetNewFor<CPDF_Number>("BitsPerComponent", bits);
+  pDict->SetNewFor<CPDF_Number>("BitsPerComponent", info.bits_per_components);
   pDict->SetNewFor<CPDF_Name>("Filter", "DCTDecode");
-  if (!color_trans) {
+  if (!info.color_transform) {
     CPDF_Dictionary* pParms =
         pDict->SetNewFor<CPDF_Dictionary>(pdfium::stream::kDecodeParms);
     pParms->SetNewFor<CPDF_Number>("ColorTransform", 0);
   }
   m_bIsMask = false;
-  m_Width = width;
-  m_Height = height;
+  m_Width = info.width;
+  m_Height = info.height;
   if (!m_pStream)
     m_pStream = pdfium::MakeRetain<CPDF_Stream>();
   return pDict;
diff --git a/core/fxcodec/jpeg/jpegmodule.cpp b/core/fxcodec/jpeg/jpegmodule.cpp
index b582c7f..72925f1 100644
--- a/core/fxcodec/jpeg/jpegmodule.cpp
+++ b/core/fxcodec/jpeg/jpegmodule.cpp
@@ -42,13 +42,13 @@
   CJpegContext();
   ~CJpegContext() override;
 
-  jmp_buf* GetJumpMark() { return &m_JumpMark; }
+  jmp_buf& GetJumpMark() { return m_JumpMark; }
 
   jmp_buf m_JumpMark;
-  jpeg_decompress_struct m_Info;
-  jpeg_error_mgr m_ErrMgr;
-  jpeg_source_mgr m_SrcMgr;
-  unsigned int m_SkipSize;
+  jpeg_decompress_struct m_Info = {};
+  jpeg_error_mgr m_ErrMgr = {};
+  jpeg_source_mgr m_SrcMgr = {};
+  unsigned int m_SkipSize = 0;
   void* (*m_AllocFunc)(unsigned int);
   void (*m_FreeFunc)(void*);
 };
@@ -188,19 +188,16 @@
 }
 
 CJpegContext::CJpegContext()
-    : m_SkipSize(0), m_AllocFunc(jpeg_alloc_func), m_FreeFunc(jpeg_free_func) {
-  memset(&m_Info, 0, sizeof(m_Info));
+    : m_AllocFunc(jpeg_alloc_func), m_FreeFunc(jpeg_free_func) {
   m_Info.client_data = this;
   m_Info.err = &m_ErrMgr;
 
-  memset(&m_ErrMgr, 0, sizeof(m_ErrMgr));
   m_ErrMgr.error_exit = error_fatal1;
   m_ErrMgr.emit_message = error_do_nothing1;
   m_ErrMgr.output_message = error_do_nothing;
   m_ErrMgr.format_message = error_do_nothing2;
   m_ErrMgr.reset_error_mgr = error_do_nothing;
 
-  memset(&m_SrcMgr, 0, sizeof(m_SrcMgr));
   m_SrcMgr.init_source = src_do_nothing;
   m_SrcMgr.term_source = src_do_nothing;
   m_SrcMgr.skip_input_data = src_skip_data1;
@@ -495,14 +492,14 @@
   return std::move(pDecoder);
 }
 
-bool JpegModule::LoadInfo(pdfium::span<const uint8_t> src_span,
-                          int* width,
-                          int* height,
-                          int* num_components,
-                          int* bits_per_components,
-                          bool* color_transform) {
-  return JpegLoadInfo(src_span, width, height, num_components,
-                      bits_per_components, color_transform);
+Optional<JpegModule::JpegImageInfo> JpegModule::LoadInfo(
+    pdfium::span<const uint8_t> src_span) {
+  JpegImageInfo info;
+  if (!JpegLoadInfo(src_span, &info.width, &info.height, &info.num_components,
+                    &info.bits_per_components, &info.color_transform)) {
+    return pdfium::nullopt;
+  }
+  return info;
 }
 
 std::unique_ptr<ModuleIface::Context> JpegModule::Start() {
@@ -578,7 +575,7 @@
   return static_cast<FX_FILESIZE>(ctx->m_SrcMgr.bytes_in_buffer);
 }
 
-jmp_buf* JpegModule::GetJumpMark(Context* pContext) {
+jmp_buf& JpegModule::GetJumpMark(Context* pContext) {
   return static_cast<CJpegContext*>(pContext)->GetJumpMark();
 }
 
diff --git a/core/fxcodec/jpeg/jpegmodule.h b/core/fxcodec/jpeg/jpegmodule.h
index 353de7f..0ecf204 100644
--- a/core/fxcodec/jpeg/jpegmodule.h
+++ b/core/fxcodec/jpeg/jpegmodule.h
@@ -12,6 +12,7 @@
 
 #include "build/build_config.h"
 #include "core/fxcodec/codec_module_iface.h"
+#include "third_party/base/optional.h"
 #include "third_party/base/span.h"
 
 class CFX_DIBBase;
@@ -23,6 +24,14 @@
 
 class JpegModule final : public ModuleIface {
  public:
+  struct JpegImageInfo {
+    int width;
+    int height;
+    int num_components;
+    int bits_per_components;
+    bool color_transform;
+  };
+
   std::unique_ptr<ScanlineDecoder> CreateDecoder(
       pdfium::span<const uint8_t> src_span,
       int width,
@@ -36,13 +45,8 @@
              RetainPtr<CFX_CodecMemory> codec_memory,
              CFX_DIBAttribute* pAttribute) override;
 
-  jmp_buf* GetJumpMark(Context* pContext);
-  bool LoadInfo(pdfium::span<const uint8_t> src_span,
-                int* width,
-                int* height,
-                int* num_components,
-                int* bits_per_components,
-                bool* color_transform);
+  jmp_buf& GetJumpMark(Context* pContext);
+  Optional<JpegImageInfo> LoadInfo(pdfium::span<const uint8_t> src_span);
 
   std::unique_ptr<Context> Start();
 
diff --git a/core/fxcodec/progressivedecoder.cpp b/core/fxcodec/progressivedecoder.cpp
index 7582e16..e948b39 100644
--- a/core/fxcodec/progressivedecoder.cpp
+++ b/core/fxcodec/progressivedecoder.cpp
@@ -1025,7 +1025,7 @@
 
   // Setting jump marker before calling ReadHeader, since a longjmp to
   // the marker indicates a fatal error.
-  if (setjmp(*pJpegModule->GetJumpMark(m_pJpegContext.get())) == -1) {
+  if (setjmp(pJpegModule->GetJumpMark(m_pJpegContext.get())) == -1) {
     m_pJpegContext.reset();
     m_status = FXCODEC_STATUS_ERR_FORMAT;
     return false;
@@ -1061,7 +1061,7 @@
   GetDownScale(down_scale);
   // Setting jump marker before calling StartScanLine, since a longjmp to
   // the marker indicates a fatal error.
-  if (setjmp(*pJpegModule->GetJumpMark(m_pJpegContext.get())) == -1) {
+  if (setjmp(pJpegModule->GetJumpMark(m_pJpegContext.get())) == -1) {
     m_pJpegContext.reset();
     m_status = FXCODEC_STATUS_ERROR;
     return FXCODEC_STATUS_ERROR;
@@ -1105,7 +1105,7 @@
   JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule();
   // Setting jump marker before calling ReadScanLine, since a longjmp to
   // the marker indicates a fatal error.
-  if (setjmp(*pJpegModule->GetJumpMark(m_pJpegContext.get())) == -1) {
+  if (setjmp(pJpegModule->GetJumpMark(m_pJpegContext.get())) == -1) {
     m_pJpegContext.reset();
     m_status = FXCODEC_STATUS_ERROR;
     return FXCODEC_STATUS_ERROR;