summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorWei Li <weili@chromium.org>2016-01-05 12:51:32 -0800
committerWei Li <weili@chromium.org>2016-01-05 12:51:32 -0800
commitc009e8e6bfefa4f77bc02ac0b359b9fe58af384f (patch)
tree304f44f6e2c950301579cec9faa692d624f0b8c9 /core
parent8ab45eafebfd510554920e09e5ee85e94701dea9 (diff)
downloadpdfium-c009e8e6bfefa4f77bc02ac0b359b9fe58af384f.tar.xz
Merge to XFA: Exit infinite loops for cross reference loading
When cross reference sections form a loop, our code will enter an infinite loop. Add detection and exit code for v4 cross reference loading. V5 loading was done previously. TBR=thestig@chromium.org Review URL: https://codereview.chromium.org/1558093002 . (cherry picked from commit aab8f462ea3368ed4825172231131e1a10db978d) Review URL: https://codereview.chromium.org/1556423002 .
Diffstat (limited to 'core')
-rw-r--r--core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp42
1 files changed, 23 insertions, 19 deletions
diff --git a/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp b/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp
index c6e48e74a2..026247c3aa 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)) {