Better validate Prev entries in trailers.

Prev entries are defined as "The byte offset from the beginning of the
file" so they should not be negative.

Simplify another FX_SAFE_FILESIZE usage along the way.

Change-Id: I596d708ff5a08abcaf9688edbc9e5715b6a30119
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/60970
Reviewed-by: Henrique Nakashima <hnakashima@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/parser/cpdf_data_avail.cpp b/core/fpdfapi/parser/cpdf_data_avail.cpp
index df759a7..457ae61 100644
--- a/core/fpdfapi/parser/cpdf_data_avail.cpp
+++ b/core/fpdfapi/parser/cpdf_data_avail.cpp
@@ -748,21 +748,22 @@
   }
 
   if (!m_bMainXRefLoadTried) {
-    const FX_SAFE_FILESIZE main_xref_offset =
+    const FX_SAFE_FILESIZE prev =
         m_pDocument->GetParser()->GetTrailer()->GetIntegerFor("Prev");
-    if (!main_xref_offset.IsValid())
+    const FX_FILESIZE main_xref_offset = prev.ValueOrDefault(-1);
+    if (main_xref_offset < 0)
       return DataError;
 
-    if (main_xref_offset.ValueOrDie() == 0)
+    if (main_xref_offset == 0)
       return DataAvailable;
 
     FX_SAFE_SIZE_T data_size = m_dwFileLen;
-    data_size -= main_xref_offset.ValueOrDie();
+    data_size -= main_xref_offset;
     if (!data_size.IsValid())
       return DataError;
 
     if (!GetValidator()->CheckDataRangeAndRequestIfUnavailable(
-            main_xref_offset.ValueOrDie(), data_size.ValueOrDie()))
+            main_xref_offset, data_size.ValueOrDie()))
       return DataNotAvailable;
 
     CPDF_Parser::Error eRet =
diff --git a/core/fpdfapi/parser/cpdf_parser.cpp b/core/fpdfapi/parser/cpdf_parser.cpp
index 01c2a67..f8e244e 100644
--- a/core/fpdfapi/parser/cpdf_parser.cpp
+++ b/core/fpdfapi/parser/cpdf_parser.cpp
@@ -1051,19 +1051,20 @@
 }
 
 CPDF_Parser::Error CPDF_Parser::LoadLinearizedMainXRefTable() {
-  const FX_SAFE_FILESIZE main_xref_offset = GetTrailer()->GetIntegerFor("Prev");
-  if (!main_xref_offset.IsValid())
+  const FX_SAFE_FILESIZE prev = GetTrailer()->GetIntegerFor("Prev");
+  const FX_FILESIZE main_xref_offset = prev.ValueOrDefault(-1);
+  if (main_xref_offset < 0)
     return FORMAT_ERROR;
 
-  if (main_xref_offset.ValueOrDie() == 0)
+  if (main_xref_offset == 0)
     return SUCCESS;
 
   const AutoRestorer<uint32_t> save_metadata_objnum(&m_MetadataObjnum);
   m_MetadataObjnum = 0;
   m_ObjectStreamMap.clear();
 
-  if (!LoadLinearizedAllCrossRefV4(main_xref_offset.ValueOrDie()) &&
-      !LoadLinearizedAllCrossRefV5(main_xref_offset.ValueOrDie())) {
+  if (!LoadLinearizedAllCrossRefV4(main_xref_offset) &&
+      !LoadLinearizedAllCrossRefV5(main_xref_offset)) {
     m_LastXRefOffset = 0;
     return FORMAT_ERROR;
   }
diff --git a/core/fpdfapi/parser/cpdf_read_validator.cpp b/core/fpdfapi/parser/cpdf_read_validator.cpp
index 61d7d19..80e6517 100644
--- a/core/fpdfapi/parser/cpdf_read_validator.cpp
+++ b/core/fpdfapi/parser/cpdf_read_validator.cpp
@@ -21,9 +21,7 @@
 FX_FILESIZE AlignUp(FX_FILESIZE offset) {
   FX_SAFE_FILESIZE safe_result = AlignDown(offset);
   safe_result += kAlignBlockValue;
-  if (safe_result.IsValid())
-    return safe_result.ValueOrDie();
-  return offset;
+  return safe_result.ValueOrDefault(offset);
 }
 
 }  // namespace