diff options
author | Wei Li <weili@chromium.org> | 2016-01-05 12:51:32 -0800 |
---|---|---|
committer | Wei Li <weili@chromium.org> | 2016-01-05 12:51:32 -0800 |
commit | c009e8e6bfefa4f77bc02ac0b359b9fe58af384f (patch) | |
tree | 304f44f6e2c950301579cec9faa692d624f0b8c9 /core/src | |
parent | 8ab45eafebfd510554920e09e5ee85e94701dea9 (diff) | |
download | pdfium-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/src')
-rw-r--r-- | core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp | 42 |
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)) { |