Index: core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp |
diff --git a/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp b/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp |
index c6e48e74a2cc9ba20a8177a4ef6cf26fb4deac9a..026247c3aa606d41be252e678274626b60c7fda2 100644 |
--- a/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp |
+++ b/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp |
@@ -374,30 +374,25 @@ FX_BOOL CPDF_Parser::LoadAllCrossRefV4(FX_FILESIZE xrefpos) { |
CFX_FileSizeArray CrossRefList, XRefStreamList; |
CrossRefList.Add(xrefpos); |
XRefStreamList.Add(GetDirectInteger(m_pTrailer, "XRefStm")); |
- if (!CheckDirectType(m_pTrailer, "Prev", PDFOBJ_NUMBER)) { |
- return FALSE; |
- } |
- FX_FILESIZE newxrefpos = GetDirectInteger(m_pTrailer, "Prev"); |
- if (newxrefpos == xrefpos) { |
- return FALSE; |
- } |
- xrefpos = newxrefpos; |
+ |
+ std::set<FX_FILESIZE> seen_xrefpos; |
+ seen_xrefpos.insert(xrefpos); |
+ // When |m_pTrailer| doesn't have Prev entry or Prev entry value is not |
+ // numerical, GetDirectInteger() returns 0. Loading will end. |
+ xrefpos = GetDirectInteger(m_pTrailer, "Prev"); |
while (xrefpos) { |
+ // Check for circular references. |
+ if (pdfium::ContainsKey(seen_xrefpos, xrefpos)) |
+ return FALSE; |
+ seen_xrefpos.insert(xrefpos); |
CrossRefList.InsertAt(0, xrefpos); |
LoadCrossRefV4(xrefpos, 0, TRUE); |
std::unique_ptr<CPDF_Dictionary, ReleaseDeleter<CPDF_Dictionary>> pDict( |
LoadTrailerV4()); |
if (!pDict) |
return FALSE; |
+ xrefpos = GetDirectInteger(pDict.get(), "Prev"); |
- if (!CheckDirectType(pDict.get(), "Prev", PDFOBJ_NUMBER)) |
- return FALSE; |
- |
- newxrefpos = GetDirectInteger(pDict.get(), "Prev"); |
- if (newxrefpos == xrefpos) |
- return FALSE; |
- |
- xrefpos = newxrefpos; |
XRefStreamList.InsertAt(0, pDict->GetInteger("XRefStm")); |
m_Trailers.Add(pDict.release()); |
} |
@@ -423,17 +418,26 @@ FX_BOOL CPDF_Parser::LoadLinearizedAllCrossRefV4(FX_FILESIZE xrefpos, |
CFX_FileSizeArray CrossRefList, XRefStreamList; |
CrossRefList.Add(xrefpos); |
XRefStreamList.Add(GetDirectInteger(m_pTrailer, "XRefStm")); |
+ |
+ std::set<FX_FILESIZE> seen_xrefpos; |
+ seen_xrefpos.insert(xrefpos); |
xrefpos = GetDirectInteger(m_pTrailer, "Prev"); |
while (xrefpos) { |
+ // Check for circular references. |
+ if (pdfium::ContainsKey(seen_xrefpos, xrefpos)) |
+ return FALSE; |
+ seen_xrefpos.insert(xrefpos); |
CrossRefList.InsertAt(0, xrefpos); |
LoadCrossRefV4(xrefpos, 0, TRUE); |
- CPDF_Dictionary* pDict = LoadTrailerV4(); |
+ std::unique_ptr<CPDF_Dictionary, ReleaseDeleter<CPDF_Dictionary>> pDict( |
+ LoadTrailerV4()); |
if (!pDict) { |
return FALSE; |
} |
- xrefpos = GetDirectInteger(pDict, "Prev"); |
+ xrefpos = GetDirectInteger(pDict.get(), "Prev"); |
+ |
XRefStreamList.InsertAt(0, pDict->GetInteger("XRefStm")); |
- m_Trailers.Add(pDict); |
+ m_Trailers.Add(pDict.release()); |
} |
for (int32_t i = 1; i < CrossRefList.GetSize(); i++) |
if (!LoadCrossRefV4(CrossRefList[i], XRefStreamList[i], FALSE)) { |