sc/inc/chartlis.hxx | 6 ++++++ sc/source/core/tool/chartlis.cxx | 21 +++++++++++++++++++++ 2 files changed, 27 insertions(+)
New commits: commit ef2ed50231fd946c1f374ffbce28ebb98eda56c5 Author: Eike Rathke <er...@redhat.com> Date: Sat Nov 15 02:00:16 2014 +0100 fdo#73695 prevent use of invalidated iterator due to re-entrance ... through the UNO backdoor.. While charts are updated there can be chart data listeners in BASIC that in turn modify things such that charts are inserted/removed from the listener chain, invalidating the iterator. If that happens break and bail out instead of crashing. Not ideal, but.. Change-Id: Iefb33d3a96d79caed0ee4e19b73e8f811ef3d937 diff --git a/sc/inc/chartlis.hxx b/sc/inc/chartlis.hxx index f9a3641..9952d4b 100644 --- a/sc/inc/chartlis.hxx +++ b/sc/inc/chartlis.hxx @@ -141,6 +141,12 @@ public: typedef boost::unordered_set<OUString, OUStringHash> StringSetType; private: ListenersType maListeners; + enum UpdateStatus + { + SC_CLCUPDATE_NONE, + SC_CLCUPDATE_RUNNING, + SC_CLCUPDATE_MODIFIED + } meModifiedDuringUpdate; ::std::list<RangeListenerItem> maHiddenListeners; StringSetType maNonOleObjectNames; diff --git a/sc/source/core/tool/chartlis.cxx b/sc/source/core/tool/chartlis.cxx index be56325..837dbfe 100644 --- a/sc/source/core/tool/chartlis.cxx +++ b/sc/source/core/tool/chartlis.cxx @@ -411,6 +411,7 @@ ScChartListenerCollection::RangeListenerItem::RangeListenerItem(const ScRange& r } ScChartListenerCollection::ScChartListenerCollection( ScDocument* pDocP ) : + meModifiedDuringUpdate( SC_CLCUPDATE_NONE ), pDoc( pDocP ) { aTimer.SetTimeoutHdl( LINK( this, ScChartListenerCollection, TimerHdl ) ); @@ -418,6 +419,7 @@ ScChartListenerCollection::ScChartListenerCollection( ScDocument* pDocP ) : ScChartListenerCollection::ScChartListenerCollection( const ScChartListenerCollection& rColl ) : + meModifiedDuringUpdate( SC_CLCUPDATE_NONE ), pDoc( rColl.pDoc ) { aTimer.SetTimeoutHdl( LINK( this, ScChartListenerCollection, TimerHdl ) ); @@ -441,12 +443,16 @@ void ScChartListenerCollection::StartAllListeners() void ScChartListenerCollection::insert(ScChartListener* pListener) { + if (meModifiedDuringUpdate == SC_CLCUPDATE_RUNNING) + meModifiedDuringUpdate = SC_CLCUPDATE_MODIFIED; OUString aName = pListener->GetName(); maListeners.insert(aName, pListener); } void ScChartListenerCollection::removeByName(const OUString& rName) { + if (meModifiedDuringUpdate == SC_CLCUPDATE_RUNNING) + meModifiedDuringUpdate = SC_CLCUPDATE_MODIFIED; maListeners.erase(rName); } @@ -519,6 +525,9 @@ public: void ScChartListenerCollection::FreeUnused() { + if (meModifiedDuringUpdate == SC_CLCUPDATE_RUNNING) + meModifiedDuringUpdate = SC_CLCUPDATE_MODIFIED; + ListenersType aUsed, aUnused; // First, filter each listener into 'used' and 'unused' categories. @@ -550,6 +559,9 @@ void ScChartListenerCollection::FreeUnused() void ScChartListenerCollection::FreeUno( const uno::Reference< chart::XChartDataChangeEventListener >& rListener, const uno::Reference< chart::XChartData >& rSource ) { + if (meModifiedDuringUpdate == SC_CLCUPDATE_RUNNING) + meModifiedDuringUpdate = SC_CLCUPDATE_MODIFIED; + std::vector<ScChartListener*> aUsed, aUnused; // First, filter each listener into 'used' and 'unused' categories. @@ -594,6 +606,11 @@ IMPL_LINK_NOARG(ScChartListenerCollection, TimerHdl) void ScChartListenerCollection::UpdateDirtyCharts() { + // During ScChartListener::Update() the most nasty things can happen due to + // UNO listeners, e.g. reentrant calls via BASIC to insert() and FreeUno() + // and similar that modify maListeners and invalidate iterators. + meModifiedDuringUpdate = SC_CLCUPDATE_RUNNING; + ListenersType::iterator it = maListeners.begin(), itEnd = maListeners.end(); for (; it != itEnd; ++it) { @@ -601,9 +618,13 @@ void ScChartListenerCollection::UpdateDirtyCharts() if (p->IsDirty()) p->Update(); + if (meModifiedDuringUpdate == SC_CLCUPDATE_MODIFIED) + break; // iterator is invalid + if (aTimer.IsActive() && !pDoc->IsImportingXML()) break; // one interfered } + meModifiedDuringUpdate = SC_CLCUPDATE_NONE; } void ScChartListenerCollection::SetDirty() _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits