summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2019-11-26 16:45:48 +0000
committerGabor Kelemen <gabor.kelemen.extern@allotropia.de>2023-03-03 08:50:25 +0100
commitee1c77a325e8d18725592372bd402c5f79842012 (patch)
treeb68ac60bb9f4c7bd0368b4fe809e01e21da72915
parent8b1efdc1d7fd9ae86c996d706aa2d419ae8470f5 (diff)
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@redhat.com> Tested-by: Caolán McNamara <caolanm@redhat.com>
-rw-r--r--sw/inc/ndole.hxx15
-rw-r--r--sw/source/core/ole/ndole.cxx14
-rw-r--r--sw/source/filter/basflt/shellio.cxx6
3 files changed, 32 insertions, 3 deletions
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 9000d6ef1b9e..ff7233a74a45 100644
--- a/sw/source/core/ole/ndole.cxx
+++ b/sw/source/core/ole/ndole.cxx
@@ -980,6 +980,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 )
@@ -1006,6 +1018,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 47657980602f..5c80d7da6fef 100644
--- a/sw/source/filter/basflt/shellio.cxx
+++ b/sw/source/filter/basflt/shellio.cxx
@@ -58,6 +58,7 @@
#include <poolfmt.hxx>
#include <fltini.hxx>
#include <docsh.hxx>
+#include <ndole.hxx>
#include <ndtxt.hxx>
#include <redline.hxx>
#include <swerror.h>
@@ -854,8 +855,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 )
@@ -865,7 +865,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 )
{