[Libreoffice-commits] core.git: sw/inc sw/source

Caolán McNamara (via logerrit) logerrit at kemper.freedesktop.org
Tue Nov 26 23:28:54 UTC 2019


 sw/inc/ndole.hxx                    |   15 +++++++++++++++
 sw/source/core/ole/ndole.cxx        |   14 ++++++++++++++
 sw/source/filter/basflt/shellio.cxx |    6 +++---
 3 files changed, 32 insertions(+), 3 deletions(-)

New commits:
commit 1cf1e9cc33327128f30c6781b4d8c16e20601540
Author:     Caolán McNamara <caolanm at redhat.com>
AuthorDate: Tue Nov 26 16:45:48 2019 +0000
Commit:     Caolán McNamara <caolanm at redhat.com>
CommitDate: Wed Nov 27 00:27:24 2019 +0100

    crashtesting: export of fdo50613-3.odt to docx crashes
    
    there are multiple objects in the doc and the ole cache hovers at the max size at
    which it wants to purge excess object.
    
    On save to docx, object a's chart model is fetched in order to save it, this
    triggers activating that object a, so object b is purged from the cache.
    storeOwn is called on b to save it to the document persist storage.
    
    During save of object b to document persist, ChartView::getExplicitValuesForAxis
    is called, which calls impl_updateView which eventually calls lcl_setDefaultWritingMode.
    
    *if* IsCTLFontEnabled is on, then chart digs through its parents objects
    looking for a chart in order to see what the writing direction is at the
    insertion point of the chart, or failing that for the page its on)
    (this also seems dubious as it might be any chart, not the current chart)
    
    To see if the object is a chart it calls getPropertyValue("CLSID") which brings
    the object into the ole cache, another object is purged from the cache, and the
    object purged is object b (which is in progress of getting purged already)
    
    object b is now purged in the inner case, so when control is returned to the outer
    storeOwn the object properties have been deleted and all is lost
    
    disallow a purge within a purge
    
    Change-Id: Ia21e794759aa82b6bcf39c638be8b47ac58a9bb3
    Reviewed-on: https://gerrit.libreoffice.org/83808
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>

diff --git a/sw/inc/ndole.hxx b/sw/inc/ndole.hxx
index 852fffd84e3d..b413d5af187d 100644
--- a/sw/inc/ndole.hxx
+++ b/sw/inc/ndole.hxx
@@ -168,6 +168,21 @@ inline const SwOLENode *SwNode::GetOLENode() const
      return SwNodeType::Ole == m_nNodeType ? static_cast<const SwOLENode*>(this) : nullptr;
 }
 
+namespace sw
+{
+    class DocumentSettingManager;
+}
+
+class SW_DLLPUBLIC PurgeGuard
+{
+private:
+    ::sw::DocumentSettingManager &m_rManager;
+    bool m_bOrigPurgeOle;
+public:
+    PurgeGuard(const SwDoc& rDoc);
+    ~PurgeGuard();
+};
+
 #endif  // _ INCLUDED_SW_INC_NDOLE_HXX
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/ole/ndole.cxx b/sw/source/core/ole/ndole.cxx
index c66ff319ac93..27af55bd915c 100644
--- a/sw/source/core/ole/ndole.cxx
+++ b/sw/source/core/ole/ndole.cxx
@@ -984,6 +984,18 @@ bool SwOLEObj::UnloadObject()
     return bRet;
 }
 
+PurgeGuard::PurgeGuard(const SwDoc& rDoc)
+    : m_rManager(const_cast<SwDoc&>(rDoc).GetDocumentSettingManager())
+    , m_bOrigPurgeOle(m_rManager.get(DocumentSettingId::PURGE_OLE))
+{
+    m_rManager.set(DocumentSettingId::PURGE_OLE, false);
+}
+
+PurgeGuard::~PurgeGuard()
+{
+    m_rManager.set(DocumentSettingId::PURGE_OLE, m_bOrigPurgeOle);
+}
+
 bool SwOLEObj::UnloadObject( uno::Reference< embed::XEmbeddedObject > const & xObj, const SwDoc* pDoc, sal_Int64 nAspect )
 {
     if ( !pDoc )
@@ -1010,6 +1022,8 @@ bool SwOLEObj::UnloadObject( uno::Reference< embed::XEmbeddedObject > const & xO
                     {
                         uno::Reference < embed::XEmbedPersist > xPers( xObj, uno::UNO_QUERY );
                         assert(xPers.is() && "Modified object without persistence in cache!");
+
+                        PurgeGuard aGuard(*pDoc);
                         xPers->storeOwn();
                     }
 
diff --git a/sw/source/filter/basflt/shellio.cxx b/sw/source/filter/basflt/shellio.cxx
index 708e13c2535b..0839b1c14df6 100644
--- a/sw/source/filter/basflt/shellio.cxx
+++ b/sw/source/filter/basflt/shellio.cxx
@@ -56,6 +56,7 @@
 #include <poolfmt.hxx>
 #include <fltini.hxx>
 #include <docsh.hxx>
+#include <ndole.hxx>
 #include <ndtxt.hxx>
 #include <redline.hxx>
 #include <swerror.h>
@@ -847,8 +848,7 @@ ErrCode SwWriter::Write( WriterRef const & rxWriter, const OUString* pRealFileNa
         pESh->StartAllAction();
     }
 
-    const bool bOrigPurgeOle = pOutDoc->getIDocumentSettingAccess().get(DocumentSettingId::PURGE_OLE);
-    pOutDoc->getIDocumentSettingAccess().set(DocumentSettingId::PURGE_OLE, false);
+    auto xGuard = std::make_unique<PurgeGuard>(*pOutDoc);
 
     ErrCode nError = ERRCODE_NONE;
     if( pMedium )
@@ -858,7 +858,7 @@ ErrCode SwWriter::Write( WriterRef const & rxWriter, const OUString* pRealFileNa
     else if( xStg.is() )
         nError = rxWriter->Write( *pPam, xStg, pRealFileName );
 
-    pOutDoc->getIDocumentSettingAccess().set(DocumentSettingId::PURGE_OLE, bOrigPurgeOle );
+    xGuard.reset();
 
     if( pESh )
     {


More information about the Libreoffice-commits mailing list