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