summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@suse.com>2011-11-21 12:08:49 -0500
committerKohei Yoshida <kohei.yoshida@suse.com>2011-11-21 12:12:37 -0500
commitd714c17c21bb061672ac0e900644f09380eaa140 (patch)
treeb913ef91302e21a0a1f1bed799462e2eb9699cc6
parent513c888595db021c8eaed77a2438301b1c306885 (diff)
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.
-rw-r--r--sc/inc/dpobject.hxx3
-rw-r--r--sc/source/core/data/dpobject.cxx48
2 files changed, 45 insertions, 6 deletions
diff --git a/sc/inc/dpobject.hxx b/sc/inc/dpobject.hxx
index bd69edb82b39..cc73fcbee82a 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 38bf5c525584..9c0663df45fa 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 );
}