sc/source/filter/excel/xeformula.cxx | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-)
New commits: commit f205403ff4efae613e87b07e7345ec20e96f68f1 Author: Caolán McNamara <caol...@redhat.com> AuthorDate: Fri Feb 17 11:00:52 2023 +0000 Commit: Caolán McNamara <caol...@redhat.com> CommitDate: Fri Feb 17 12:30:39 2023 +0000 crashtesting: crash on export of forum-mso-en4-568138.xlsx to xls recurses to death warn:legacy.osl:186588:186588:sc/source/filter/excel/xeformula.cxx:518: XclExpFmlaCompImpl::CreateFormula - unknown garbage behind formula warn:legacy.osl:186588:186588:sc/source/filter/excel/xeformula.cxx:518: XclExpFmlaCompImpl::CreateFormula - unknown garbage behind formula warn:legacy.osl:186588:186588:sc/source/filter/excel/xeformula.cxx:2235: XclExpFmlaCompImpl::PopOperandPos - token stack broken Segmentation fault (core dumped) Change-Id: I17172be42c9992ceb3a90c5a92344a58328dc483 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/147204 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caol...@redhat.com> diff --git a/sc/source/filter/excel/xeformula.cxx b/sc/source/filter/excel/xeformula.cxx index d44e13c41935..71f5056beb93 100644 --- a/sc/source/filter/excel/xeformula.cxx +++ b/sc/source/filter/excel/xeformula.cxx @@ -325,7 +325,8 @@ private: const ScAddress* pScBasePos, XclExpRefLog* pRefLog ); void RecalcTokenClasses(); - void RecalcTokenClass( const XclExpTokenConvInfo& rConvInfo, XclFuncParamConv ePrevConv, XclExpClassConv ePrevClassConv, bool bWasRefClass ); + void RecalcTokenClass( const XclExpTokenConvInfo& rConvInfo, XclFuncParamConv ePrevConv, XclExpClassConv ePrevClassConv, bool bWasRefClass, + o3tl::sorted_vector<const XclExpTokenConvInfo*>& rSeenTokens ); void FinalizeFormula(); XclTokenArrayRef CreateTokenArray(); @@ -634,7 +635,8 @@ void XclExpFmlaCompImpl::RecalcTokenClasses() XclFuncParamConv eParamConv = bNameFmla ? EXC_PARAMCONV_ARR : EXC_PARAMCONV_VAL; XclExpClassConv eClassConv = bNameFmla ? EXC_CLASSCONV_ARR : EXC_CLASSCONV_VAL; XclExpTokenConvInfo aConvInfo = { PopOperandPos(), eParamConv, !bNameFmla }; - RecalcTokenClass( aConvInfo, eParamConv, eClassConv, bNameFmla ); + o3tl::sorted_vector<const XclExpTokenConvInfo*> aSeenTokens; + RecalcTokenClass(aConvInfo, eParamConv, eClassConv, bNameFmla, aSeenTokens); } // clear operand vectors (calls to the expensive InsertZeros() may follow) @@ -643,9 +645,19 @@ void XclExpFmlaCompImpl::RecalcTokenClasses() } void XclExpFmlaCompImpl::RecalcTokenClass( const XclExpTokenConvInfo& rConvInfo, - XclFuncParamConv ePrevConv, XclExpClassConv ePrevClassConv, bool bWasRefClass ) + XclFuncParamConv ePrevConv, XclExpClassConv ePrevClassConv, bool bWasRefClass, + o3tl::sorted_vector<const XclExpTokenConvInfo*>& rSeenTokens ) { OSL_ENSURE( rConvInfo.mnTokPos < GetSize(), "XclExpFmlaCompImpl::RecalcTokenClass - invalid token position" ); + + const bool bAlreadySeen = !rSeenTokens.insert(&rConvInfo).second; + if (bAlreadySeen) + { + SAL_WARN("sc.filter", "XclExpFmlaCompImpl::RecalcTokenClass: loop in nested operands"); + return; + } + rSeenTokens.insert(&rConvInfo); + sal_uInt8& rnTokenId = mxData->maTokVec[ rConvInfo.mnTokPos ]; sal_uInt8 nTokClass = GetTokenClass( rnTokenId ); @@ -752,7 +764,7 @@ void XclExpFmlaCompImpl::RecalcTokenClass( const XclExpTokenConvInfo& rConvInfo, if( rConvInfo.mnTokPos < mxData->maOpListVec.size() ) if( const XclExpOperandList* pOperands = mxData->maOpListVec[ rConvInfo.mnTokPos ].get() ) for( const auto& rOperand : *pOperands ) - RecalcTokenClass( rOperand, eConv, eClassConv, nTokClass == EXC_TOKCLASS_REF ); + RecalcTokenClass( rOperand, eConv, eClassConv, nTokClass == EXC_TOKCLASS_REF, rSeenTokens ); } void XclExpFmlaCompImpl::FinalizeFormula()