include/vcl/filter/pdfdocument.hxx | 16 ++++++++++++---- vcl/source/filter/ipdf/pdfdocument.cxx | 32 ++++++++++++++++++++------------ 2 files changed, 32 insertions(+), 16 deletions(-)
New commits: commit cc8140fe71becc92976167e2a96dbe1d727097dc Author: Caolán McNamara <caol...@redhat.com> AuthorDate: Wed Aug 1 19:25:27 2018 +0100 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Fri Aug 3 11:14:00 2018 +0200 forcepoint#66 make sure we don't get stuck endlessly reparsing Change-Id: Ie2733e8d7f73e5f6a072604c477e949cd944189a Reviewed-on: https://gerrit.libreoffice.org/58466 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.st...@cib.de> diff --git a/vcl/source/filter/ipdf/pdfdocument.cxx b/vcl/source/filter/ipdf/pdfdocument.cxx index 584f22536e67..48cb17b67fae 100644 --- a/vcl/source/filter/ipdf/pdfdocument.cxx +++ b/vcl/source/filter/ipdf/pdfdocument.cxx @@ -2175,9 +2175,14 @@ size_t PDFDictionaryElement::Parse(const std::vector< std::unique_ptr<PDFElement else if (!pDictionary->alreadyParsing()) { // Nested dictionary. - i = PDFDictionaryElement::Parse(rElements, pDictionary, pDictionary->m_aItems); - rDictionary[aName] = pDictionary; - aName.clear(); + const size_t nexti + = PDFDictionaryElement::Parse(rElements, pDictionary, pDictionary->m_aItems); + if (nexti >= i) // ensure we go forwards and not endlessly loop + { + i = nexti; + rDictionary[aName] = pDictionary; + aName.clear(); + } } } commit 171657a1f675268839526b1a13e5f3549fb73516 Author: Caolán McNamara <caol...@redhat.com> AuthorDate: Wed Aug 1 15:05:45 2018 +0100 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Fri Aug 3 11:13:45 2018 +0200 forcepoint#66 protect against infinite parse recurse Change-Id: I0313cc141469a00b7d6a5bd15400e9d5a8f686cf Reviewed-on: https://gerrit.libreoffice.org/58452 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.st...@cib.de> diff --git a/include/vcl/filter/pdfdocument.hxx b/include/vcl/filter/pdfdocument.hxx index 697751b7f94d..f06049e55c30 100644 --- a/include/vcl/filter/pdfdocument.hxx +++ b/include/vcl/filter/pdfdocument.hxx @@ -38,9 +38,21 @@ class PDFNumberElement; /// A byte range in a PDF file. class VCL_DLLPUBLIC PDFElement { + bool m_bVisiting; + bool m_bParsing; + public: + PDFElement() + : m_bVisiting(false) + , m_bParsing(false) + { + } virtual bool Read(SvStream& rStream) = 0; virtual ~PDFElement() = default; + void setVisiting(bool bVisiting) { m_bVisiting = bVisiting; } + bool alreadyVisiting() const { return m_bVisiting; } + void setParsing(bool bParsing) { m_bParsing = bParsing; } + bool alreadyParsing() const { return m_bParsing; } }; /// Indirect object: something with a unique ID. @@ -50,7 +62,6 @@ class VCL_DLLPUBLIC PDFObjectElement : public PDFElement PDFDocument& m_rDoc; double m_fObjectValue; double m_fGenerationValue; - bool m_bVisiting; std::map<OString, PDFElement*> m_aDictionary; /// If set, the object contains this number element (outside any dictionary/array). PDFNumberElement* m_pNumberElement; @@ -110,9 +121,6 @@ public: SvMemoryStream* GetStreamBuffer() const; void SetStreamBuffer(std::unique_ptr<SvMemoryStream>& pStreamBuffer); PDFDocument& GetDocument(); - - /// Visits the page tree recursively, looking for page objects. - void visitPages(std::vector<PDFObjectElement*>& rRet); }; /// Array object: a list. diff --git a/vcl/source/filter/ipdf/pdfdocument.cxx b/vcl/source/filter/ipdf/pdfdocument.cxx index b55ad45096ef..584f22536e67 100644 --- a/vcl/source/filter/ipdf/pdfdocument.cxx +++ b/vcl/source/filter/ipdf/pdfdocument.cxx @@ -1751,16 +1751,16 @@ const std::vector< std::unique_ptr<PDFElement> >& PDFDocument::GetElements() } /// Visits the page tree recursively, looking for page objects. -void PDFObjectElement::visitPages(std::vector<PDFObjectElement*>& rRet) +static void visitPages(PDFObjectElement* pPages, std::vector<PDFObjectElement*>& rRet) { - auto pKids = dynamic_cast<PDFArrayElement*>(Lookup("Kids")); + auto pKids = dynamic_cast<PDFArrayElement*>(pPages->Lookup("Kids")); if (!pKids) { SAL_WARN("vcl.filter", "visitPages: pages has no kids"); return; } - m_bVisiting = true; + pPages->setVisiting(true); for (const auto& pKid : pKids->GetElements()) { @@ -1773,7 +1773,7 @@ void PDFObjectElement::visitPages(std::vector<PDFObjectElement*>& rRet) continue; // detect if visiting reenters itself - if (pKidObject->m_bVisiting) + if (pKidObject->alreadyVisiting()) { SAL_WARN("vcl.filter", "visitPages: loop in hierarchy"); continue; @@ -1782,13 +1782,13 @@ void PDFObjectElement::visitPages(std::vector<PDFObjectElement*>& rRet) auto pName = dynamic_cast<PDFNameElement*>(pKidObject->Lookup("Type")); if (pName && pName->GetValue() == "Pages") // Pages inside pages: recurse. - pKidObject->visitPages(rRet); + visitPages(pKidObject, rRet); else // Found an actual page. rRet.push_back(pKidObject); } - m_bVisiting = false; + pPages->setVisiting(false); } std::vector<PDFObjectElement*> PDFDocument::GetPages() @@ -1833,7 +1833,7 @@ std::vector<PDFObjectElement*> PDFDocument::GetPages() return aRet; } - pPages->visitPages(aRet); + visitPages(pPages, aRet); return aRet; } @@ -2098,7 +2098,6 @@ PDFObjectElement::PDFObjectElement(PDFDocument& rDoc, double fObjectValue, doubl : m_rDoc(rDoc), m_fObjectValue(fObjectValue), m_fGenerationValue(fGenerationValue), - m_bVisiting(false), m_pNumberElement(nullptr), m_nDictionaryOffset(0), m_nDictionaryLength(0), @@ -2126,6 +2125,8 @@ size_t PDFDictionaryElement::Parse(const std::vector< std::unique_ptr<PDFElement if (!rDictionary.empty()) return nRet; + pThis->setParsing(true); + auto pThisObject = dynamic_cast<PDFObjectElement*>(pThis); // This is set to non-nullptr here for nested dictionaries only. auto pThisDictionary = dynamic_cast<PDFDictionaryElement*>(pThis); @@ -2171,7 +2172,7 @@ size_t PDFDictionaryElement::Parse(const std::vector< std::unique_ptr<PDFElement pThisObject->SetDictionaryOffset(nDictionaryOffset); } } - else + else if (!pDictionary->alreadyParsing()) { // Nested dictionary. i = PDFDictionaryElement::Parse(rElements, pDictionary, pDictionary->m_aItems); @@ -2345,6 +2346,8 @@ size_t PDFDictionaryElement::Parse(const std::vector< std::unique_ptr<PDFElement aNumbers.clear(); } + pThis->setParsing(false); + return nRet; } _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits