diff options
author | Miklos Vajna <vmiklos@collabora.co.uk> | 2016-11-10 10:18:31 +0100 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.co.uk> | 2016-11-10 17:46:27 +0100 |
commit | c21329fa904b682bde3df1082821df0af7ebbea3 (patch) | |
tree | 0716a5b31a05ee4e3e35538d7309494ac0a76c00 /xmlsecurity | |
parent | 8445764681bfe7bd6cd31194878e1314a8fafa3b (diff) |
xmlsecurity PDF verify: fix incremental updates vs object streams
The problem: an object stream provies obj#1 and obj#2, then an
incremental updates provides an updated obj#1'. Then we look up obj#2,
parse the stored objects on-demand, so at the end when later we look up
the first object, we find obj#1, not obj#1'.
An easy workaround would be to never update already existing objects
from object streams, but that would break when an incremental update
provides an object stream.
Fix the problem by parsing stored objects right after tokenizing the
object stream, and not later, on-demand, when we no longer have the
context what objects should be ignored.
This is needed (but not enough) to correctly append a signature at the
end of a PDF file that has both object streams and incremental updates.
Change-Id: I3c1fae5ac26804c8e8cc1984511f43cfa881c97b
Diffstat (limited to 'xmlsecurity')
-rw-r--r-- | xmlsecurity/source/pdfio/pdfdocument.cxx | 37 |
1 files changed, 18 insertions, 19 deletions
diff --git a/xmlsecurity/source/pdfio/pdfdocument.cxx b/xmlsecurity/source/pdfio/pdfdocument.cxx index 58aac9428051..29212224ced6 100644 --- a/xmlsecurity/source/pdfio/pdfdocument.cxx +++ b/xmlsecurity/source/pdfio/pdfdocument.cxx @@ -603,7 +603,7 @@ bool PDFDocument::Sign(const uno::Reference<security::XCertificate>& xCertificat SvMemoryStream* pStreamBuffer = pAcroFormObject->GetStreamBuffer(); if (!pStreamBuffer) { - SAL_WARN("xmlsecurity.pdfio", "PDFDocument::Sign: AcroForm object is in an object stream"); + SAL_WARN("xmlsecurity.pdfio", "PDFDocument::Sign: AcroForm object is not in an object stream"); return false; } @@ -982,6 +982,8 @@ bool PDFDocument::Tokenize(SvStream& rStream, TokenizeMode eMode, std::vector< s { // Last seen object token. PDFObjectElement* pObject = pObjectElement; + PDFNameElement* pObjectKey = nullptr; + PDFObjectElement* pObjectStream = nullptr; bool bInXRef = false; // The next number will be an xref offset. bool bInStartXRef = false; @@ -1064,10 +1066,15 @@ bool PDFDocument::Tokenize(SvStream& rStream, TokenizeMode eMode, std::vector< s } case '/': { - rElements.push_back(std::unique_ptr<PDFElement>(new PDFNameElement())); + auto pNameElement = new PDFNameElement(); + rElements.push_back(std::unique_ptr<PDFElement>(pNameElement)); rStream.SeekRel(-1); - if (!rElements.back()->Read(rStream)) + if (!pNameElement->Read(rStream)) return false; + if (pObject && pObjectKey && pObjectKey->GetValue() == "Type" && pNameElement->GetValue() == "ObjStm") + pObjectStream = pObject; + else + pObjectKey = pNameElement; break; } case '(': @@ -1197,6 +1204,14 @@ bool PDFDocument::Tokenize(SvStream& rStream, TokenizeMode eMode, std::vector< s // Found endobj and only object parsing was requested, we're done. return true; } + + if (pObjectStream) + { + // We're at the end of an object stream, parse the stored objects. + pObjectStream->ParseStoredObjects(); + pObjectStream = nullptr; + pObjectKey = nullptr; + } } else if (aKeyword == "true" || aKeyword == "false") rElements.push_back(std::unique_ptr<PDFElement>(new PDFBooleanElement(aKeyword.toBoolean()))); @@ -3096,22 +3111,6 @@ PDFObjectElement* PDFReferenceElement::LookupObject() PDFObjectElement* PDFDocument::LookupObject(size_t nObjectNumber) { auto itIDObjects = m_aIDObjects.find(nObjectNumber); - auto itXRef = m_aXRef.find(nObjectNumber); - if (itIDObjects == m_aIDObjects.end() && itXRef != m_aXRef.end()) - { - // We don't have an object for this number yet, but there is an xref - // entry for it. - const XRefEntry& rEntry = itXRef->second; - if (rEntry.m_eType == XRefEntryType::COMPRESSED) - { - // It's a compressed entry, try parsing the stored objects. - if (PDFObjectElement* pObjectStream = LookupObject(rEntry.m_nOffset)) - // This registers new IDs. - pObjectStream->ParseStoredObjects(); - } - // Find again, now that the new objects are registered. - itIDObjects = m_aIDObjects.find(nObjectNumber); - } if (itIDObjects != m_aIDObjects.end()) return itIDObjects->second; |