[Libreoffice-commits] core.git: Branch 'distro/vector/vector-7.0' - embeddedobj/source sw/source

Miklos Vajna (via logerrit) logerrit at kemper.freedesktop.org
Fri Apr 9 08:04:10 UTC 2021


 embeddedobj/source/msole/olecomponent.cxx |    3 +++
 embeddedobj/source/msole/olepersist.cxx   |   15 +++++++++++++++
 sw/source/filter/html/htmlreqifreader.cxx |    9 +++++++++
 3 files changed, 27 insertions(+)

New commits:
commit d8a2a453866e035d77654caef115463cfdbe7c07
Author:     Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Thu Apr 8 17:03:21 2021 +0200
Commit:     Miklos Vajna <vmiklos at collabora.com>
CommitDate: Fri Apr 9 10:01:19 2021 +0200

    embeddedobj: fix lost native data when updating it via OLE fails
    
    How to reproduce the problem:
    
    1) Create an ODT file which has an OLE object, where the native data is
    an OLE2 container, containing a Package stream, containing a DOCX file.
    
    2) Install some external application on Windows which registers itself
    as a handler for the DOCX CSLID [ this is where writing a testcase for
    this bug is challenging ].
    
    3) Open this document via Java, using URP. Load the document with
    Hidden=true and OnMainThread=true.
    
    4) Dispatch .uno:UpdateAll
    
    5) Save the document using XStorable.store()
    
    Expected result: the native data is there.
    
    Actual result: the native data is sometimes missing (0 bytes). Typically
    happens at least once if you perform the steps 4 times in a row.
    
    The root cause is that GetUserClassID() Win32 API fails in some cases,
    and re-trying a few times after a small sleep doesn't help.
    
    Handle this error better by detecting this situation in
    OleEmbeddedObject::SwitchOwnPersistence() and reusing the old native
    data, similar to how svt::EmbeddedObjectRef::GetReplacement() updates
    the preview image in a transactional way (only delete the old one when
    we have a one one).
    
    Finally, detect a broken OLE2 preview during reqif export, this way the
    reqif export result's embedded object is editable in Word, while
    \objdata was simply empty previously.
    
    (cherry picked from commit fb4dc0f1786e0a036fc224393e91a3f1fdbff1b3)
    
    Change-Id: I4dd34ebe6ad892a14cdcfb82acc82d9edf790fb3

diff --git a/embeddedobj/source/msole/olecomponent.cxx b/embeddedobj/source/msole/olecomponent.cxx
index 7e8cfdb1809e..8fc8a3e0559f 100644
--- a/embeddedobj/source/msole/olecomponent.cxx
+++ b/embeddedobj/source/msole/olecomponent.cxx
@@ -1300,7 +1300,10 @@ void OleComponent::StoreOwnTmpIfNecessary()
             GUID aCLSID;
             hr = m_pNativeImpl->m_pOleObject->GetUserClassID( &aCLSID );
             if ( FAILED( hr ) )
+            {
+                SAL_WARN("embeddedobj.ole", "OleComponent::StoreOwnTmpIfNecessary: GetUserClassID() failed");
                 throw io::IOException(); // TODO
+            }
 
             hr = WriteClassStg( m_pNativeImpl->m_pIStorage, aCLSID );
             if ( FAILED( hr ) )
diff --git a/embeddedobj/source/msole/olepersist.cxx b/embeddedobj/source/msole/olepersist.cxx
index c4c8760b549b..57699246a723 100644
--- a/embeddedobj/source/msole/olepersist.cxx
+++ b/embeddedobj/source/msole/olepersist.cxx
@@ -767,6 +767,21 @@ void OleEmbeddedObject::SwitchOwnPersistence( const uno::Reference< embed::XStor
     sal_Int32 nStreamMode = m_bReadOnly ? embed::ElementModes::READ : embed::ElementModes::READWRITE;
 
     uno::Reference< io::XStream > xNewOwnStream = xNewParentStorage->openStreamElement( aNewName, nStreamMode );
+
+    uno::Reference<io::XSeekable> xNewSeekable (xNewOwnStream, uno::UNO_QUERY);
+    if (xNewSeekable.is() && xNewSeekable->getLength() == 0)
+    {
+        uno::Reference<io::XSeekable> xOldSeekable(m_xObjectStream, uno::UNO_QUERY);
+        if (xOldSeekable.is() && xOldSeekable->getLength() > 0)
+        {
+            SAL_WARN("embeddedobj.ole", "OleEmbeddedObject::SwitchOwnPersistence: empty new stream, reusing old one");
+            uno::Reference<io::XInputStream> xInput = m_xObjectStream->getInputStream();
+            uno::Reference<io::XOutputStream> xOutput = xNewOwnStream->getOutputStream();
+            comphelper::OStorageHelper::CopyInputToOutput(xInput, xOutput);
+            xNewSeekable->seek(0);
+        }
+    }
+
     SAL_WARN_IF( !xNewOwnStream.is(), "embeddedobj.ole", "The method can not return empty reference!" );
 
     SwitchOwnPersistence( xNewParentStorage, xNewOwnStream, aNewName );
diff --git a/sw/source/filter/html/htmlreqifreader.cxx b/sw/source/filter/html/htmlreqifreader.cxx
index 005dd2788640..6488f32ad578 100644
--- a/sw/source/filter/html/htmlreqifreader.cxx
+++ b/sw/source/filter/html/htmlreqifreader.cxx
@@ -142,6 +142,15 @@ bool ParseOLE2Presentation(SvStream& rOle2, sal_uInt32& nWidth, sal_uInt32& nHei
     // Read Data.
     if (nSize > xOle2Presentation->remainingSize())
         return false;
+
+    if (nSize <= 64)
+    {
+        SAL_WARN("sw.html",
+                 "ParseOLE2Presentation: ignoring potentially broken small preview: size is "
+                     << nSize);
+        return false;
+    }
+
     std::vector<char> aBuffer(nSize);
     xOle2Presentation->ReadBytes(aBuffer.data(), aBuffer.size());
     rPresentationData.WriteBytes(aBuffer.data(), aBuffer.size());


More information about the Libreoffice-commits mailing list