diff options
author | Kohei Yoshida <kohei.yoshida@collabora.com> | 2014-05-01 12:16:12 -0400 |
---|---|---|
committer | Kohei Yoshida <kohei.yoshida@collabora.com> | 2014-05-01 12:17:45 -0400 |
commit | 7fbe0f56192f7e106c560646d37fbb93b69b0446 (patch) | |
tree | 2a4dec15c4ba3f69a1a7a757386135a6d921112c | |
parent | 6b431b1f0d397067504b5300d49e10e232936836 (diff) |
fdo#77806: Use the common block position set for start and end listening.
Else an invalid iterator may result, which would eventually leads to a
crash.
Change-Id: Ie909de61244d661c72a3450cc69b29fbb218a248
-rw-r--r-- | sc/inc/listenercontext.hxx | 7 | ||||
-rw-r--r-- | sc/source/core/data/column.cxx | 9 | ||||
-rw-r--r-- | sc/source/core/data/listenercontext.cxx | 9 | ||||
-rw-r--r-- | sc/source/core/tool/token.cxx | 8 |
4 files changed, 27 insertions, 6 deletions
diff --git a/sc/inc/listenercontext.hxx b/sc/inc/listenercontext.hxx index 0e63b8d11e20..7d66f9248ad6 100644 --- a/sc/inc/listenercontext.hxx +++ b/sc/inc/listenercontext.hxx @@ -15,6 +15,7 @@ #include <boost/noncopyable.hpp> #include <boost/scoped_ptr.hpp> +#include <boost/shared_ptr.hpp> class ScDocument; class ScTokenArray; @@ -27,9 +28,10 @@ class ColumnBlockPositionSet; class StartListeningContext : boost::noncopyable { ScDocument& mrDoc; - boost::scoped_ptr<ColumnBlockPositionSet> mpSet; + boost::shared_ptr<ColumnBlockPositionSet> mpSet; public: StartListeningContext(ScDocument& rDoc); + StartListeningContext(ScDocument& rDoc, const boost::shared_ptr<ColumnBlockPositionSet>& pSet); ScDocument& getDoc(); ColumnBlockPosition* getBlockPosition(SCTAB nTab, SCCOL nCol); @@ -39,12 +41,13 @@ class EndListeningContext : boost::noncopyable { ScDocument& mrDoc; ColumnSpanSet maSet; - boost::scoped_ptr<ColumnBlockPositionSet> mpPosSet; + boost::shared_ptr<ColumnBlockPositionSet> mpPosSet; ScTokenArray* mpOldCode; ScAddress maPosDelta; // Add this to get the old position prior to the move. public: EndListeningContext(ScDocument& rDoc, ScTokenArray* pOldCode = NULL); + EndListeningContext(ScDocument& rDoc, const boost::shared_ptr<ColumnBlockPositionSet>& pSet, ScTokenArray* pOldCode = NULL); void setPositionDelta( const ScAddress& rDelta ); diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx index 208c04688e53..a76e746adc89 100644 --- a/sc/source/core/data/column.cxx +++ b/sc/source/core/data/column.cxx @@ -2176,9 +2176,14 @@ class UpdateRefOnNonCopy : std::unary_function<sc::FormulaGroupEntry, void> // Perform end-listening, start-listening, and dirtying on all // formula cells in the group. - sc::StartListeningContext aStartCxt(mpCxt->mrDoc); + // Make sure that the start and end listening contexts share the + // same block position set, else an invalid iterator may ensue. + boost::shared_ptr<sc::ColumnBlockPositionSet> pPosSet( + new sc::ColumnBlockPositionSet(mpCxt->mrDoc)); + + sc::StartListeningContext aStartCxt(mpCxt->mrDoc, pPosSet); + sc::EndListeningContext aEndCxt(mpCxt->mrDoc, pPosSet, pOldCode.get()); - sc::EndListeningContext aEndCxt(mpCxt->mrDoc, pOldCode.get()); aEndCxt.setPositionDelta( ScAddress(-mpCxt->mnColDelta, -mpCxt->mnRowDelta, -mpCxt->mnTabDelta)); diff --git a/sc/source/core/data/listenercontext.cxx b/sc/source/core/data/listenercontext.cxx index add75a25a0e7..dcdffac65710 100644 --- a/sc/source/core/data/listenercontext.cxx +++ b/sc/source/core/data/listenercontext.cxx @@ -16,6 +16,10 @@ namespace sc { StartListeningContext::StartListeningContext(ScDocument& rDoc) : mrDoc(rDoc), mpSet(new ColumnBlockPositionSet(rDoc)) {} +StartListeningContext::StartListeningContext( + ScDocument& rDoc, const boost::shared_ptr<ColumnBlockPositionSet>& pSet) : + mrDoc(rDoc), mpSet(pSet) {} + ScDocument& StartListeningContext::getDoc() { return mrDoc; @@ -30,6 +34,11 @@ EndListeningContext::EndListeningContext(ScDocument& rDoc, ScTokenArray* pOldCod mrDoc(rDoc), maSet(false), mpPosSet(new ColumnBlockPositionSet(rDoc)), mpOldCode(pOldCode), maPosDelta(0,0,0) {} +EndListeningContext::EndListeningContext( + ScDocument& rDoc, const boost::shared_ptr<ColumnBlockPositionSet>& pSet, ScTokenArray* pOldCode) : + mrDoc(rDoc), maSet(false), mpPosSet(pSet), + mpOldCode(pOldCode), maPosDelta(0,0,0) {} + void EndListeningContext::setPositionDelta( const ScAddress& rDelta ) { maPosDelta = rDelta; diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx index bd884eb0246c..b1f8e022eade 100644 --- a/sc/source/core/tool/token.cxx +++ b/sc/source/core/tool/token.cxx @@ -2785,13 +2785,17 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnShift( const sc::RefUpdateCon sc::RefUpdateResult ScTokenArray::AdjustReferenceOnMove( const sc::RefUpdateContext& rCxt, const ScAddress& rOldPos, const ScAddress& rNewPos ) { + sc::RefUpdateResult aRes; + + if (!rCxt.mnColDelta && !rCxt.mnRowDelta && !rCxt.mnTabDelta) + // The cell hasn't moved at all. + return aRes; + // When moving, the range is the destination range. We need to use the old // range prior to the move for hit analysis. ScRange aOldRange = rCxt.maRange; aOldRange.Move(-rCxt.mnColDelta, -rCxt.mnRowDelta, -rCxt.mnTabDelta); - sc::RefUpdateResult aRes; - FormulaToken** p = pCode; FormulaToken** pEnd = p + static_cast<size_t>(nLen); for (; p != pEnd; ++p) |