Check the first page xref size when parsing linearized PDFs.

When parsing linearized PDFs, the first page's cross-reference table
objects may not match up with the trailer's size entry. The current
behavior for handling PDFs with this error is to trust the trailer's
size entry, but that leads to incorrect PDF parsing, whereas other PDF
readers handle this error correctly.

Fix this issue by changing CPDF_Parser::StartLinearizedParse() to check
for the error. In which case, rebuild the cross-reference table.

To test this, add a deliberately bad bug_1287409.pdf. The steps to
create this PDF is as follows:

1) Run: qpdf --linearize rectangles.pdf bug_1287409.pdf
2) Deliberately change the trailer's /Size entry in a text editor.

The existing CPDF_Parser behavior results in an unknown /MediaBox for
the first page, and the page size will default to 612x792. With this
fix, the page size will be correctly set to 200x300.

Bug: chromium:1287409
Change-Id: I4f31a1775521ec43b02fb4bf88c75fe09f087815
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/103473
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: K. Moon <kmoon@chromium.org>
diff --git a/core/fpdfapi/parser/cpdf_parser.cpp b/core/fpdfapi/parser/cpdf_parser.cpp
index 65de611..f41dd8d 100644
--- a/core/fpdfapi/parser/cpdf_parser.cpp
+++ b/core/fpdfapi/parser/cpdf_parser.cpp
@@ -1058,8 +1058,14 @@
 
     m_CrossRefTable->SetTrailer(std::move(trailer));
     const int32_t xrefsize = GetTrailer()->GetDirectIntegerFor("Size");
-    if (xrefsize > 0)
-      ShrinkObjectMap(xrefsize);
+    if (xrefsize > 0) {
+      // Check if `xrefsize` is correct. If it is incorrect, give up and rebuild
+      // the xref table.
+      const uint32_t expected_last_obj_num = xrefsize - 1;
+      if (GetLastObjNum() != expected_last_obj_num && !RebuildCrossRef()) {
+        return FORMAT_ERROR;
+      }
+    }
   }
 
   Error eRet = SetEncryptHandler();
diff --git a/testing/resources/pixel/bug_1287409.pdf b/testing/resources/pixel/bug_1287409.pdf
new file mode 100644
index 0000000..3973822
--- /dev/null
+++ b/testing/resources/pixel/bug_1287409.pdf
Binary files differ
diff --git a/testing/resources/pixel/bug_1287409_expected.pdf.0.png b/testing/resources/pixel/bug_1287409_expected.pdf.0.png
new file mode 100644
index 0000000..60507e1
--- /dev/null
+++ b/testing/resources/pixel/bug_1287409_expected.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1287409_expected_skia.pdf.0.png b/testing/resources/pixel/bug_1287409_expected_skia.pdf.0.png
new file mode 100644
index 0000000..0b00554
--- /dev/null
+++ b/testing/resources/pixel/bug_1287409_expected_skia.pdf.0.png
Binary files differ