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 f64ba0deb079aa28ce8827eca889e071a28783dc..bc5d3edc2bbc6bcacd66680a15110eaf64899e14 100644 |
--- a/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp |
+++ b/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp |
@@ -582,21 +582,29 @@ bool CPDF_Parser::LoadCrossRefV4(FX_FILESIZE pos, |
} |
m_Syntax.RestorePos(SavedPos + count * recordsize); |
} |
- return !streampos || LoadCrossRefV5(streampos, streampos, FALSE); |
+ return !streampos || LoadCrossRefV5(&streampos, FALSE); |
} |
FX_BOOL CPDF_Parser::LoadAllCrossRefV5(FX_FILESIZE xrefpos) { |
- if (!LoadCrossRefV5(xrefpos, xrefpos, TRUE)) { |
+ if (!LoadCrossRefV5(&xrefpos, TRUE)) { |
return FALSE; |
} |
- while (xrefpos) |
- if (!LoadCrossRefV5(xrefpos, xrefpos, FALSE)) { |
+ std::set<FX_FILESIZE> seen_xrefpos; |
+ while (xrefpos) { |
+ seen_xrefpos.insert(xrefpos); |
+ if (!LoadCrossRefV5(&xrefpos, FALSE)) { |
+ return FALSE; |
+ } |
+ // Check for circular references. |
+ if (seen_xrefpos.find(xrefpos) != seen_xrefpos.end()) { |
return FALSE; |
} |
+ } |
m_ObjectStreamMap.InitHashTable(101, FALSE); |
m_bXRefStream = TRUE; |
return TRUE; |
} |
+ |
FX_BOOL CPDF_Parser::RebuildCrossRef() { |
m_CrossRef.RemoveAll(); |
m_V5Type.RemoveAll(); |
@@ -975,10 +983,8 @@ FX_BOOL CPDF_Parser::RebuildCrossRef() { |
return m_pTrailer && m_CrossRef.GetSize() > 0; |
} |
-FX_BOOL CPDF_Parser::LoadCrossRefV5(FX_FILESIZE pos, |
- FX_FILESIZE& prev, |
- FX_BOOL bMainXRef) { |
- CPDF_Object* pObject = ParseIndirectObjectAt(m_pDocument, pos, 0, nullptr); |
+FX_BOOL CPDF_Parser::LoadCrossRefV5(FX_FILESIZE* pos, FX_BOOL bMainXRef) { |
+ CPDF_Object* pObject = ParseIndirectObjectAt(m_pDocument, *pos, 0, nullptr); |
if (!pObject) |
return FALSE; |
@@ -997,7 +1003,7 @@ FX_BOOL CPDF_Parser::LoadCrossRefV5(FX_FILESIZE pos, |
if (!pStream) |
return FALSE; |
- prev = pStream->GetDict()->GetInteger(FX_BSTRC("Prev")); |
+ *pos = pStream->GetDict()->GetInteger(FX_BSTRC("Prev")); |
int32_t size = pStream->GetDict()->GetInteger(FX_BSTRC("Size")); |
if (size < 0) { |
pStream->Release(); |
@@ -1563,7 +1569,7 @@ FX_DWORD CPDF_Parser::StartAsynParse(IFX_FileRead* pFileAccess, |
FX_BOOL bXRefRebuilt = FALSE; |
FX_BOOL bLoadV4 = FALSE; |
if (!(bLoadV4 = LoadCrossRefV4(dwFirstXRefOffset, 0, FALSE, FALSE)) && |
- !LoadCrossRefV5(dwFirstXRefOffset, dwFirstXRefOffset, TRUE)) { |
+ !LoadCrossRefV5(&dwFirstXRefOffset, TRUE)) { |
if (!RebuildCrossRef()) { |
return PDFPARSE_ERROR_FORMAT; |
} |
@@ -1623,13 +1629,20 @@ FX_DWORD CPDF_Parser::StartAsynParse(IFX_FileRead* pFileAccess, |
return PDFPARSE_ERROR_SUCCESS; |
} |
FX_BOOL CPDF_Parser::LoadLinearizedAllCrossRefV5(FX_FILESIZE xrefpos) { |
- if (!LoadCrossRefV5(xrefpos, xrefpos, FALSE)) { |
+ if (!LoadCrossRefV5(&xrefpos, FALSE)) { |
return FALSE; |
} |
- while (xrefpos) |
- if (!LoadCrossRefV5(xrefpos, xrefpos, FALSE)) { |
+ std::set<FX_FILESIZE> seen_xrefpos; |
+ while (xrefpos) { |
+ seen_xrefpos.insert(xrefpos); |
+ if (!LoadCrossRefV5(&xrefpos, FALSE)) { |
+ return FALSE; |
+ } |
+ // Check for circular references. |
+ if (seen_xrefpos.find(xrefpos) != seen_xrefpos.end()) { |
return FALSE; |
} |
+ } |
m_ObjectStreamMap.InitHashTable(101, FALSE); |
m_bXRefStream = TRUE; |
return TRUE; |