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

Kohei Yoshida kohei at kemper.freedesktop.org
Mon Nov 21 09:12:40 PST 2011


 sc/inc/dpobject.hxx              |    3 ++
 sc/source/core/data/dpobject.cxx |   48 ++++++++++++++++++++++++++++++++++-----
 2 files changed, 45 insertions(+), 6 deletions(-)

New commits:
commit d714c17c21bb061672ac0e900644f09380eaa140
Author: Kohei Yoshida <kohei.yoshida at suse.com>
Date:   Mon Nov 21 12:08:49 2011 -0500

    i#117239: Prevent crash on load with pivot table.
    
    The crash was due to recursive reference of GETPIVOTDATA within the
    source range of the pivot table object referring to itself.  The
    solution is to disable self reference with GETPIVOTDATA function.
    
    BTW, it goes without saying that, using GETPIVOTDATA inside the source
    range of the very pivot table that it references is asking for trouble.

diff --git a/sc/inc/dpobject.hxx b/sc/inc/dpobject.hxx
index bd69edb..cc73fcb 100644
--- a/sc/inc/dpobject.hxx
+++ b/sc/inc/dpobject.hxx
@@ -105,6 +105,7 @@ private:
     bool                    bAllowMove:1;
     bool                    bAlive:1;         // false if only used to hold settings
     bool                    bSettingsChanged:1;
+    bool                    mbEnableGetPivotData:1;
 
     SC_DLLPRIVATE ScDPTableData*    GetTableData();
     SC_DLLPRIVATE void              CreateObjects();
@@ -115,6 +116,8 @@ public:
     ScDPObject(const ScDPObject& r);
     ~ScDPObject();
 
+    void EnableGetPivotData(bool b);
+
     /**
      * When a DP object is "alive", it has table output on a sheet.  This flag
      * doesn't really change the behavior of the object, but is used only for
diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx
index 38bf5c5..9c0663d 100644
--- a/sc/source/core/data/dpobject.cxx
+++ b/sc/source/core/data/dpobject.cxx
@@ -199,7 +199,8 @@ ScDPObject::ScDPObject( ScDocument* pD ) :
     mbHeaderLayout(false),
     bAllowMove(false),
     bAlive(false),
-    bSettingsChanged(false)
+    bSettingsChanged(false),
+    mbEnableGetPivotData(true)
 {
 }
 
@@ -219,7 +220,8 @@ ScDPObject::ScDPObject(const ScDPObject& r) :
     mbHeaderLayout( r.mbHeaderLayout ),
     bAllowMove(false),
     bAlive(false),
-    bSettingsChanged(false)
+    bSettingsChanged(false),
+    mbEnableGetPivotData(r.mbEnableGetPivotData)
 {
     if (r.pSaveData)
         pSaveData = new ScDPSaveData(*r.pSaveData);
@@ -242,6 +244,11 @@ ScDPObject::~ScDPObject()
     ClearSource();
 }
 
+void ScDPObject::EnableGetPivotData(bool b)
+{
+    mbEnableGetPivotData = b;
+}
+
 void ScDPObject::SetAlive(bool bSet)
 {
     bAlive = bSet;
@@ -426,6 +433,26 @@ void ScDPObject::CreateOutput()
     }
 }
 
+namespace {
+
+class DisableGetPivotData
+{
+    ScDPObject& mrDPObj;
+    bool mbOldState;
+public:
+    DisableGetPivotData(ScDPObject& rObj, bool bOld) : mrDPObj(rObj), mbOldState(bOld)
+    {
+        mrDPObj.EnableGetPivotData(false);
+    }
+
+    ~DisableGetPivotData()
+    {
+        mrDPObj.EnableGetPivotData(mbOldState);
+    }
+};
+
+}
+
 ScDPTableData* ScDPObject::GetTableData()
 {
     if (!mpTableData)
@@ -444,9 +471,16 @@ ScDPTableData* ScDPObject::GetTableData()
                 OSL_FAIL("no source descriptor");
                 pSheetDesc = new ScSheetSourceDesc(pDoc);     // dummy defaults
             }
-            const ScDPCache* pCache = pSheetDesc->CreateCache();
-            if (pCache)
-                pData.reset(new ScSheetDPData(pDoc, *pSheetDesc, pCache));
+
+            {
+                // Temporarily disable GETPIVOTDATA to avoid having
+                // GETPIVOTDATA called onto itself from within the source
+                // range.
+                DisableGetPivotData aSwitch(*this, mbEnableGetPivotData);
+                const ScDPCache* pCache = pSheetDesc->CreateCache();
+                if (pCache)
+                    pData.reset(new ScSheetDPData(pDoc, *pSheetDesc, pCache));
+            }
         }
 
         // grouping (for cell or database data)
@@ -1047,8 +1081,10 @@ void ScDPObject::GetHeaderPositionData(const ScAddress& rPos, DataPilotTableHead
 bool ScDPObject::GetPivotData( ScDPGetPivotDataField& rTarget,
                                const std::vector< ScDPGetPivotDataField >& rFilters )
 {
-    CreateOutput();             // create xSource and pOutput if not already done
+    if (!mbEnableGetPivotData)
+        return false;
 
+    CreateOutput();             // create xSource and pOutput if not already done
     return pOutput->GetPivotData( rTarget, rFilters );
 }
 


More information about the Libreoffice-commits mailing list