diff options
author | Eike Rathke <erack@redhat.com> | 2015-04-14 23:09:46 +0200 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2015-04-21 13:07:49 +0000 |
commit | 5c6f7f0920a91c974e9639f2c751582c8f140b2b (patch) | |
tree | 67ba4ce68067e3cac55aeaae88532253327a9abd | |
parent | c93eaee6af54f4786af16c602ddb3dc21331a5a6 (diff) |
tdf#89957 prevent crash, not really fixed
See source code comment.
(cherry picked from commit cff5ee864b2d87d74079697425d7895dbf1b2ba4)
more SAL_INFO sc.core.grouparealistener
(cherry picked from commit b03563571fb922636635ea72f2dbda18d736ff89)
Conflicts:
sc/source/core/tool/grouparealistener.cxx
a3c75e626edee3ad28ad5b7eb80f729ae8aaa83f
Change-Id: I3ab7ab6aec1d782de0733064fea031c895f28965
Reviewed-on: https://gerrit.libreoffice.org/15331
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
-rw-r--r-- | sc/inc/column.hxx | 2 | ||||
-rw-r--r-- | sc/source/core/data/column2.cxx | 15 | ||||
-rw-r--r-- | sc/source/core/tool/grouparealistener.cxx | 43 |
3 files changed, 47 insertions, 13 deletions
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index 1c79f1125294..bacafa5f0962 100644 --- a/sc/inc/column.hxx +++ b/sc/inc/column.hxx @@ -351,7 +351,7 @@ public: void GetFormula( SCROW nRow, OUString& rFormula ) const; const ScFormulaCell* GetFormulaCell( SCROW nRow ) const; ScFormulaCell* GetFormulaCell( SCROW nRow ); - ScFormulaCell * const * GetFormulaCellBlockAddress( SCROW nRow ) const; + ScFormulaCell * const * GetFormulaCellBlockAddress( SCROW nRow, size_t& rBlockSize ) const; CellType GetCellType( SCROW nRow ) const; SCSIZE GetCellCount() const; sal_uInt32 GetWeightedCount() const; diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx index 943dcd6a5aa9..0f22f7974a03 100644 --- a/sc/source/core/data/column2.cxx +++ b/sc/source/core/data/column2.cxx @@ -2712,26 +2712,37 @@ void ScColumn::SetNumberFormat( SCROW nRow, sal_uInt32 nNumberFormat ) ApplyAttr(nRow, SfxUInt32Item(ATTR_VALUE_FORMAT, nNumberFormat)); } -ScFormulaCell * const * ScColumn::GetFormulaCellBlockAddress( SCROW nRow ) const +ScFormulaCell * const * ScColumn::GetFormulaCellBlockAddress( SCROW nRow, size_t& rBlockSize ) const { if (!ValidRow(nRow)) + { + rBlockSize = 0; return NULL; + } std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nRow); sc::CellStoreType::const_iterator it = aPos.first; if (it == maCells.end()) + { + rBlockSize = 0; return NULL; + } if (it->type != sc::element_type_formula) + { // Not a formula cell. + rBlockSize = 0; return NULL; + } + rBlockSize = it->size; return &sc::formula_block::at(*it->data, aPos.second); } const ScFormulaCell* ScColumn::FetchFormulaCell( SCROW nRow ) const { - ScFormulaCell const * const * pp = GetFormulaCellBlockAddress( nRow ); + size_t nBlockSize = 0; + ScFormulaCell const * const * pp = GetFormulaCellBlockAddress( nRow, nBlockSize ); return pp ? *pp : NULL; } diff --git a/sc/source/core/tool/grouparealistener.cxx b/sc/source/core/tool/grouparealistener.cxx index be4b0f01e533..86be4f736d92 100644 --- a/sc/source/core/tool/grouparealistener.cxx +++ b/sc/source/core/tool/grouparealistener.cxx @@ -86,16 +86,18 @@ FormulaGroupAreaListener::FormulaGroupAreaListener( const ScRange& rRange, const assert(mpColumn); SAL_INFO( "sc.core.grouparealistener", "FormulaGroupAreaListener ctor this " << this << - " range " << maRange.Format(SCA_VALID) << - " mnTopCellRow " << mnTopCellRow << " length " << mnGroupLen); + " range " << (maRange == BCA_LISTEN_ALWAYS ? "LISTEN-ALWAYS" : maRange.Format(SCA_VALID)) << + " mnTopCellRow " << mnTopCellRow << " length " << mnGroupLen << + ", col/tab " << mpColumn->GetCol() << "/" << mpColumn->GetTab()); } FormulaGroupAreaListener::~FormulaGroupAreaListener() { SAL_INFO( "sc.core.grouparealistener", "FormulaGroupAreaListener dtor this " << this << - " range " << maRange.Format(SCA_VALID) << - " mnTopCellRow " << mnTopCellRow << " length " << mnGroupLen); + " range " << (maRange == BCA_LISTEN_ALWAYS ? "LISTEN-ALWAYS" : maRange.Format(SCA_VALID)) << + " mnTopCellRow " << mnTopCellRow << " length " << mnGroupLen << + ", col/tab " << mpColumn->GetCol() << "/" << mpColumn->GetTab()); } ScRange FormulaGroupAreaListener::getListeningRange() const @@ -184,13 +186,33 @@ void FormulaGroupAreaListener::collectFormulaCells( { SAL_INFO( "sc.core.grouparealistener", "FormulaGroupAreaListener::collectFormulaCells() this " << this << - " range " << maRange.Format(SCA_VALID) << - " mnTopCellRow " << mnTopCellRow << " length " << mnGroupLen); + " range " << (maRange == BCA_LISTEN_ALWAYS ? "LISTEN-ALWAYS" : maRange.Format(SCA_VALID)) << + " mnTopCellRow " << mnTopCellRow << " length " << mnGroupLen << + ", col/tab " << mpColumn->GetCol() << "/" << mpColumn->GetTab()); - ScFormulaCell* const * pp = mpColumn->GetFormulaCellBlockAddress( mnTopCellRow); - assert(pp); + size_t nBlockSize = 0; + ScFormulaCell* const * pp = mpColumn->GetFormulaCellBlockAddress( mnTopCellRow, nBlockSize); if (!pp) + { + SAL_WARN("sc", "GetFormulaCellBlockAddress not found"); return; + } + + /* FIXME: with tdf#89957 it happened that the actual block size in column + * AP (shifted from AO) of sheet 'w' was smaller than the remembered group + * length and correct. This is just a very ugly workaround, the real cause + * is yet unknown, but at least don't crash in such case. The intermediate + * cause is that not all affected group area listeners are destroyed and + * newly created, so mpColumn still points to the old column that then has + * the content of a shifted column. Effectively this workaround has the + * consequence that the group area listener is fouled up and not all + * formula cells are notified.. */ + if (nBlockSize < static_cast<size_t>(mnGroupLen)) + { + SAL_WARN("sc.core","FormulaGroupAreaListener::collectFormulaCells() nBlockSize " << + nBlockSize << " < " << mnGroupLen << " mnGroupLen"); + const_cast<FormulaGroupAreaListener*>(this)->mnGroupLen = static_cast<SCROW>(nBlockSize); + } ScFormulaCell* const * ppEnd = pp + mnGroupLen; @@ -280,8 +302,9 @@ ScAddress FormulaGroupAreaListener::getTopCellPos() const const ScFormulaCell* FormulaGroupAreaListener::getTopCell() const { - const ScFormulaCell* const * pp = mpColumn->GetFormulaCellBlockAddress( mnTopCellRow); - assert(pp); + size_t nBlockSize = 0; + const ScFormulaCell* const * pp = mpColumn->GetFormulaCellBlockAddress( mnTopCellRow, nBlockSize); + SAL_WARN_IF(!pp, "sc", "GetFormulaCellBlockAddress not found"); return pp ? *pp : NULL; } |