diff options
author | Noel Grandin <noel.grandin@collabora.co.uk> | 2023-04-17 13:24:25 +0200 |
---|---|---|
committer | Noel Grandin <noel.grandin@collabora.co.uk> | 2023-04-18 07:51:38 +0200 |
commit | b1684730ccbbca83df4dcb07d4759eebebbc4d66 (patch) | |
tree | 1020c7ddf124777f22a138e2741958b52c173bb1 /tools | |
parent | 7c36c5fdfdfeab9d15ea733fe2a831cd4ff25d27 (diff) |
tdf#143200 assert when pasting a cell to a large-height range
The values are unfortunately genuinely outside the range that our
Fraction class can work with.
So do the least-bad thing for now, and reduce the magnitude of the
values until they fit.
Change-Id: Iedc34e9767b3d4a502f5d84efcdebc96c6514cac
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150493
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/source/generic/fract.cxx | 44 |
1 files changed, 22 insertions, 22 deletions
diff --git a/tools/source/generic/fract.cxx b/tools/source/generic/fract.cxx index 4acd46cec404..a583e75a7cac 100644 --- a/tools/source/generic/fract.cxx +++ b/tools/source/generic/fract.cxx @@ -49,24 +49,36 @@ static boost::rational<sal_Int32> toRational(sal_Int32 n, sal_Int32 d) return boost::rational<sal_Int32>(n, d); } +static constexpr bool isOutOfRange(sal_Int64 nNum) +{ + return nNum < std::numeric_limits<sal_Int32>::min() + || nNum > std::numeric_limits<sal_Int32>::max(); +} + // Initialized by setting nNum as nominator and nDen as denominator // Negative values in the denominator are invalid and cause the // inversion of both nominator and denominator signs // in order to return the correct value. Fraction::Fraction( sal_Int64 nNum, sal_Int64 nDen ) : mnNumerator(nNum), mnDenominator(nDen) { - assert( nNum >= std::numeric_limits<sal_Int32>::min() ); - assert( nNum <= std::numeric_limits<sal_Int32>::max( )); - assert( nDen >= std::numeric_limits<sal_Int32>::min() ); - assert( nDen <= std::numeric_limits<sal_Int32>::max( )); - if ( nDen == 0 ) + if ( isOutOfRange(nNum) || isOutOfRange(nDen) ) + { + // tdf#143200 + SAL_WARN("tools.fraction", "values outside of range we can represent, doing reduction, which will reduce precision"); + do + { + mnNumerator /= 2; + mnDenominator /= 2; + } while (isOutOfRange(mnNumerator) || isOutOfRange(mnDenominator)); + } + if ( mnDenominator == 0 ) { mbValid = false; SAL_WARN( "tools.fraction", "'Fraction(" << nNum << ",0)' invalid fraction created" ); return; } - if ((nDen == -1 && nNum == std::numeric_limits<sal_Int32>::min()) || - (nNum == -1 && nDen == std::numeric_limits<sal_Int32>::min())) + else if ((nDen == -1 && nNum == std::numeric_limits<sal_Int32>::min()) || + (nNum == -1 && nDen == std::numeric_limits<sal_Int32>::min())) { mbValid = false; SAL_WARN("tools.fraction", "'Fraction(" << nNum << "," << nDen << ")' invalid fraction created"); @@ -77,21 +89,9 @@ Fraction::Fraction( sal_Int64 nNum, sal_Int64 nDen ) : mnNumerator(nNum), mnDeno /** * only here to prevent passing of NaN */ -Fraction::Fraction( double nNum, double nDen ) : mnNumerator(sal_Int64(nNum)), mnDenominator(sal_Int64(nDen)) -{ - assert( !std::isnan(nNum) ); - assert( !std::isnan(nDen) ); - assert( nNum >= std::numeric_limits<sal_Int32>::min() ); - assert( nNum <= std::numeric_limits<sal_Int32>::max( )); - assert( nDen >= std::numeric_limits<sal_Int32>::min() ); - assert( nDen <= std::numeric_limits<sal_Int32>::max( )); - if ( nDen == 0 ) - { - mbValid = false; - SAL_WARN( "tools.fraction", "'Fraction(" << nNum << ",0)' invalid fraction created" ); - return; - } -} +Fraction::Fraction( double nNum, double nDen ) + : Fraction(sal_Int64(nNum), sal_Int64(nDen)) +{} Fraction::Fraction( double dVal ) { |