From 90c964fb069bfa9934493481f8ccfefef9c3b3fe Mon Sep 17 00:00:00 2001 From: weili Date: Fri, 22 Apr 2016 15:25:14 -0700 Subject: Add a simple check for V4 cross reference table Some unknown software generates cross reference table with the claimed object numbers are all off by one. Add a simple verification function to detect this scenario, thus have a chance to rebuild the correct cross reference table. To avoid unnecessary checks and potiential performance hit, we only check for the very first non free entry. BUG=602650 Review URL: https://codereview.chromium.org/1910063004 --- core/fpdfapi/fpdf_parser/cpdf_parser.cpp | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'core/fpdfapi/fpdf_parser/cpdf_parser.cpp') diff --git a/core/fpdfapi/fpdf_parser/cpdf_parser.cpp b/core/fpdfapi/fpdf_parser/cpdf_parser.cpp index 1ec912ebee..acf51de1ea 100644 --- a/core/fpdfapi/fpdf_parser/cpdf_parser.cpp +++ b/core/fpdfapi/fpdf_parser/cpdf_parser.cpp @@ -316,6 +316,32 @@ FX_FILESIZE CPDF_Parser::GetObjectOffset(uint32_t objnum) const { return 0; } +// Ideally, all the cross reference entries should be verified. +// In reality, we rarely see well-formed cross references don't match +// with the objects. crbug/602650 showed a case where object numbers +// in the cross reference table are all off by one. +bool CPDF_Parser::VerifyCrossRefV4() { + for (const auto& it : m_ObjectInfo) { + if (it.second.pos == 0) + continue; + // Find the first non-zero position. + FX_FILESIZE SavedPos = m_pSyntax->SavePos(); + m_pSyntax->RestorePos(it.second.pos); + bool is_num = false; + CFX_ByteString num_str = m_pSyntax->GetNextWord(&is_num); + m_pSyntax->RestorePos(SavedPos); + if (!is_num || num_str.IsEmpty() || + FXSYS_atoui(num_str.c_str()) != it.first) { + // If the object number read doesn't match the one stored, + // something is wrong with the cross reference table. + return false; + } else { + return true; + } + } + return true; +} + FX_BOOL CPDF_Parser::LoadAllCrossRefV4(FX_FILESIZE xrefpos) { if (!LoadCrossRefV4(xrefpos, 0, TRUE)) return FALSE; @@ -366,6 +392,8 @@ FX_BOOL CPDF_Parser::LoadAllCrossRefV4(FX_FILESIZE xrefpos) { for (size_t i = 0; i < CrossRefList.size(); ++i) { if (!LoadCrossRefV4(CrossRefList[i], XRefStreamList[i], FALSE)) return FALSE; + if (i == 0 && !VerifyCrossRefV4()) + return FALSE; } return TRUE; } -- cgit v1.2.3