sc/source/core/tool/interpr1.cxx | 330 +++++++++++++++++++-------------------- 1 file changed, 167 insertions(+), 163 deletions(-)
New commits: commit 69f9c57551120afbb7e2d877f8478148a0c545dc Author: Eike Rathke <er...@redhat.com> Date: Tue May 23 18:32:30 2017 +0200 svRefList always needs to be in a loop to be eventually popped from stack If it has more than one entries, rRefInList and rParam are incremented (effectively annulating a nParam--) and only the last entry pops the token from stack. This could had led to wrong references for other (previous) parameters. Change-Id: I4204d1be4da2e538cece20d92cb7cd96b7c8fa84 diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx index 4eb3e3bbe518..4618bddec326 100644 --- a/sc/source/core/tool/interpr1.cxx +++ b/sc/source/core/tool/interpr1.cxx @@ -5634,8 +5634,6 @@ void ScInterpreter::IterateParametersIfs( double(*ResultFunc)( const sc::ParamIf size_t nRowSize = 0; size_t nColSize = 0; double fVal = 0.0; - short nParam = 1; - size_t nRefInList = 0; SCCOL nDimensionCols = 0; SCROW nDimensionRows = 0; @@ -5723,8 +5721,8 @@ void ScInterpreter::IterateParametersIfs( double(*ResultFunc)( const sc::ParamIf } // take range - nParam = 1; - nRefInList = 0; + short nParam = nParamCount; + size_t nRefInList = 0; SCCOL nCol1 = 0; SCROW nRow1 = 0; SCTAB nTab1 = 0; @@ -5732,63 +5730,66 @@ void ScInterpreter::IterateParametersIfs( double(*ResultFunc)( const sc::ParamIf SCROW nRow2 = 0; SCTAB nTab2 = 0; ScMatrixRef pQueryMatrix; - switch ( GetStackType() ) + while (nParam-- == nParamCount) { - case svRefList : - { - ScRange aRange; - PopDoubleRef( aRange, nParam, nRefInList); - aRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2); - } + switch ( GetStackType() ) + { + case svRefList : + { + ScRange aRange; + PopDoubleRef( aRange, nParam, nRefInList); + aRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2); + } break; - case svDoubleRef : - PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 ); + case svDoubleRef : + PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 ); break; - case svSingleRef : - PopSingleRef( nCol1, nRow1, nTab1 ); - nCol2 = nCol1; - nRow2 = nRow1; - nTab2 = nTab1; + case svSingleRef : + PopSingleRef( nCol1, nRow1, nTab1 ); + nCol2 = nCol1; + nRow2 = nRow1; + nTab2 = nTab1; break; - case svMatrix: - case svExternalSingleRef: - case svExternalDoubleRef: - { - pQueryMatrix = PopMatrix(); - if (!pQueryMatrix) + case svMatrix: + case svExternalSingleRef: + case svExternalDoubleRef: { - PushError( FormulaError::IllegalParameter); - return; + pQueryMatrix = PopMatrix(); + if (!pQueryMatrix) + { + PushError( FormulaError::IllegalParameter); + return; + } + nCol1 = 0; + nRow1 = 0; + nTab1 = 0; + SCSIZE nC, nR; + pQueryMatrix->GetDimensions( nC, nR); + nCol2 = static_cast<SCCOL>(nC - 1); + nRow2 = static_cast<SCROW>(nR - 1); + nTab2 = 0; } - nCol1 = 0; - nRow1 = 0; - nTab1 = 0; - SCSIZE nC, nR; - pQueryMatrix->GetDimensions( nC, nR); - nCol2 = static_cast<SCCOL>(nC - 1); - nRow2 = static_cast<SCROW>(nR - 1); - nTab2 = 0; - } break; - default: - PushError( FormulaError::IllegalParameter); + default: + PushError( FormulaError::IllegalParameter); + return; + } + if ( nTab1 != nTab2 ) + { + PushError( FormulaError::IllegalArgument); return; - } - if ( nTab1 != nTab2 ) - { - PushError( FormulaError::IllegalArgument); - return; - } + } - // All reference ranges must be of same dimension and size. - if (!nDimensionCols) - nDimensionCols = nCol2 - nCol1 + 1; - if (!nDimensionRows) - nDimensionRows = nRow2 - nRow1 + 1; - if ((nDimensionCols != (nCol2 - nCol1 + 1)) || (nDimensionRows != (nRow2 - nRow1 + 1))) - { - PushError ( FormulaError::IllegalArgument); - return; + // All reference ranges must be of same dimension and size. + if (!nDimensionCols) + nDimensionCols = nCol2 - nCol1 + 1; + if (!nDimensionRows) + nDimensionRows = nRow2 - nRow1 + 1; + if ((nDimensionCols != (nCol2 - nCol1 + 1)) || (nDimensionRows != (nRow2 - nRow1 + 1))) + { + PushError ( FormulaError::IllegalArgument); + return; + } } // recalculate matrix values @@ -5884,142 +5885,145 @@ void ScInterpreter::IterateParametersIfs( double(*ResultFunc)( const sc::ParamIf // main range - only for AVERAGEIFS, SUMIFS, MINIFS and MAXIFS if (nParamCount == 1) { - nParam = 1; - nRefInList = 0; - bool bNull = true; - SCCOL nMainCol1 = 0; - SCROW nMainRow1 = 0; - SCTAB nMainTab1 = 0; - SCCOL nMainCol2 = 0; - SCROW nMainRow2 = 0; - SCTAB nMainTab2 = 0; - ScMatrixRef pMainMatrix; - switch ( GetStackType() ) + short nParam = nParamCount; + size_t nRefInList = 0; + while (nParam-- == nParamCount) { - case svRefList : - { - ScRange aRange; - PopDoubleRef( aRange, nParam, nRefInList); - aRange.GetVars( nMainCol1, nMainRow1, nMainTab1, nMainCol2, nMainRow2, nMainTab2); - } + bool bNull = true; + SCCOL nMainCol1 = 0; + SCROW nMainRow1 = 0; + SCTAB nMainTab1 = 0; + SCCOL nMainCol2 = 0; + SCROW nMainRow2 = 0; + SCTAB nMainTab2 = 0; + ScMatrixRef pMainMatrix; + switch ( GetStackType() ) + { + case svRefList : + { + ScRange aRange; + PopDoubleRef( aRange, nParam, nRefInList); + aRange.GetVars( nMainCol1, nMainRow1, nMainTab1, nMainCol2, nMainRow2, nMainTab2); + } break; - case svDoubleRef : - PopDoubleRef( nMainCol1, nMainRow1, nMainTab1, nMainCol2, nMainRow2, nMainTab2 ); + case svDoubleRef : + PopDoubleRef( nMainCol1, nMainRow1, nMainTab1, nMainCol2, nMainRow2, nMainTab2 ); break; - case svSingleRef : - PopSingleRef( nMainCol1, nMainRow1, nMainTab1 ); - nMainCol2 = nMainCol1; - nMainRow2 = nMainRow1; - nMainTab2 = nMainTab1; + case svSingleRef : + PopSingleRef( nMainCol1, nMainRow1, nMainTab1 ); + nMainCol2 = nMainCol1; + nMainRow2 = nMainRow1; + nMainTab2 = nMainTab1; break; - case svMatrix: - case svExternalSingleRef: - case svExternalDoubleRef: - { - pMainMatrix = PopMatrix(); - if (!pMainMatrix) + case svMatrix: + case svExternalSingleRef: + case svExternalDoubleRef: { - PushError( FormulaError::IllegalParameter); - return; + pMainMatrix = PopMatrix(); + if (!pMainMatrix) + { + PushError( FormulaError::IllegalParameter); + return; + } + nMainCol1 = 0; + nMainRow1 = 0; + nMainTab1 = 0; + SCSIZE nC, nR; + pMainMatrix->GetDimensions( nC, nR); + nMainCol2 = static_cast<SCCOL>(nC - 1); + nMainRow2 = static_cast<SCROW>(nR - 1); + nMainTab2 = 0; } - nMainCol1 = 0; - nMainRow1 = 0; - nMainTab1 = 0; - SCSIZE nC, nR; - pMainMatrix->GetDimensions( nC, nR); - nMainCol2 = static_cast<SCCOL>(nC - 1); - nMainRow2 = static_cast<SCROW>(nR - 1); - nMainTab2 = 0; - } break; - default: - PushError( FormulaError::IllegalParameter); + default: + PushError( FormulaError::IllegalParameter); + return; + } + if ( nMainTab1 != nMainTab2 ) + { + PushError( FormulaError::IllegalArgument); return; - } - if ( nMainTab1 != nMainTab2 ) - { - PushError( FormulaError::IllegalArgument); - return; - } - - // All reference ranges must be of same dimension and size. - if ((nDimensionCols != (nMainCol2 - nMainCol1 + 1)) || (nDimensionRows != (nMainRow2 - nMainRow1 + 1))) - { - PushError ( FormulaError::IllegalArgument); - return; - } - - if (nGlobalError != FormulaError::NONE) - { - PushError( nGlobalError); - return; // bail out - } + } - // end-result calculation - ScAddress aAdr; - aAdr.SetTab( nMainTab1 ); - if (pMainMatrix) - { - std::vector<double> aMainValues; - pMainMatrix->GetDoubleArray(aMainValues, false); // Map empty values to NaN's. - if (aResArray.size() != aMainValues.size()) + // All reference ranges must be of same dimension and size. + if ((nDimensionCols != (nMainCol2 - nMainCol1 + 1)) || (nDimensionRows != (nMainRow2 - nMainRow1 + 1))) { - PushError( FormulaError::IllegalArgument); + PushError ( FormulaError::IllegalArgument); return; } - std::vector<sal_uInt8>::const_iterator itRes = aResArray.begin(), itResEnd = aResArray.end(); - std::vector<double>::const_iterator itMain = aMainValues.begin(); - for (; itRes != itResEnd; ++itRes, ++itMain) + if (nGlobalError != FormulaError::NONE) { - if (*itRes != nQueryCount) - continue; + PushError( nGlobalError); + return; // bail out + } - fVal = *itMain; - if (GetDoubleErrorValue(fVal) == FormulaError::ElementNaN) - continue; + // end-result calculation + ScAddress aAdr; + aAdr.SetTab( nMainTab1 ); + if (pMainMatrix) + { + std::vector<double> aMainValues; + pMainMatrix->GetDoubleArray(aMainValues, false); // Map empty values to NaN's. + if (aResArray.size() != aMainValues.size()) + { + PushError( FormulaError::IllegalArgument); + return; + } - ++aRes.mfCount; - if (bNull && fVal != 0.0) + std::vector<sal_uInt8>::const_iterator itRes = aResArray.begin(), itResEnd = aResArray.end(); + std::vector<double>::const_iterator itMain = aMainValues.begin(); + for (; itRes != itResEnd; ++itRes, ++itMain) { - bNull = false; - aRes.mfMem = fVal; + if (*itRes != nQueryCount) + continue; + + fVal = *itMain; + if (GetDoubleErrorValue(fVal) == FormulaError::ElementNaN) + continue; + + ++aRes.mfCount; + if (bNull && fVal != 0.0) + { + bNull = false; + aRes.mfMem = fVal; + } + else + aRes.mfSum += fVal; + if ( aRes.mfMin > fVal ) + aRes.mfMin = fVal; + if ( aRes.mfMax < fVal ) + aRes.mfMax = fVal; } - else - aRes.mfSum += fVal; - if ( aRes.mfMin > fVal ) - aRes.mfMin = fVal; - if ( aRes.mfMax < fVal ) - aRes.mfMax = fVal; } - } - else - { - std::vector<sal_uInt8>::const_iterator itRes = aResArray.begin(); - for (size_t nCol = 0; nCol < nColSize; ++nCol) + else { - for (size_t nRow = 0; nRow < nRowSize; ++nRow, ++itRes) + std::vector<sal_uInt8>::const_iterator itRes = aResArray.begin(); + for (size_t nCol = 0; nCol < nColSize; ++nCol) { - if (*itRes == nQueryCount) + for (size_t nRow = 0; nRow < nRowSize; ++nRow, ++itRes) { - aAdr.SetCol( static_cast<SCCOL>(nCol) + nMainCol1); - aAdr.SetRow( static_cast<SCROW>(nRow) + nMainRow1); - ScRefCellValue aCell(*pDok, aAdr); - if (aCell.hasNumeric()) + if (*itRes == nQueryCount) { - fVal = GetCellValue(aAdr, aCell); - ++aRes.mfCount; - if ( bNull && fVal != 0.0 ) + aAdr.SetCol( static_cast<SCCOL>(nCol) + nMainCol1); + aAdr.SetRow( static_cast<SCROW>(nRow) + nMainRow1); + ScRefCellValue aCell(*pDok, aAdr); + if (aCell.hasNumeric()) { - bNull = false; - aRes.mfMem = fVal; + fVal = GetCellValue(aAdr, aCell); + ++aRes.mfCount; + if ( bNull && fVal != 0.0 ) + { + bNull = false; + aRes.mfMem = fVal; + } + else + aRes.mfSum += fVal; + if ( aRes.mfMin > fVal ) + aRes.mfMin = fVal; + if ( aRes.mfMax < fVal ) + aRes.mfMax = fVal; } - else - aRes.mfSum += fVal; - if ( aRes.mfMin > fVal ) - aRes.mfMin = fVal; - if ( aRes.mfMax < fVal ) - aRes.mfMax = fVal; } } } _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits