Validate more image values in CPDF_DIBBase.

Change-Id: Ia5f72e6397ee959d897a945c4069f47c494b5511
Reviewed-on: https://pdfium-review.googlesource.com/42870
Commit-Queue: Ryan Harrison <rharrison@chromium.org>
Reviewed-by: Ryan Harrison <rharrison@chromium.org>
diff --git a/core/fpdfapi/page/cpdf_image.cpp b/core/fpdfapi/page/cpdf_image.cpp
index 85e7d8a..f7eec13 100644
--- a/core/fpdfapi/page/cpdf_image.cpp
+++ b/core/fpdfapi/page/cpdf_image.cpp
@@ -32,18 +32,16 @@
 #include "third_party/base/numerics/safe_conversions.h"
 #include "third_party/base/ptr_util.h"
 
-namespace {
-
-bool IsValidJpegComponent(int32_t comps) {
+// static
+bool CPDF_Image::IsValidJpegComponent(int32_t comps) {
   return comps == 1 || comps == 3 || comps == 4;
 }
 
-bool IsValidJpegBitsPerComponent(int32_t bpc) {
+// static
+bool CPDF_Image::IsValidJpegBitsPerComponent(int32_t bpc) {
   return bpc == 1 || bpc == 2 || bpc == 4 || bpc == 8 || bpc == 16;
 }
 
-}  // namespace
-
 CPDF_Image::CPDF_Image(CPDF_Document* pDoc) : m_pDocument(pDoc) {}
 
 CPDF_Image::CPDF_Image(CPDF_Document* pDoc,
diff --git a/core/fpdfapi/page/cpdf_image.h b/core/fpdfapi/page/cpdf_image.h
index f775221..b463671 100644
--- a/core/fpdfapi/page/cpdf_image.h
+++ b/core/fpdfapi/page/cpdf_image.h
@@ -28,6 +28,9 @@
   template <typename T, typename... Args>
   friend RetainPtr<T> pdfium::MakeRetain(Args&&... args);
 
+  static bool IsValidJpegComponent(int32_t comps);
+  static bool IsValidJpegBitsPerComponent(int32_t bpc);
+
   void ConvertStreamToIndirectObject();
 
   CPDF_Dictionary* GetDict() const;
diff --git a/core/fpdfapi/render/cpdf_dibbase.cpp b/core/fpdfapi/render/cpdf_dibbase.cpp
index d342a99..3557672 100644
--- a/core/fpdfapi/render/cpdf_dibbase.cpp
+++ b/core/fpdfapi/render/cpdf_dibbase.cpp
@@ -54,7 +54,12 @@
   return pSrc[pos / 8] & (1 << (7 - pos % 8));
 }
 
-bool IsAllowedBPCValue(int bpc) {
+// Just to sanity check and filter out obvious bad values.
+bool IsMaybeValidBitsPerComponent(int bpc) {
+  return bpc >= 0 && bpc <= 16;
+}
+
+bool IsAllowedBitsPerComponent(int bpc) {
   return bpc == 1 || bpc == 2 || bpc == 4 || bpc == 8 || bpc == 16;
 }
 
@@ -338,6 +343,9 @@
 bool CPDF_DIBBase::LoadColorInfo(const CPDF_Dictionary* pFormResources,
                                  const CPDF_Dictionary* pPageResources) {
   m_bpc_orig = m_pDict->GetIntegerFor("BitsPerComponent");
+  if (!IsMaybeValidBitsPerComponent(m_bpc_orig))
+    return false;
+
   if (m_pDict->GetIntegerFor("ImageMask"))
     m_bImageMask = true;
 
@@ -517,6 +525,10 @@
                              &bTransform)) {
     return false;
   }
+  if (!CPDF_Image::IsValidJpegComponent(comps) ||
+      !CPDF_Image::IsValidJpegBitsPerComponent(bpc)) {
+    return false;
+  }
 
   if (m_nComponents == static_cast<uint32_t>(comps)) {
     m_bpc = bpc;
@@ -719,10 +731,18 @@
   if (!m_pColorSpace || m_Family == PDFCS_PATTERN)
     return;
 
-  if (m_bpc == 0 || m_bpc * m_nComponents > 8)
+  if (m_bpc == 0)
     return;
 
-  if (m_bpc * m_nComponents == 1) {
+  // Use FX_SAFE_UINT32 just to be on the safe side, in case |m_bpc| or
+  // |m_nComponents| somehow gets a bad value.
+  FX_SAFE_UINT32 safe_bits = m_bpc;
+  safe_bits *= m_nComponents;
+  uint32_t bits = safe_bits.ValueOrDefault(255);
+  if (bits > 8)
+    return;
+
+  if (bits == 1) {
     if (m_bDefaultDecode &&
         (m_Family == PDFCS_DEVICEGRAY || m_Family == PDFCS_DEVICERGB)) {
       return;
@@ -759,7 +779,7 @@
     return;
   }
 
-  int palette_count = 1 << (m_bpc * m_nComponents);
+  int palette_count = 1 << bits;
   // Using at least 16 elements due to the call m_pColorSpace->GetRGB().
   std::vector<float> color_values(std::max(m_nComponents, 16u));
   for (int i = 0; i < palette_count; i++) {
@@ -817,7 +837,7 @@
     }
   }
 
-  if (!IsAllowedBPCValue(m_bpc))
+  if (!IsAllowedBitsPerComponent(m_bpc))
     m_bpc = 0;
 }