[Libreoffice-commits] core.git: xmlsecurity/source

Miklos Vajna vmiklos at collabora.co.uk
Thu Nov 10 16:47:10 UTC 2016


 xmlsecurity/source/pdfio/pdfdocument.cxx |   37 +++++++++++++++----------------
 1 file changed, 18 insertions(+), 19 deletions(-)

New commits:
commit c21329fa904b682bde3df1082821df0af7ebbea3
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Thu Nov 10 10:18:31 2016 +0100

    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

diff --git a/xmlsecurity/source/pdfio/pdfdocument.cxx b/xmlsecurity/source/pdfio/pdfdocument.cxx
index 58aac94..2921222 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;


More information about the Libreoffice-commits mailing list