chart2/source/tools/PolynomialRegressionCurveCalculator.cxx | 2 - chart2/source/view/charttypes/PieChart.cxx | 2 - include/o3tl/safeint.hxx | 9 ++++++ include/vcl/outdev.hxx | 3 +- sc/inc/kahan.hxx | 5 ++- sc/source/core/tool/interpr2.cxx | 18 ++++++------ sc/source/core/tool/interpr3.cxx | 8 ++--- sc/source/core/tool/interpr5.cxx | 4 +- sc/source/core/tool/interpr6.cxx | 6 ++-- sc/source/core/tool/interpr8.cxx | 2 - sc/source/core/tool/subtotal.cxx | 2 - scaddins/source/analysis/analysishelper.cxx | 8 +---- scaddins/source/analysis/financial.cxx | 2 - 13 files changed, 40 insertions(+), 31 deletions(-)
New commits: commit 2df011d176a4f851de7e30fc0084f55b33478b2f Author: Caolán McNamara <caolan.mcnam...@collabora.com> AuthorDate: Sun Aug 17 11:53:34 2025 +0100 Commit: Caolán McNamara <caolan.mcnam...@collabora.com> CommitDate: Sun Aug 17 15:34:40 2025 +0200 cid#1664822 silence Uncaught exception Change-Id: I417bdfaf9b5bc09a3ff3472d288bc36dc2cb11d6 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/189825 Tested-by: Caolán McNamara <caolan.mcnam...@collabora.com> Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx index fb61ff86b123..4ec08b257bf2 100644 --- a/include/vcl/outdev.hxx +++ b/include/vcl/outdev.hxx @@ -61,6 +61,7 @@ #include <unotools/fontdefs.hxx> #include <cppuhelper/weakref.hxx> +#include <o3tl/deleter.hxx> #include <com/sun/star/drawing/LineCap.hpp> #include <com/sun/star/uno/Reference.h> @@ -1923,7 +1924,7 @@ protected: struct OutputDeviceRestoreStateGuard { OutputDevice& m_rDev; - ~OutputDeviceRestoreStateGuard() { m_rDev.Pop(); } + ~OutputDeviceRestoreStateGuard() { suppress_fun_call_w_exception(m_rDev.Pop()); } }; Push(nFlags); commit 23f77eb0e294013716c172a7ea92350253c3d6f3 Author: Caolán McNamara <caolan.mcnam...@collabora.com> AuthorDate: Thu Aug 14 09:19:34 2025 +0100 Commit: Caolán McNamara <caolan.mcnam...@collabora.com> CommitDate: Sun Aug 17 15:34:28 2025 +0200 cid#1660546 suppress Division or modulo by float zero in spreadsheet related code, similar to runtime cases of bin/sanitize-excludelist.txt but probably more dubious. also: cid#1660554 Division or modulo by float zero cid#1660545 Division or modulo by float zero cid#1660527 Division or modulo by float zero cid#1660501 Division or modulo by float zero cid#1660485 Division or modulo by float zero cid#1660442 Division or modulo by float zero cid#1660396 Division or modulo by float zero cid#1660241 Division or modulo by float zero cid#1660134 Division or modulo by float zero cid#1660066 Division or modulo by float zero cid#1659994 Division or modulo by float zero cid#1659979 Division or modulo by float zero cid#1659964 Division or modulo by float zero cid#1659940 Division or modulo by float zero cid#1659913 Division or modulo by float zero cid#1659893 Division or modulo by float zero cid#1659890 Division or modulo by float zero cid#1659868 Division or modulo by float zero cid#1659745 Division or modulo by float zero cid#1659721 Division or modulo by float zero cid#1659711 Division or modulo by float zero cid#1659611 Division or modulo by float zero cid#1659814 Division or modulo by float zero Change-Id: I29830cad3170e5e45348f7bd4e08f028d21a4543 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/189823 Tested-by: Caolán McNamara <caolan.mcnam...@collabora.com> Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> diff --git a/chart2/source/tools/PolynomialRegressionCurveCalculator.cxx b/chart2/source/tools/PolynomialRegressionCurveCalculator.cxx index f8921d73c266..1f2ea3e3e965 100644 --- a/chart2/source/tools/PolynomialRegressionCurveCalculator.cxx +++ b/chart2/source/tools/PolynomialRegressionCurveCalculator.cxx @@ -151,7 +151,7 @@ void SAL_CALL PolynomialRegressionCurveCalculator::recalculateRegression( double fSumXY = lcl_GetDotProduct(xVector, yVector); double fSumX2 = lcl_GetDotProduct(xVector, xVector); - double fSlope = fSumXY / fSumX2; + double fSlope = o3tl::div_allow_zero(fSumXY, fSumX2); if (!mForceIntercept) { diff --git a/chart2/source/view/charttypes/PieChart.cxx b/chart2/source/view/charttypes/PieChart.cxx index 3fc7968fa23f..812cfb66babe 100644 --- a/chart2/source/view/charttypes/PieChart.cxx +++ b/chart2/source/view/charttypes/PieChart.cxx @@ -1421,7 +1421,7 @@ void PieChart::createOneBar( rtl::Reference<SvxShapeGroupAnyD> xSeriesGroupShape_Shapes = getSeriesGroupShape(pSeries, xSeriesTarget); ///collect data point information (logic coordinates, style ): - double fY = pDataSrc->getData(pSeries, nPointIndex, eType) / barSum; + double fY = o3tl::div_allow_zero(pDataSrc->getData(pSeries, nPointIndex, eType), barSum); if( std::isnan(fY) ) continue; if(fY==0.0)//@todo: continue also if the resolution is too small diff --git a/include/o3tl/safeint.hxx b/include/o3tl/safeint.hxx index a57f5f269d09..94a109fa2799 100644 --- a/include/o3tl/safeint.hxx +++ b/include/o3tl/safeint.hxx @@ -234,6 +234,15 @@ template<typename T> [[nodiscard]] inline T sanitizing_min(T a, T b) return std::min(a, b); } +// For use when std::inf is an acceptable result +[[nodiscard]] inline double div_allow_zero(double a, double b) +{ +#if defined(__COVERITY__) && __COVERITY_MAJOR__ <= 2024 + assert(b != 0 && "suppress floating point divide_by_zero"); +#endif + return a / b; +} + // To sanitize in/de-crementing value where the result is known by the caller to be guaranteed to fit in // the source type range without over/under-flow [[nodiscard]] inline unsigned short sanitizing_inc(unsigned short value) diff --git a/sc/inc/kahan.hxx b/sc/inc/kahan.hxx index c2560635fbdf..de3014b42ed9 100644 --- a/sc/inc/kahan.hxx +++ b/sc/inc/kahan.hxx @@ -215,7 +215,10 @@ public: inline KahanSum operator*(double fTimes) const { return get() * fTimes; } - inline KahanSum operator/(const KahanSum& fDivides) const { return get() / fDivides.get(); } + inline KahanSum operator/(const KahanSum& fDivides) const + { + return o3tl::div_allow_zero(get(), fDivides.get()); + } inline KahanSum operator/(double fDivides) const { return get() / fDivides; } diff --git a/sc/source/core/tool/interpr2.cxx b/sc/source/core/tool/interpr2.cxx index c71bbc39d88d..a4e390e13fc1 100644 --- a/sc/source/core/tool/interpr2.cxx +++ b/sc/source/core/tool/interpr2.cxx @@ -1506,7 +1506,7 @@ void ScInterpreter::ScIRR() } SetError(nIterError); } - double xNew = x - fNom.get() / fDenom.get(); // x(i+1) = x(i)-f(x(i))/f'(x(i)) + double xNew = x - o3tl::div_allow_zero(fNom.get(), fDenom.get()); // x(i+1) = x(i)-f(x(i))/f'(x(i)) nItCount++; fEps = std::abs(xNew - x); x = xNew; @@ -1636,7 +1636,7 @@ void ScInterpreter::ScMIRR() PushError( nGlobalError ); else { - double fResult = -fNPV_reinvest.get() / fNPV_invest.get(); + double fResult = -o3tl::div_allow_zero(fNPV_reinvest.get(), fNPV_invest.get()); fResult *= pow( fRate1_reinvest, static_cast<double>( nCount - 1 ) ); fResult = pow( fResult, div( 1.0, (nCount - 1)) ); PushDouble( fResult - 1.0 ); @@ -1656,7 +1656,7 @@ void ScInterpreter::ScISPMT() if( nGlobalError != FormulaError::NONE ) PushError( nGlobalError); else - PushDouble( fInvest * fRate * (fPeriod / fTotal - 1.0) ); + PushDouble( fInvest * fRate * (o3tl::div_allow_zero(fPeriod, fTotal) - 1.0) ); } } @@ -1704,8 +1704,8 @@ void ScInterpreter::ScSYD() double fLife = GetDouble(); double fSalvage = GetDouble(); double fCost = GetDouble(); - double fSyd = ((fCost - fSalvage) * (fLife - fPer + 1.0)) / - ((fLife * (fLife + 1.0)) / 2.0); + double fSyd = o3tl::div_allow_zero((fCost - fSalvage) * (fLife - fPer + 1.0), + (fLife * (fLife + 1.0)) / 2.0); PushDouble(fSyd); } } @@ -1714,7 +1714,7 @@ double ScInterpreter::ScGetDDB(double fCost, double fSalvage, double fLife, double fPeriod, double fFactor) { double fDdb, fRate, fOldValue, fNewValue; - fRate = fFactor / fLife; + fRate = o3tl::div_allow_zero(fFactor, fLife); if (fRate >= 1.0) { fRate = 1.0; @@ -1941,7 +1941,7 @@ double ScInterpreter::ScGetPMT(double fRate, double fNper, double fPv, { double fPayment; if (fRate == 0.0) - fPayment = (fPv + fFv) / fNper; + fPayment = o3tl::div_allow_zero(fPv + fFv, fNper); else { if (bPayInAdvance) // payment in advance @@ -2029,9 +2029,9 @@ void ScInterpreter::ScNper() if ( fPV + fFV == 0.0 ) PushDouble( 0.0 ); else if (fRate == 0.0) - PushDouble(-(fPV + fFV)/fPmt); + PushDouble(-o3tl::div_allow_zero(fPV + fFV, fPmt)); else if (bPayInAdvance) - PushDouble(log(-(fRate*fFV-fPmt*(1.0+fRate))/(fRate*fPV+fPmt*(1.0+fRate))) + PushDouble(log(-o3tl::div_allow_zero(fRate*fFV-fPmt*(1.0+fRate), (fRate*fPV+fPmt*(1.0+fRate)))) / std::log1p(fRate)); else PushDouble(log(-(fRate*fFV-fPmt)/(fRate*fPV+fPmt)) / std::log1p(fRate)); diff --git a/sc/source/core/tool/interpr3.cxx b/sc/source/core/tool/interpr3.cxx index 505f551d73db..ba53101f5e16 100644 --- a/sc/source/core/tool/interpr3.cxx +++ b/sc/source/core/tool/interpr3.cxx @@ -257,7 +257,7 @@ double ScInterpreter::gauss(double x) else { static const double asympt[] = { -1.0, 1.0, -3.0, 15.0, -105.0 }; - nVal = 0.5 + phi(xAbs) * taylor(asympt, 4, 1.0 / (xAbs * xAbs)) / xAbs; + nVal = 0.5 + phi(xAbs) * o3tl::div_allow_zero(taylor(asympt, 4, o3tl::div_allow_zero(1.0, xAbs * xAbs)), xAbs); } if (x < 0.0) return -nVal; @@ -812,7 +812,7 @@ double ScInterpreter::GetBeta(double fAlpha, double fBeta) fA = fBeta; fB = fAlpha; } if (fA+fB < fMaxGammaArgument) // simple case - return GetGamma(fA)/GetGamma(fA+fB)*GetGamma(fB); + return o3tl::div_allow_zero(GetGamma(fA), GetGamma(fA+fB)) * GetGamma(fB); // need logarithm // GetLogGamma is not accurate enough, back to Lanczos for all three // GetGamma and arrange factors newly. @@ -3019,7 +3019,7 @@ void ScInterpreter::ScHarMean() } } if (nGlobalError == FormulaError::NONE) - PushDouble( nValCount / nVal.get() ); + PushDouble( o3tl::div_allow_zero(nValCount, nVal.get()) ); else PushError( nGlobalError); } @@ -3191,7 +3191,7 @@ void ScInterpreter::ScGeoMean() } } if (nGlobalError == FormulaError::NONE) - PushDouble(exp(nVal.get() / nValCount)); + PushDouble(exp(o3tl::div_allow_zero(nVal.get(), nValCount))); else PushError( nGlobalError); } diff --git a/sc/source/core/tool/interpr5.cxx b/sc/source/core/tool/interpr5.cxx index 15f013f33fb1..b660d53df1b5 100644 --- a/sc/source/core/tool/interpr5.cxx +++ b/sc/source/core/tool/interpr5.cxx @@ -2121,7 +2121,7 @@ void lcl_ApplyHouseholderTransformation(const ScMatrixRef& pMatA, SCSIZE nC, // ScMatrix matrices are zero based, index access (column,row) double fDenominator = lcl_GetColumnSumProduct(pMatA, nC, pMatA, nC, nC, nN); double fNumerator = lcl_GetColumnSumProduct(pMatA, nC, pMatY, 0, nC, nN); - double fFactor = 2.0 * (fNumerator/fDenominator); + double fFactor = 2.0 * o3tl::div_allow_zero(fNumerator, fDenominator); for (SCSIZE row = nC; row < nN; row++) pMatY->PutDouble( pMatY->GetDouble(row) - fFactor * pMatA->GetDouble(nC,row), row); @@ -2134,7 +2134,7 @@ void lcl_TApplyHouseholderTransformation(const ScMatrixRef& pMatA, SCSIZE nR, // ScMatrix matrices are zero based, index access (column,row) double fDenominator = lcl_TGetColumnSumProduct(pMatA, nR, pMatA, nR, nR, nN); double fNumerator = lcl_TGetColumnSumProduct(pMatA, nR, pMatY, 0, nR, nN); - double fFactor = 2.0 * (fNumerator/fDenominator); + double fFactor = 2.0 * o3tl::div_allow_zero(fNumerator, fDenominator); for (SCSIZE col = nR; col < nN; col++) pMatY->PutDouble( pMatY->GetDouble(col) - fFactor * pMatA->GetDouble(col,nR), col); diff --git a/sc/source/core/tool/interpr6.cxx b/sc/source/core/tool/interpr6.cxx index 2d6a38a3c6b1..6d9889841a97 100644 --- a/sc/source/core/tool/interpr6.cxx +++ b/sc/source/core/tool/interpr6.cxx @@ -96,7 +96,7 @@ double ScInterpreter::GetGammaContFraction( double fA, double fX ) double ScInterpreter::GetGammaSeries( double fA, double fX ) { double fDenomfactor = fA; - double fSummand = 1.0/fA; + double fSummand = o3tl::div_allow_zero(1.0, fA); double fSum = fSummand; int nCount=1; do @@ -171,7 +171,7 @@ double ScInterpreter::GetGammaDistPDF( double fX, double fAlpha, double fLambda const double fLogDblMax = log( ::std::numeric_limits<double>::max()); if (log(fXr) * (fAlpha-1.0) < fLogDblMax && fAlpha < fMaxGammaArgument) { - return pow( fXr, fAlpha-1.0) * exp(-fXr) / fLambda / GetGamma(fAlpha); + return o3tl::div_allow_zero(pow( fXr, fAlpha-1.0) * exp(-fXr) / fLambda, GetGamma(fAlpha)); } else { @@ -182,7 +182,7 @@ double ScInterpreter::GetGammaDistPDF( double fX, double fAlpha, double fLambda { if (fAlpha<fMaxGammaArgument) { - return pow( fXr, fAlpha-1.0) * exp(-fXr) / fLambda / GetGamma(fAlpha); + return o3tl::div_allow_zero(pow( fXr, fAlpha-1.0) * exp(-fXr) / fLambda, GetGamma(fAlpha)); } else { diff --git a/sc/source/core/tool/interpr8.cxx b/sc/source/core/tool/interpr8.cxx index 1c53c7ba4932..05e38e0f19c1 100644 --- a/sc/source/core/tool/interpr8.cxx +++ b/sc/source/core/tool/interpr8.cxx @@ -521,7 +521,7 @@ void ScETSForecastCalculation::calcAccuracyIndicators() int nCalcCount = mnCount - 1; mfMAE = fSumAbsErr.get() / nCalcCount; - mfMASE = fSumAbsErr.get() / ( nCalcCount * fSumDivisor.get() / ( nCalcCount - 1 ) ); + mfMASE = o3tl::div_allow_zero(fSumAbsErr.get(), nCalcCount * fSumDivisor.get() / ( nCalcCount - 1 )); mfMSE = fSumErrSq.get() / nCalcCount; mfRMSE = sqrt( mfMSE ); mfSMAPE = fSumAbsPercErr.get() * 2.0 / nCalcCount; diff --git a/sc/source/core/tool/subtotal.cxx b/sc/source/core/tool/subtotal.cxx index 4c213893b14d..ed9c6c478127 100644 --- a/sc/source/core/tool/subtotal.cxx +++ b/sc/source/core/tool/subtotal.cxx @@ -54,7 +54,7 @@ bool SubTotal::SafeDiv(double& fVal1, double fVal2) { bool bOk = true; SAL_MATH_FPEXCEPTIONS_OFF(); - fVal1 /= fVal2; + fVal1 = o3tl::div_allow_zero(fVal1, fVal2); if (!std::isfinite(fVal1)) { bOk = false; diff --git a/scaddins/source/analysis/analysishelper.cxx b/scaddins/source/analysis/analysishelper.cxx index 73673bd4e593..d228667e25b9 100644 --- a/scaddins/source/analysis/analysishelper.cxx +++ b/scaddins/source/analysis/analysishelper.cxx @@ -1065,9 +1065,7 @@ double GetYieldmat( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_ double y = 1.0 + fIssMat * fRate; y /= fPrice / 100.0 + fIssSet * fRate; y--; - y /= fSetMat; - - return y; + return o3tl::div_allow_zero(y, fSetMat); } @@ -1195,9 +1193,7 @@ double GetOddlyield( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal double y = fRedemp + fDCi * 100.0 * fRate / fFreq; y /= fPrice + fAi * 100.0 * fRate / fFreq; y--; - y *= fFreq / fDSCi; - - return y; + return y * o3tl::div_allow_zero(fFreq, fDSCi); } diff --git a/scaddins/source/analysis/financial.cxx b/scaddins/source/analysis/financial.cxx index 074d8ff4fe2d..dcc7f0554e9f 100644 --- a/scaddins/source/analysis/financial.cxx +++ b/scaddins/source/analysis/financial.cxx @@ -553,7 +553,7 @@ double SAL_CALL AnalysisAddIn::getXirr( do { fResultValue = lcl_sca_XirrResult( aValues, aDates, fResultRate ); - double fNewRate = fResultRate - fResultValue / lcl_sca_XirrResult_Deriv1( aValues, aDates, fResultRate ); + double fNewRate = fResultRate - o3tl::div_allow_zero(fResultValue, lcl_sca_XirrResult_Deriv1(aValues, aDates, fResultRate)); double fRateEps = fabs( fNewRate - fResultRate ); fResultRate = fNewRate; bContLoop = (fRateEps > fMaxEps) && (fabs( fResultValue ) > fMaxEps);