Here is another bug fix I'd like to push to the -3-4 branch.

https://bugs.freedesktop.org/show_bug.cgi?id=36719

Opening a document with a pivot table that is linked to a invalid
database source crashes Calc in various places.  The attached patch
fixes this.

The changes are mostly simple things such as checking for NULL pointers
before dereferencing.

I'm attaching a patch instead of cherry-picking because the commit I
pushed to master has a wrong bug ID in the message.

Anyway, review & sign-off appreciated.

Kohei

-- 
Kohei Yoshida, LibreOffice hacker, Calc
<kyosh...@novell.com>
>From 9b4370d6946f9dee5d363e362d86247df7d2958c Mon Sep 17 00:00:00 2001
From: Kohei Yoshida <kyosh...@novell.com>
Date: Fri, 10 Jun 2011 13:06:49 -0400
Subject: [PATCH] fdo#36719: Prevent crash on pivot table with invalid database connection.

Check for NULL cache state to handle invalid database connection more
gracefully (i.e. without crashing).
---
 sc/source/core/data/dpcachetable.cxx |   11 ++++++++---
 sc/source/core/data/dpsdbtab.cxx     |   10 +++++++++-
 sc/source/ui/view/cellsh1.cxx        |   24 +++++++++++++++++++++++-
 3 files changed, 40 insertions(+), 5 deletions(-)

diff --git a/sc/source/core/data/dpcachetable.cxx b/sc/source/core/data/dpcachetable.cxx
index 40d34ac..b7b8a64 100644
--- a/sc/source/core/data/dpcachetable.cxx
+++ b/sc/source/core/data/dpcachetable.cxx
@@ -180,12 +180,12 @@ ScDPCacheTable::~ScDPCacheTable()
 
 sal_Int32 ScDPCacheTable::getRowSize() const
 {
-    return getCache()->GetRowCount();
+    return mpCache ? getCache()->GetRowCount() : 0;
 }
 
 sal_Int32 ScDPCacheTable::getColSize() const
 {
-    return getCache()->GetColumnCount();
+    return mpCache ? getCache()->GetColumnCount() : 0;
 }
 
 void ScDPCacheTable::fillTable(
@@ -313,6 +313,9 @@ void ScDPCacheTable::filterByPageDimension(const vector<Criterion>& rCriteria, c
 
 const ScDPItemData* ScDPCacheTable::getCell(SCCOL nCol, SCROW nRow, bool bRepeatIfEmpty) const
 { 
+    if (!mpCache)
+        return NULL;
+
    SCROW nId= getCache()->GetItemDataId(nCol, nRow, bRepeatIfEmpty);
    return getCache()->GetItemDataById( nCol, nId );
 }
@@ -331,6 +334,8 @@ void  ScDPCacheTable::getValue( ScDPValueData& rVal, SCCOL nCol, SCROW nRow, boo
 }
 String ScDPCacheTable::getFieldName(SCCOL  nIndex) const
 {
+    if (!mpCache)
+        return String();
     return getCache()->GetDimensionName( nIndex );
 }
 
@@ -410,7 +415,7 @@ void ScDPCacheTable::filterTable(const vector<Criterion>& rCriteria, Sequence< S
 
 SCROW ScDPCacheTable::getOrder(long nDim, SCROW nIndex) const
 {
-    return getCache()->GetOrder(nDim, nIndex);
+    return mpCache ? getCache()->GetOrder(nDim, nIndex) : 0;
 }
 
 void ScDPCacheTable::clear()
diff --git a/sc/source/core/data/dpsdbtab.cxx b/sc/source/core/data/dpsdbtab.cxx
index 417c142..d16d03e 100644
--- a/sc/source/core/data/dpsdbtab.cxx
+++ b/sc/source/core/data/dpsdbtab.cxx
@@ -136,10 +136,18 @@ void ScDatabaseDPData::SetEmptyFlags( sal_Bool /* bIgnoreEmptyRows */, sal_Bool
 void ScDatabaseDPData::CreateCacheTable()
 {
     if (!aCacheTable.empty())
+        // cache table already created.
         return;
 
     if (!aCacheTable.hasCache())
-        aCacheTable.setCache(mrImport.CreateCache());
+    {
+        const ScDPCache* pCache = mrImport.CreateCache();
+        if (!pCache)
+            // Cache creation failed.  Perhaps invalid database connection.
+            return;
+
+        aCacheTable.setCache(pCache);
+    }
 
     aCacheTable.fillTable();
 }
diff --git a/sc/source/ui/view/cellsh1.cxx b/sc/source/ui/view/cellsh1.cxx
index 30d3933..90fb0ba 100644
--- a/sc/source/ui/view/cellsh1.cxx
+++ b/sc/source/ui/view/cellsh1.cxx
@@ -2127,6 +2127,27 @@ void ScCellShell::ExecuteExternalSource(
         _rRequest.Ignore();
 }
 
+namespace {
+
+bool isDPSourceValid(const ScDPObject& rDPObj)
+{
+    if (rDPObj.IsImportData())
+    {
+        // If the data type is database, check if the database is still valid.
+        const ScImportSourceDesc* pDesc = rDPObj.GetImportSourceDesc();
+        if (!pDesc)
+            return false;
+
+        const ScDPCache* pCache = pDesc->CreateCache();
+        if (!pCache)
+            // cashe creation failed, probably due to invalid connection.
+            return false;
+    }
+    return true;
+}
+
+}
+
 void ScCellShell::ExecuteDataPilotDialog()
 {
     ScModule* pScMod = SC_MOD();
@@ -2142,7 +2163,8 @@ void ScCellShell::ExecuteDataPilotDialog()
                                 pData->GetTabNo() );
     if ( pDPObj )   // on an existing table?
     {
-        pNewDPObject.reset(new ScDPObject(*pDPObj));
+        if (isDPSourceValid(*pDPObj))
+            pNewDPObject.reset(new ScDPObject(*pDPObj));
     }
     else            // create new table
     {
-- 
1.7.3.4

_______________________________________________
LibreOffice mailing list
LibreOffice@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/libreoffice

Reply via email to