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

Kohei Yoshida kohei.yoshida at collabora.com
Thu May 1 09:17:59 PDT 2014


 sc/inc/listenercontext.hxx              |    7 +++++--
 sc/source/core/data/column.cxx          |    9 +++++++--
 sc/source/core/data/listenercontext.cxx |    9 +++++++++
 sc/source/core/tool/token.cxx           |    8 ++++++--
 4 files changed, 27 insertions(+), 6 deletions(-)

New commits:
commit 7fbe0f56192f7e106c560646d37fbb93b69b0446
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Thu May 1 12:16:12 2014 -0400

    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

diff --git a/sc/inc/listenercontext.hxx b/sc/inc/listenercontext.hxx
index 0e63b8d..7d66f924 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 208c046..a76e746 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 add75a2..dcdffac 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 bd884eb..b1f8e02 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)


More information about the Libreoffice-commits mailing list