diff options
author | Kohei Yoshida <kohei.yoshida@suse.com> | 2011-11-21 12:08:49 -0500 |
---|---|---|
committer | Kohei Yoshida <kohei.yoshida@suse.com> | 2011-11-21 12:12:37 -0500 |
commit | d714c17c21bb061672ac0e900644f09380eaa140 (patch) | |
tree | b913ef91302e21a0a1f1bed799462e2eb9699cc6 /sc | |
parent | 513c888595db021c8eaed77a2438301b1c306885 (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.
Diffstat (limited to 'sc')
-rw-r--r-- | sc/inc/dpobject.hxx | 3 | ||||
-rw-r--r-- | sc/source/core/data/dpobject.cxx | 48 |
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 ); } |