Break off part of CPDF_Parser::LoadCrossRefV5() into another method.

Put the per-entry parsing code into ProcessCrossRefV5Entry().

Change-Id: I4fb94d7f2f65ed816f1b41f009e890647df85bea
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/86170
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfapi/parser/cpdf_parser.cpp b/core/fpdfapi/parser/cpdf_parser.cpp
index fffcac4..3a5f4fb 100644
--- a/core/fpdfapi/parser/cpdf_parser.cpp
+++ b/core/fpdfapi/parser/cpdf_parser.cpp
@@ -46,6 +46,10 @@
 // "%PDF-1.7\n"
 constexpr FX_FILESIZE kPDFHeaderSize = 9;
 
+// The required number of fields in a /W array in a cross-reference stream
+// dictionary.
+constexpr size_t kMinFieldCount = 3;
+
 struct CrossRefV5IndexEntry {
   uint32_t start_obj_num;
   uint32_t obj_count;
@@ -724,7 +728,7 @@
     dwAccWidth += field_widths[i];
   }
 
-  if (!dwAccWidth.IsValid() || field_widths.size() < 3)
+  if (!dwAccWidth.IsValid() || field_widths.size() < kMinFieldCount)
     return false;
 
   uint32_t total_width = dwAccWidth.ValueOrDie();
@@ -752,60 +756,68 @@
     if (!dwMaxObjNum.IsValid() || dwMaxObjNum.ValueOrDie() > dwV5Size)
       continue;
 
-    for (uint32_t i = 0; i < index.obj_count; i++) {
+    for (uint32_t i = 0; i < index.obj_count; ++i) {
       const uint32_t obj_num = index.start_obj_num + i;
       if (obj_num >= CPDF_Parser::kMaxObjectNumber)
         break;
 
-      ObjectType type = ObjectType::kNotCompressed;
-      pdfium::span<const uint8_t> entry_span =
-          seg_span.subspan(i * total_width, total_width);
-      if (field_widths[0]) {
-        const uint32_t cross_ref_stream_obj_type =
-            GetVarInt(entry_span.first(field_widths[0]));
-        type = GetObjectTypeFromCrossRefStreamType(cross_ref_stream_obj_type);
-        if (type == ObjectType::kNull)
-          continue;
-      }
-
-      const ObjectType existing_type = GetObjectType(obj_num);
-      if (existing_type == ObjectType::kNull) {
-        uint32_t offset =
-            GetVarInt(entry_span.subspan(field_widths[0], field_widths[1]));
-        if (pdfium::base::IsValueInRangeForNumericType<FX_FILESIZE>(offset))
-          m_CrossRefTable->AddNormal(obj_num, 0, offset);
-        continue;
-      }
-
-      if (existing_type != ObjectType::kFree)
-        continue;
-
-      if (type == ObjectType::kFree) {
-        m_CrossRefTable->SetFree(obj_num);
-        continue;
-      }
-
-      const uint32_t entry_value =
-          GetVarInt(entry_span.subspan(field_widths[0], field_widths[1]));
-      if (type == ObjectType::kNotCompressed) {
-        const uint32_t offset = entry_value;
-        if (pdfium::base::IsValueInRangeForNumericType<FX_FILESIZE>(offset))
-          m_CrossRefTable->AddNormal(obj_num, 0, offset);
-        continue;
-      }
-
-      DCHECK_EQ(type, ObjectType::kCompressed);
-      const uint32_t archive_obj_num = entry_value;
-      if (!IsValidObjectNumber(archive_obj_num))
-        continue;
-
-      m_CrossRefTable->AddCompressed(obj_num, archive_obj_num);
+      ProcessCrossRefV5Entry(seg_span.subspan(i * total_width, total_width),
+                             field_widths, obj_num);
     }
+
     segindex += index.obj_count;
   }
   return true;
 }
 
+void CPDF_Parser::ProcessCrossRefV5Entry(
+    pdfium::span<const uint8_t> entry_span,
+    pdfium::span<const uint32_t> field_widths,
+    uint32_t obj_num) {
+  DCHECK_GE(field_widths.size(), kMinFieldCount);
+  ObjectType type = ObjectType::kNotCompressed;
+  if (field_widths[0]) {
+    const uint32_t cross_ref_stream_obj_type =
+        GetVarInt(entry_span.first(field_widths[0]));
+    type = GetObjectTypeFromCrossRefStreamType(cross_ref_stream_obj_type);
+    if (type == ObjectType::kNull)
+      return;
+  }
+
+  const ObjectType existing_type = GetObjectType(obj_num);
+  if (existing_type == ObjectType::kNull) {
+    uint32_t offset =
+        GetVarInt(entry_span.subspan(field_widths[0], field_widths[1]));
+    if (pdfium::base::IsValueInRangeForNumericType<FX_FILESIZE>(offset))
+      m_CrossRefTable->AddNormal(obj_num, 0, offset);
+    return;
+  }
+
+  if (existing_type != ObjectType::kFree)
+    return;
+
+  if (type == ObjectType::kFree) {
+    m_CrossRefTable->SetFree(obj_num);
+    return;
+  }
+
+  const uint32_t entry_value =
+      GetVarInt(entry_span.subspan(field_widths[0], field_widths[1]));
+  if (type == ObjectType::kNotCompressed) {
+    const uint32_t offset = entry_value;
+    if (pdfium::base::IsValueInRangeForNumericType<FX_FILESIZE>(offset))
+      m_CrossRefTable->AddNormal(obj_num, 0, offset);
+    return;
+  }
+
+  DCHECK_EQ(type, ObjectType::kCompressed);
+  const uint32_t archive_obj_num = entry_value;
+  if (!IsValidObjectNumber(archive_obj_num))
+    return;
+
+  m_CrossRefTable->AddCompressed(obj_num, archive_obj_num);
+}
+
 const CPDF_Array* CPDF_Parser::GetIDArray() const {
   return GetTrailer() ? GetTrailer()->GetArrayFor("ID") : nullptr;
 }
diff --git a/core/fpdfapi/parser/cpdf_parser.h b/core/fpdfapi/parser/cpdf_parser.h
index 513f6a4..ba49609 100644
--- a/core/fpdfapi/parser/cpdf_parser.h
+++ b/core/fpdfapi/parser/cpdf_parser.h
@@ -146,6 +146,9 @@
   bool LoadAllCrossRefV4(FX_FILESIZE xref_offset);
   bool LoadAllCrossRefV5(FX_FILESIZE xref_offset);
   bool LoadCrossRefV5(FX_FILESIZE* pos, bool bMainXRef);
+  void ProcessCrossRefV5Entry(pdfium::span<const uint8_t> entry_span,
+                              pdfium::span<const uint32_t> field_widths,
+                              uint32_t obj_num);
   RetainPtr<CPDF_Dictionary> LoadTrailerV4();
   Error SetEncryptHandler();
   void ReleaseEncryptHandler();