Deduplicate code in CPDF_Parser and rename some methods

- Refactor common code into FindAllCrossReferenceTablesAndStream()
- Rename LoadAllCrossRefTable() to LoadAllCrossRefTables()
- Rename LoadAllCrossRefStream() to LoadAllCrossRefStreams()

Change-Id: Iced6b5b84f4c9a1a013975738f1d47fe0fc2cd3c
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/118331
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Thomas Sepez <tsepez@google.com>
diff --git a/core/fpdfapi/parser/cpdf_data_avail.cpp b/core/fpdfapi/parser/cpdf_data_avail.cpp
index 5c1fb43..0850f7e 100644
--- a/core/fpdfapi/parser/cpdf_data_avail.cpp
+++ b/core/fpdfapi/parser/cpdf_data_avail.cpp
@@ -195,9 +195,9 @@
       return false;
   }
 
-  if (!m_parser.LoadAllCrossRefTable(
+  if (!m_parser.LoadAllCrossRefTables(
           m_pCrossRefAvail->last_crossref_offset()) &&
-      !m_parser.LoadAllCrossRefStream(
+      !m_parser.LoadAllCrossRefStreams(
           m_pCrossRefAvail->last_crossref_offset())) {
     m_internalStatus = InternalStatus::kLoadAllFile;
     return false;
diff --git a/core/fpdfapi/parser/cpdf_parser.cpp b/core/fpdfapi/parser/cpdf_parser.cpp
index dcdcb7b..61861de 100644
--- a/core/fpdfapi/parser/cpdf_parser.cpp
+++ b/core/fpdfapi/parser/cpdf_parser.cpp
@@ -250,8 +250,8 @@
 
   m_LastXRefOffset = ParseStartXRef();
   if (m_LastXRefOffset >= kPDFHeaderSize) {
-    if (!LoadAllCrossRefTable(m_LastXRefOffset) &&
-        !LoadAllCrossRefStream(m_LastXRefOffset)) {
+    if (!LoadAllCrossRefTables(m_LastXRefOffset) &&
+        !LoadAllCrossRefStreams(m_LastXRefOffset)) {
       if (!RebuildCrossRef())
         return FORMAT_ERROR;
 
@@ -372,7 +372,7 @@
   return true;
 }
 
-bool CPDF_Parser::LoadAllCrossRefTable(FX_FILESIZE xref_offset) {
+bool CPDF_Parser::LoadAllCrossRefTables(FX_FILESIZE xref_offset) {
   if (!LoadCrossRefTable(xref_offset, /*skip=*/true)) {
     return false;
   }
@@ -400,39 +400,11 @@
   }
 
   // Otherwise, follow the /Prev from the trailer.
-  std::vector<FX_FILESIZE> xref_stream_list{xref_stm};
   std::vector<FX_FILESIZE> xref_list{xref_offset};
-  std::set<FX_FILESIZE> seen_xref_offset{xref_offset};
-
-  // When the trailer doesn't have Prev entry or Prev entry value is not
-  // numerical, GetDirectInteger() returns 0. Loading will end.
-  xref_offset = GetTrailer()->GetDirectIntegerFor("Prev");
-  while (xref_offset > 0) {
-    // Check for circular references.
-    if (pdfium::Contains(seen_xref_offset, xref_offset)) {
-      return false;
-    }
-
-    seen_xref_offset.insert(xref_offset);
-    xref_list.insert(xref_list.begin(), xref_offset);
-
-    // SLOW ...
-    LoadCrossRefTable(xref_offset, /*skip=*/true);
-
-    RetainPtr<CPDF_Dictionary> trailer_dict = LoadTrailer();
-    if (!trailer_dict) {
-      return false;
-    }
-
-    xref_offset = trailer_dict->GetDirectIntegerFor("Prev");
-    xref_stm = trailer_dict->GetIntegerFor("XRefStm");
-    xref_stream_list.insert(xref_stream_list.begin(), xref_stm);
-
-    // SLOW ...
-    m_CrossRefTable = CPDF_CrossRefTable::MergeUp(
-        std::make_unique<CPDF_CrossRefTable>(std::move(trailer_dict),
-                                             kNoTrailerObjectNumber),
-        std::move(m_CrossRefTable));
+  std::vector<FX_FILESIZE> xref_stream_list{xref_stm};
+  if (!FindAllCrossReferenceTablesAndStream(xref_offset, xref_list,
+                                            xref_stream_list)) {
+    return false;
   }
 
   for (size_t i = 0; i < xref_list.size(); ++i) {
@@ -469,11 +441,11 @@
   // first-page trailer, as the caller already did that and passed it in as
   // |main_xref_offset|.
   FX_FILESIZE xref_stm = GetTrailer()->GetDirectIntegerFor("XRefStm");
-  std::vector<FX_FILESIZE> xref_stream_list{xref_stm};
   std::vector<FX_FILESIZE> xref_list{main_xref_offset};
-  std::set<FX_FILESIZE> seen_xref_offset{main_xref_offset};
+  std::vector<FX_FILESIZE> xref_stream_list{xref_stm};
 
-  // Merge the trailers.
+  // Merge the trailers. Now GetTrailer() returns the merged trailer, where
+  // /Prev is from the main-trailer.
   m_CrossRefTable = CPDF_CrossRefTable::MergeUp(
       std::make_unique<CPDF_CrossRefTable>(std::move(main_trailer),
                                            kNoTrailerObjectNumber),
@@ -482,35 +454,9 @@
   // Ignore /Prev for hybrid-reference files.
   // See ISO 32000-1:2008 spec, table 17.
   if (!xref_stm) {
-    // Now GetTrailer() returns the merged trailer, where /Prev is from the
-    // main-trailer.
-    FX_FILESIZE xref_offset = GetTrailer()->GetDirectIntegerFor("Prev");
-    while (xref_offset > 0) {
-      // Check for circular references.
-      if (pdfium::Contains(seen_xref_offset, xref_offset)) {
-        return false;
-      }
-
-      seen_xref_offset.insert(xref_offset);
-      xref_list.insert(xref_list.begin(), xref_offset);
-
-      // SLOW ...
-      LoadCrossRefTable(xref_offset, /*skip=*/true);
-
-      RetainPtr<CPDF_Dictionary> trailer_dict = LoadTrailer();
-      if (!trailer_dict) {
-        return false;
-      }
-
-      xref_offset = trailer_dict->GetDirectIntegerFor("Prev");
-      xref_stm = trailer_dict->GetIntegerFor("XRefStm");
-      xref_stream_list.insert(xref_stream_list.begin(), xref_stm);
-
-      // SLOW ...
-      m_CrossRefTable = CPDF_CrossRefTable::MergeUp(
-          std::make_unique<CPDF_CrossRefTable>(std::move(trailer_dict),
-                                               kNoTrailerObjectNumber),
-          std::move(m_CrossRefTable));
+    if (!FindAllCrossReferenceTablesAndStream(main_xref_offset, xref_list,
+                                              xref_stream_list)) {
+      return false;
     }
   }
 
@@ -689,7 +635,7 @@
   }
 }
 
-bool CPDF_Parser::LoadAllCrossRefStream(FX_FILESIZE xref_offset) {
+bool CPDF_Parser::LoadAllCrossRefStreams(FX_FILESIZE xref_offset) {
   if (!LoadCrossRefStream(&xref_offset, /*is_main_xref=*/true)) {
     return false;
   }
@@ -732,6 +678,45 @@
   return true;
 }
 
+bool CPDF_Parser::FindAllCrossReferenceTablesAndStream(
+    FX_FILESIZE main_xref_offset,
+    std::vector<FX_FILESIZE>& xref_list,
+    std::vector<FX_FILESIZE>& xref_stream_list) {
+  std::set<FX_FILESIZE> seen_xref_offset{main_xref_offset};
+
+  // When the trailer doesn't have Prev entry or Prev entry value is not
+  // numerical, GetDirectInteger() returns 0. Loading will end.
+  FX_FILESIZE xref_offset = GetTrailer()->GetDirectIntegerFor("Prev");
+  while (xref_offset > 0) {
+    // Check for circular references.
+    if (pdfium::Contains(seen_xref_offset, xref_offset)) {
+      return false;
+    }
+
+    seen_xref_offset.insert(xref_offset);
+    xref_list.insert(xref_list.begin(), xref_offset);
+
+    // SLOW ...
+    LoadCrossRefTable(xref_offset, /*skip=*/true);
+
+    RetainPtr<CPDF_Dictionary> trailer_dict = LoadTrailer();
+    if (!trailer_dict) {
+      return false;
+    }
+
+    xref_offset = trailer_dict->GetDirectIntegerFor("Prev");
+    xref_stream_list.insert(xref_stream_list.begin(),
+                            trailer_dict->GetIntegerFor("XRefStm"));
+
+    // SLOW ...
+    m_CrossRefTable = CPDF_CrossRefTable::MergeUp(
+        std::make_unique<CPDF_CrossRefTable>(std::move(trailer_dict),
+                                             kNoTrailerObjectNumber),
+        std::move(m_CrossRefTable));
+  }
+  return true;
+}
+
 bool CPDF_Parser::RebuildCrossRef() {
   auto cross_ref_table = std::make_unique<CPDF_CrossRefTable>();
 
diff --git a/core/fpdfapi/parser/cpdf_parser.h b/core/fpdfapi/parser/cpdf_parser.h
index aaed8bc..26abc7d 100644
--- a/core/fpdfapi/parser/cpdf_parser.h
+++ b/core/fpdfapi/parser/cpdf_parser.h
@@ -143,9 +143,13 @@
     CPDF_CrossRefTable::ObjectInfo info;
   };
 
-  bool LoadAllCrossRefTable(FX_FILESIZE xref_offset);
-  bool LoadAllCrossRefStream(FX_FILESIZE xref_offset);
+  bool LoadAllCrossRefTables(FX_FILESIZE xref_offset);
+  bool LoadAllCrossRefStreams(FX_FILESIZE xref_offset);
   bool LoadAllSecondaryCrossRefStreams(FX_FILESIZE xref_offset);
+  bool FindAllCrossReferenceTablesAndStream(
+      FX_FILESIZE main_xref_offset,
+      std::vector<FX_FILESIZE>& xref_list,
+      std::vector<FX_FILESIZE>& xref_stream_list);
   bool LoadCrossRefStream(FX_FILESIZE* pos, bool is_main_xref);
   void ProcessCrossRefStreamEntry(pdfium::span<const uint8_t> entry_span,
                                   pdfium::span<const uint32_t> field_widths,