Index: 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 1ec912ebeec82f8c788beb697ab523c8451335fd..acf51de1eafcfc39c3845451a2438b78754756bf 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; |
} |