check for NaN in Fraction
which can result from division by zero in earlier code, rather assert
explicitly than suffer from weird very large sal_Int64 values (which is
what NaN converts to, if we let it do the implicit conversion)
Change-Id: Id059b84906bbc90a4fa51489ca96dc0267bb9342
Reviewed-on: https://gerrit.libreoffice.org/42798
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
diff --git a/include/tools/fract.hxx b/include/tools/fract.hxx
index 68c0984..95aa5f5 100644
--- a/include/tools/fract.hxx
+++ b/include/tools/fract.hxx
@@ -22,6 +22,7 @@
#include <sal/types.h>
#include <tools/toolsdllapi.h>
#include <memory>
#include <type_traits>
class SvStream;
@@ -37,8 +38,14 @@ public:
Fraction();
Fraction( const Fraction & rFrac );
Fraction( Fraction && rFrac );
Fraction( sal_Int64 nNum, sal_Int64 nDen );
explicit Fraction( double dVal );
Fraction( double nNum, double nDen );
Fraction( sal_Int64 nNum, sal_Int64 nDen );
// just to prevent ambiguity between the sal_Int64 and double constructors
template<typename T1, typename T2> Fraction(
T1 nNum, T2 nDen,
typename std::enable_if<std::is_integral<T1>::value && std::is_integral<T2>::value, int>::type = 0)
: Fraction( sal_Int64(nNum), sal_Int64(nDen) ) {}
~Fraction();
bool IsValid() const;
diff --git a/tools/source/generic/fract.cxx b/tools/source/generic/fract.cxx
index 7d89ae81..1a78d4d 100644
--- a/tools/source/generic/fract.cxx
+++ b/tools/source/generic/fract.cxx
@@ -86,6 +86,27 @@ Fraction::Fraction( sal_Int64 nNum, sal_Int64 nDen ) : mpImpl(new Impl)
mpImpl->valid = true;
}
/**
* only here to prevent passing of NaN
*/
Fraction::Fraction( double nNum, double nDen ) : mpImpl(new Impl)
{
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 )
{
mpImpl->valid = false;
SAL_WARN( "tools.fraction", "'Fraction(" << nNum << ",0)' invalid fraction created" );
return;
}
mpImpl->value.assign( sal_Int64(nNum), sal_Int64(nDen));
mpImpl->valid = true;
}
Fraction::Fraction( double dVal ) : mpImpl(new Impl)
{
try
@@ -439,7 +460,8 @@ SvStream& WriteFraction( SvStream& rOStream, const Fraction& rFract )
static boost::rational<sal_Int32> rational_FromDouble(double dVal)
{
if ( dVal > std::numeric_limits<sal_Int32>::max() ||
dVal < std::numeric_limits<sal_Int32>::min() )
dVal < std::numeric_limits<sal_Int32>::min() ||
std::isnan(dVal) )
throw boost::bad_rational();
const sal_Int32 nMAX = std::numeric_limits<sal_Int32>::max() / 10;