summaryrefslogtreecommitdiff
path: root/sc/source/core/tool/token.cxx
diff options
context:
space:
mode:
authorNoel Grandin <noel.grandin@collabora.co.uk>2019-12-13 15:59:51 +0200
committerNoel Grandin <noel.grandin@collabora.co.uk>2019-12-13 19:41:59 +0100
commit113444f59dc7690850919155b9b164b1a686bbe7 (patch)
tree90828ec324aabf60236f0785178c60144c2b4975 /sc/source/core/tool/token.cxx
parent3b8e554b69de349a20d10ec90b27ab71a013b464 (diff)
sc: rowcol: tdf#50916 create ScSheetLimits to hold by rtl::Reference
ScTokenArray sometimes outlives the ScDocument that created it, which means it accesses dead data when it tries to validate columns and rows. So create the ScSheetLimits class, which ScTokenArray can hold by reference counted pointer. Change-Id: Ic5771734fe4962d12f024fc1b29232124c14208a Reviewed-on: https://gerrit.libreoffice.org/85117 Tested-by: Jenkins Reviewed-by: Michael Meeks <michael.meeks@collabora.com>
Diffstat (limited to 'sc/source/core/tool/token.cxx')
-rw-r--r--sc/source/core/tool/token.cxx78
1 files changed, 43 insertions, 35 deletions
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index 332debee8d10..6fd70a6eaf23 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -350,7 +350,7 @@ bool ScRawToken::IsValidReference(const ScDocument* pDoc) const
return false;
}
-FormulaToken* ScRawToken::CreateToken(const ScDocument* pDoc) const
+FormulaToken* ScRawToken::CreateToken(ScSheetLimits& rLimits) const
{
#define IF_NOT_OPCODE_ERROR(o,c) SAL_WARN_IF((eOp!=o), "sc.core", #c "::ctor: OpCode " << static_cast<int>(eOp) << " lost, converted to " #o "; maybe inherit from FormulaToken instead!")
switch ( GetType() )
@@ -370,14 +370,14 @@ FormulaToken* ScRawToken::CreateToken(const ScDocument* pDoc) const
}
case svSingleRef :
if (eOp == ocPush)
- return new ScSingleRefToken(pDoc, aRef.Ref1 );
+ return new ScSingleRefToken(rLimits, aRef.Ref1 );
else
- return new ScSingleRefToken(pDoc, aRef.Ref1, eOp );
+ return new ScSingleRefToken(rLimits, aRef.Ref1, eOp );
case svDoubleRef :
if (eOp == ocPush)
- return new ScDoubleRefToken(pDoc, aRef );
+ return new ScDoubleRefToken(rLimits, aRef );
else
- return new ScDoubleRefToken(pDoc, aRef, eOp );
+ return new ScDoubleRefToken(rLimits, aRef, eOp );
case svMatrix :
IF_NOT_OPCODE_ERROR( ocPush, ScMatrixToken);
return new ScMatrixToken( pMat );
@@ -499,7 +499,7 @@ void DumpToken(formula::FormulaToken const & rToken)
}
#endif
-FormulaTokenRef extendRangeReference( const ScDocument* pDoc, FormulaToken & rTok1, FormulaToken & rTok2,
+FormulaTokenRef extendRangeReference( ScSheetLimits& rLimits, FormulaToken & rTok1, FormulaToken & rTok2,
const ScAddress & rPos, bool bReuseDoubleRef )
{
@@ -549,7 +549,7 @@ FormulaTokenRef extendRangeReference( const ScDocument* pDoc, FormulaToken & rTo
if (bExternal)
xRes = new ScExternalDoubleRefToken( rTok1.GetIndex(), rTok1.GetString(), aRef);
else
- xRes = new ScDoubleRefToken(pDoc, aRef);
+ xRes = new ScDoubleRefToken(rLimits, aRef);
}
else
{
@@ -575,7 +575,7 @@ FormulaTokenRef extendRangeReference( const ScDocument* pDoc, FormulaToken & rTo
return nullptr;
if (bExternal)
return nullptr; // external reference list not possible
- xRes = new ScDoubleRefToken(pDoc, (*pRefList)[0] );
+ xRes = new ScDoubleRefToken(rLimits, (*pRefList)[0] );
}
if (!xRes)
return nullptr; // shouldn't happen...
@@ -1678,7 +1678,7 @@ void ScTokenArray::CheckToken( const FormulaToken& r )
}
}
-bool ScTokenArray::ImplGetReference( const ScDocument* pDoc, ScRange& rRange, const ScAddress& rPos, bool bValidOnly ) const
+bool ScTokenArray::ImplGetReference( ScRange& rRange, const ScAddress& rPos, bool bValidOnly ) const
{
bool bIs = false;
if ( pCode && nLen == 1 )
@@ -1690,7 +1690,7 @@ bool ScTokenArray::ImplGetReference( const ScDocument* pDoc, ScRange& rRange, co
{
const ScSingleRefData& rRef = *static_cast<const ScSingleRefToken*>(pToken)->GetSingleRef();
rRange.aStart = rRange.aEnd = rRef.toAbs(rPos);
- bIs = !bValidOnly || pDoc->ValidAddress(rRange.aStart);
+ bIs = !bValidOnly || mxSheetLimits->ValidAddress(rRange.aStart);
}
else if ( pToken->GetType() == svDoubleRef )
{
@@ -1699,7 +1699,7 @@ bool ScTokenArray::ImplGetReference( const ScDocument* pDoc, ScRange& rRange, co
const ScSingleRefData& rRef2 = rCompl.Ref2;
rRange.aStart = rRef1.toAbs(rPos);
rRange.aEnd = rRef2.toAbs(rPos);
- bIs = !bValidOnly || pDoc->ValidRange(rRange);
+ bIs = !bValidOnly || mxSheetLimits->ValidRange(rRange);
}
}
}
@@ -1852,17 +1852,25 @@ bool ScTokenArray::IsInvariant() const
bool ScTokenArray::IsReference( ScRange& rRange, const ScAddress& rPos ) const
{
- return ImplGetReference(mpDoc, rRange, rPos, false);
+ return ImplGetReference(rRange, rPos, false);
}
bool ScTokenArray::IsValidReference( ScRange& rRange, const ScAddress& rPos ) const
{
- return ImplGetReference(mpDoc, rRange, rPos, true);
+ return ImplGetReference(rRange, rPos, true);
}
ScTokenArray::ScTokenArray(const ScDocument* pDoc) :
FormulaTokenArray(),
- mpDoc(pDoc),
+ mxSheetLimits(&pDoc->GetSheetLimits()),
+ mnHashValue(0)
+{
+ ResetVectorState();
+}
+
+ScTokenArray::ScTokenArray(ScSheetLimits& rLimits) :
+ FormulaTokenArray(),
+ mxSheetLimits(&rLimits),
mnHashValue(0)
{
ResetVectorState();
@@ -1909,7 +1917,7 @@ void ScTokenArray::Clear()
std::unique_ptr<ScTokenArray> ScTokenArray::Clone() const
{
- std::unique_ptr<ScTokenArray> p(new ScTokenArray(mpDoc));
+ std::unique_ptr<ScTokenArray> p(new ScTokenArray(*mxSheetLimits));
p->nLen = nLen;
p->nRPN = nRPN;
p->nMode = nMode;
@@ -1967,7 +1975,7 @@ std::unique_ptr<ScTokenArray> ScTokenArray::Clone() const
FormulaToken* ScTokenArray::AddRawToken( const ScRawToken& r )
{
- return Add( r.CreateToken(mpDoc) );
+ return Add( r.CreateToken(*mxSheetLimits) );
}
// Utility function to ensure that there is strict alternation of values and
@@ -2165,7 +2173,7 @@ void ScTokenArray::MergeRangeReference( const ScAddress & rPos )
(((p2 = PeekPrev(nIdx)) != nullptr) && p2->GetOpCode() == ocRange) &&
((p1 = PeekPrev(nIdx)) != nullptr))
{
- FormulaTokenRef p = extendRangeReference( mpDoc, *p1, *p3, rPos, true);
+ FormulaTokenRef p = extendRangeReference( *mxSheetLimits, *p1, *p3, rPos, true);
if (p)
{
p->IncRef();
@@ -2187,17 +2195,17 @@ FormulaToken* ScTokenArray::AddOpCode( OpCode e )
FormulaToken* ScTokenArray::AddSingleReference( const ScSingleRefData& rRef )
{
- return Add( new ScSingleRefToken(mpDoc, rRef ) );
+ return Add( new ScSingleRefToken( *mxSheetLimits, rRef ) );
}
FormulaToken* ScTokenArray::AddMatrixSingleReference( const ScSingleRefData& rRef )
{
- return Add( new ScSingleRefToken(mpDoc, rRef, ocMatRef ) );
+ return Add( new ScSingleRefToken(*mxSheetLimits, rRef, ocMatRef ) );
}
FormulaToken* ScTokenArray::AddDoubleReference( const ScComplexRefData& rRef )
{
- return Add( new ScDoubleRefToken(mpDoc, rRef ) );
+ return Add( new ScDoubleRefToken(*mxSheetLimits, rRef ) );
}
FormulaToken* ScTokenArray::AddMatrix( const ScMatrixRef& p )
@@ -2234,7 +2242,7 @@ FormulaToken* ScTokenArray::AddExternalDoubleReference( sal_uInt16 nFileId, cons
FormulaToken* ScTokenArray::AddColRowName( const ScSingleRefData& rRef )
{
- return Add( new ScSingleRefToken(mpDoc, rRef, ocColRowName ) );
+ return Add( new ScSingleRefToken(*mxSheetLimits, rRef, ocColRowName ) );
}
void ScTokenArray::AssignXMLString( const OUString &rText, const OUString &rFormulaNmsp )
@@ -2258,13 +2266,13 @@ bool ScTokenArray::GetAdjacentExtendOfOuterFuncRefs( SCCOLROW& nExtend,
switch ( eDir )
{
case DIR_BOTTOM :
- if ( rPos.Row() < mpDoc->MaxRow() )
+ if ( rPos.Row() < mxSheetLimits->mnMaxRow )
nRow = (nExtend = rPos.Row()) + 1;
else
return false;
break;
case DIR_RIGHT :
- if ( rPos.Col() < mpDoc->MaxCol() )
+ if ( rPos.Col() < mxSheetLimits->mnMaxCol )
nCol = static_cast<SCCOL>(nExtend = rPos.Col()) + 1;
else
return false;
@@ -4513,7 +4521,7 @@ void ScTokenArray::ClearTabDeleted( const ScAddress& rPos, SCTAB nStartTab, SCTA
namespace {
void checkBounds(
- const ScDocument* pDoc,
+ ScSheetLimits& rLimits,
const ScAddress& rPos, SCROW nGroupLen, const ScRange& rCheckRange,
const ScSingleRefData& rRef, std::vector<SCROW>& rBounds, const ScRange* pDeletedRange )
{
@@ -4549,7 +4557,7 @@ void checkBounds(
SCROW nOffset = pDeletedRange->aStart.Row() - aAbs.aStart.Row();
SCROW nRow = rPos.Row() + nOffset;
// Unlike for rCheckRange, for pDeletedRange nRow can be anywhere>=0.
- if (pDoc->ValidRow(nRow))
+ if (rLimits.ValidRow(nRow))
rBounds.push_back(nRow);
}
@@ -4574,7 +4582,7 @@ void checkBounds(
SCROW nOffset = pDeletedRange->aEnd.Row() + 1 - aAbs.aStart.Row();
SCROW nRow = rPos.Row() + nOffset;
// Unlike for rCheckRange, for pDeletedRange nRow can be ~anywhere.
- if (pDoc->ValidRow(nRow))
+ if (rLimits.ValidRow(nRow))
rBounds.push_back(nRow);
}
}
@@ -4612,7 +4620,7 @@ void checkBounds(
pDeletedRange = &aDeletedRange;
}
- checkBounds(&rCxt.mrDoc, rPos, nGroupLen, aCheckRange, rRef, rBounds, pDeletedRange);
+ checkBounds(rCxt.mrDoc.GetSheetLimits(), rPos, nGroupLen, aCheckRange, rRef, rBounds, pDeletedRange);
}
}
@@ -4671,14 +4679,14 @@ void ScTokenArray::CheckRelativeReferenceBounds(
case svSingleRef:
{
const ScSingleRefData& rRef = *p->GetSingleRef();
- checkBounds(mpDoc, rPos, nGroupLen, rRange, rRef, rBounds, nullptr);
+ checkBounds(*mxSheetLimits, rPos, nGroupLen, rRange, rRef, rBounds, nullptr);
}
break;
case svDoubleRef:
{
const ScComplexRefData& rRef = *p->GetDoubleRef();
- checkBounds(mpDoc, rPos, nGroupLen, rRange, rRef.Ref1, rBounds, nullptr);
- checkBounds(mpDoc, rPos, nGroupLen, rRange, rRef.Ref2, rBounds, nullptr);
+ checkBounds(*mxSheetLimits, rPos, nGroupLen, rRange, rRef.Ref1, rBounds, nullptr);
+ checkBounds(*mxSheetLimits, rPos, nGroupLen, rRange, rRef.Ref2, rBounds, nullptr);
}
break;
default:
@@ -4814,7 +4822,7 @@ void appendString( OUStringBuffer& rBuf, const OUString& rStr )
rBuf.append('"');
}
-void appendTokenByType( const ScDocument* pDoc, sc::TokenStringContext& rCxt, OUStringBuffer& rBuf, const FormulaToken& rToken,
+void appendTokenByType( ScSheetLimits& rLimits, sc::TokenStringContext& rCxt, OUStringBuffer& rBuf, const FormulaToken& rToken,
const ScAddress& rPos, bool bFromRangeName )
{
if (rToken.IsExternalRef())
@@ -4845,7 +4853,7 @@ void appendTokenByType( const ScDocument* pDoc, sc::TokenStringContext& rCxt, OU
return;
rCxt.mpRefConv->makeExternalRefStr(
- pDoc, rBuf, rPos, nFileId, aFileName, it->second, aTabName,
+ rLimits, rBuf, rPos, nFileId, aFileName, it->second, aTabName,
*rToken.GetDoubleRef());
}
break;
@@ -4883,7 +4891,7 @@ void appendTokenByType( const ScDocument* pDoc, sc::TokenStringContext& rCxt, OU
ScComplexRefData aRef;
aRef.Ref1 = rRef;
aRef.Ref2 = rRef;
- rCxt.mpRefConv->makeRefStr(pDoc, rBuf, rCxt.meGram, rPos, rCxt.maErrRef, rCxt.maTabNames, aRef, true,
+ rCxt.mpRefConv->makeRefStr(rLimits, rBuf, rCxt.meGram, rPos, rCxt.maErrRef, rCxt.maTabNames, aRef, true,
bFromRangeName);
}
else
@@ -4895,7 +4903,7 @@ void appendTokenByType( const ScDocument* pDoc, sc::TokenStringContext& rCxt, OU
if (rCxt.mpRefConv)
{
const ScComplexRefData& rRef = *rToken.GetDoubleRef();
- rCxt.mpRefConv->makeRefStr(pDoc, rBuf, rCxt.meGram, rPos, rCxt.maErrRef, rCxt.maTabNames, rRef, false,
+ rCxt.mpRefConv->makeRefStr(rLimits, rBuf, rCxt.meGram, rPos, rCxt.maErrRef, rCxt.maTabNames, rRef, false,
bFromRangeName);
}
else
@@ -5115,7 +5123,7 @@ OUString ScTokenArray::CreateString( sc::TokenStringContext& rCxt, const ScAddre
if (eOp < rCxt.mxOpCodeMap->getSymbolCount())
aBuf.append(rCxt.mxOpCodeMap->getSymbol(eOp));
- appendTokenByType(mpDoc, rCxt, aBuf, *pToken, rPos, IsFromRangeName());
+ appendTokenByType(*mxSheetLimits, rCxt, aBuf, *pToken, rPos, IsFromRangeName());
}
return aBuf.makeStringAndClear();