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;