Fix LoadLinearizedAllCrossRefV4() to work properly.

In CPDF_Parser, for linearized PDFs, LoadLinearizedAllCrossRefV4() has
to read the first-page cross-reference table, as well as the main xref
table. It has to read the associated trailers for those xref tables as
well, and also merge them.

Currently, LoadLinearizedAllCrossRefV4() does not do this correctly. It
loads the main trailer, and merges it with the first-page trailer before
ever reading from the first-page trailer. Therefore, when it does read
/XRefStm for the first time, it will always fail and get values of 0.

Fix this by reading from the first-page trailer first, and then merging
the two trailers. Add comments in the function to explain what is
happening.

Bug: pdfium:1335
Change-Id: Iab5ac79d8e0c25c72519075179b001fc19cece51
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/62551
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 4a89374..a564ac8 100644
--- a/core/fpdfapi/parser/cpdf_parser.cpp
+++ b/core/fpdfapi/parser/cpdf_parser.cpp
@@ -352,23 +352,29 @@
   if (!LoadCrossRefV4(main_xref_offset, false))
     return false;
 
-  RetainPtr<CPDF_Dictionary> trailer = LoadTrailerV4();
-  if (!trailer)
+  RetainPtr<CPDF_Dictionary> main_trailer = LoadTrailerV4();
+  if (!main_trailer)
     return false;
 
-  m_CrossRefTable = CPDF_CrossRefTable::MergeUp(
-      pdfium::MakeUnique<CPDF_CrossRefTable>(std::move(trailer)),
-      std::move(m_CrossRefTable));
-
-  int32_t xrefsize = GetDirectInteger(GetTrailer(), "Size");
-  if (xrefsize == 0)
+  // GetTrailer() currently returns the first-page trailer.
+  if (GetDirectInteger(GetTrailer(), "Size") == 0)
     return false;
 
+  // Read /XRefStm from the first-page trailer. No need to read /Prev for the
+  // first-page trailer, as the caller already did that and passed it in as
+  // |main_xref_offset|.
   std::vector<FX_FILESIZE> xref_stream_list{
       GetDirectInteger(GetTrailer(), "XRefStm")};
   std::vector<FX_FILESIZE> xref_list{main_xref_offset};
   std::set<FX_FILESIZE> seen_xref_offset{main_xref_offset};
 
+  // Merge the trailers.
+  m_CrossRefTable = CPDF_CrossRefTable::MergeUp(
+      pdfium::MakeUnique<CPDF_CrossRefTable>(std::move(main_trailer)),
+      std::move(m_CrossRefTable));
+
+  // Now GetTrailer() returns the merged trailer, where /Prev is from the
+  // main-trailer.
   FX_FILESIZE xref_offset = GetDirectInteger(GetTrailer(), "Prev");
   while (xref_offset) {
     // Check for circular references.