svl/source/numbers/zformat.cxx | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
New commits: commit 2b27652d2d7bd675fa355fb904755bf5fb312348 Author: Noel Grandin <[email protected]> AuthorDate: Mon Jan 26 20:12:37 2026 +0200 Commit: Noel Grandin <[email protected]> CommitDate: Tue Jan 27 08:38:36 2026 +0100 tdf#167892 fix hang formatting very small number on windows Workaround undefined behaviour where llvm/gcc produces different code from MSVC, resulting in oscillation in this algorithm. regression from commit 44d17f8feca372acd41142d1b607d3360282bf30 Author: Eike Rathke <[email protected]> Date: Tue Oct 13 21:41:45 2020 +0200 Resolves: tdf#137453 Implicit conversion from sal_uInt64 to sal_Int32 is bad.. Change-Id: I486e8caabcbf582cf94b47547efc89d1b206503e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/198163 Reviewed-by: Noel Grandin <[email protected]> Tested-by: Jenkins diff --git a/svl/source/numbers/zformat.cxx b/svl/source/numbers/zformat.cxx index 9d617058f436..8253bd4e9429 100644 --- a/svl/source/numbers/zformat.cxx +++ b/svl/source/numbers/zformat.cxx @@ -2853,7 +2853,7 @@ double SvNumberformat::GetRoundFractionValue ( double fNumber ) const void SvNumberformat::ImpGetFractionElements ( double& fNumber, sal_uInt16 nIx, double& fIntPart, sal_Int64& nFrac, sal_Int64& nDiv ) const { - if ( fNumber < 0.0 ) + if (fNumber < 0.0) fNumber = -fNumber; fIntPart = floor(fNumber); // Integral part fNumber -= fIntPart; // Fractional part @@ -2884,9 +2884,17 @@ void SvNumberformat::ImpGetFractionElements ( double& fNumber, sal_uInt16 nIx, { double fTemp = 1.0 / fRemainder; // 64bits precision required when fRemainder is very weak nPartialDenom = static_cast<sal_Int64>(floor(fTemp)); // due to floating point notation with double precision +#ifdef _WIN32 + // The fTemp value may be out of range for sal_Int64 (e.g. 1e+19), and the result of + // casting that is undefined. In practice, gcc/llvm gives us a large positive number, but MSVC may create + // a large negative number, which will make this algorithm oscillate, so apply a correction that makes + // MSVC end up with the same thing. There is probably a better algorithm to be used here. + if (nPartialDenom < 0) + nPartialDenom = -(nPartialDenom+1); +#endif fRemainder = fTemp - static_cast<double>(nPartialDenom); nDivNext = nPartialDenom * nDiv + nDivPrev; - if ( nDivNext <= nBasis ) // continue loop + if (nDivNext <= nBasis) // continue loop { nFracNext = nPartialDenom * nFrac + nFracPrev; nFracPrev = nFrac;
