extensions/source/propctrlr/standardcontrol.cxx | 4 +--- include/o3tl/float_int_conversion.hxx | 18 ++++++++++++++++-- oox/source/vml/vmlformatting.cxx | 9 +-------- vcl/source/window/scrwnd.cxx | 15 ++------------- vcl/source/window/window2.cxx | 7 +------ 5 files changed, 21 insertions(+), 32 deletions(-)
New commits: commit 2cdcf5805b32098e75285015b57bf0f890723e41 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Wed Aug 25 10:20:48 2021 +0200 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Wed Aug 25 17:12:28 2021 +0200 Use o3tl::saturating_cast here These were of type long previously, with corresponding limits of LONG_MIN/MAX; in commit 3aef606f2758172a27718a06fea0ff9080e4d80f, they were changed to tools::Long, but without adapting limits accordingly. This adapts the limits to std::numeric_limits<tools::Long>::min()/max(). Change-Id: Ief4ee0a6219c837e1d971273da698ab07fa8a1e4 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/120984 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> diff --git a/vcl/source/window/scrwnd.cxx b/vcl/source/window/scrwnd.cxx index 7be0cd6074cf..21bbb7f787de 100644 --- a/vcl/source/window/scrwnd.cxx +++ b/vcl/source/window/scrwnd.cxx @@ -217,19 +217,8 @@ void ImplWheelWindow::ImplRecalcScrollValues() double fValX = static_cast<double>(mnActDeltaX) * nMult; double fValY = static_cast<double>(mnActDeltaY) * nMult; - if( !o3tl::convertsToAtMost(fValX, LONG_MAX) ) - mnActDeltaX = LONG_MAX; - else if( !o3tl::convertsToAtLeast(fValX, LONG_MIN) ) - mnActDeltaX = LONG_MIN; - else - mnActDeltaX = static_cast<tools::Long>(fValX); - - if( !o3tl::convertsToAtMost(fValY, LONG_MAX) ) - mnActDeltaY = LONG_MAX; - else if( !o3tl::convertsToAtLeast(fValY, LONG_MIN) ) - mnActDeltaY = LONG_MIN; - else - mnActDeltaY = static_cast<tools::Long>(fValY); + mnActDeltaX = o3tl::saturating_cast<tools::Long>(fValX); + mnActDeltaY = o3tl::saturating_cast<tools::Long>(fValY); } } } diff --git a/vcl/source/window/window2.cxx b/vcl/source/window/window2.cxx index 1db7b7aaf280..dd3a5fe05b28 100644 --- a/vcl/source/window/window2.cxx +++ b/vcl/source/window/window2.cxx @@ -588,12 +588,7 @@ static void lcl_HandleScrollHelper( ScrollBar* pScrl, double nN, bool isMultiply const double fVal = nNewPos - nN; - if ( !o3tl::convertsToAtLeast(fVal, LONG_MIN) ) - nNewPos = LONG_MIN; - else if ( !o3tl::convertsToAtMost(fVal, LONG_MAX) ) - nNewPos = LONG_MAX; - else - nNewPos = static_cast<tools::Long>(fVal); + nNewPos = o3tl::saturating_cast<tools::Long>(fVal); } pScrl->DoScroll( nNewPos ); commit e9ab5a5e4e725a348a4276b72fda63cdac2a131c Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Tue Aug 24 15:58:15 2021 +0200 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Wed Aug 25 17:12:14 2021 +0200 Introduce o3tl::saturating_cast for floating-point->integer conversion Change-Id: I73191e5ab25fdd9fd8a788db9858b5eb9d3ab955 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/120885 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> diff --git a/extensions/source/propctrlr/standardcontrol.cxx b/extensions/source/propctrlr/standardcontrol.cxx index 584c66889348..8c33d0598711 100644 --- a/extensions/source/propctrlr/standardcontrol.cxx +++ b/extensions/source/propctrlr/standardcontrol.cxx @@ -235,9 +235,7 @@ namespace pcr for ( sal_uInt16 d = 0; d < nDigits; ++d ) n *= 10; - if ( !o3tl::convertsToAtMost(n, std::numeric_limits<int>::max()) ) - return std::numeric_limits<int>::max(); - return static_cast<int>(n); + return o3tl::saturating_cast<int>(n); } static double ImplCalcDoubleValue( int nValue, sal_uInt16 nDigits ) diff --git a/include/o3tl/float_int_conversion.hxx b/include/o3tl/float_int_conversion.hxx index dfaea5ce3bd2..36bce97dd742 100644 --- a/include/o3tl/float_int_conversion.hxx +++ b/include/o3tl/float_int_conversion.hxx @@ -20,7 +20,7 @@ namespace o3tl // Return true iff `value` of floating-point type `F` converts to a value of integral type `I` no // smaller than `min`: template <typename F, typename I> -std::enable_if_t<std::is_floating_point_v<F> && std::is_integral_v<I>, bool> +constexpr std::enable_if_t<std::is_floating_point_v<F> && std::is_integral_v<I>, bool> convertsToAtLeast(F value, I min) { // If `F(min)`, `F(min) - F(1)` are too large in magnitude for `F`'s precision, then they either @@ -33,7 +33,7 @@ convertsToAtLeast(F value, I min) // Return true iff `value` of floating-point type `F` converts to a value of integral type `I` no // larger than `max`: template <typename F, typename I> -std::enable_if_t<std::is_floating_point_v<F> && std::is_integral_v<I>, bool> +constexpr std::enable_if_t<std::is_floating_point_v<F> && std::is_integral_v<I>, bool> convertsToAtMost(F value, I max) { // If `F(max)`, `F(max) + F(1)` are too large in magnitude for `F`'s precision, then they either @@ -43,6 +43,20 @@ convertsToAtMost(F value, I max) return value < F(max) + F(1); } +// Casts a floating-point to an integer, avoiding overflow. Used like: +// sal_Int64 n = o3tl::saturating_cast<sal_Int64>(f); +template <typename I, typename F> +constexpr std::enable_if_t<std::is_floating_point_v<F> && std::is_integral_v<I>, I> +saturating_cast(F f) +{ + if constexpr (std::is_signed_v<I>) + if (!convertsToAtLeast(f, std::numeric_limits<I>::min())) + return std::numeric_limits<I>::min(); + if (!convertsToAtMost(f, std::numeric_limits<I>::max())) + return std::numeric_limits<I>::max(); + return f; +} + // Return `value` of floating-point type `F` rounded to the nearest integer away from zero (which // can be useful in calls to convertsToAtLeast/Most(roundAway(x), n), to reject x that are // smaller/larger than n because they have a fractional part): diff --git a/oox/source/vml/vmlformatting.cxx b/oox/source/vml/vmlformatting.cxx index b7dc37b5e940..ef7e692838fe 100644 --- a/oox/source/vml/vmlformatting.cxx +++ b/oox/source/vml/vmlformatting.cxx @@ -201,14 +201,7 @@ sal_Int64 ConversionHelper::decodeMeasureToEmu( const GraphicHelper& rGraphicHel OSL_FAIL( "ConversionHelper::decodeMeasureToEmu - unknown measure unit" ); fValue = nRefValue; } - fValue += 0.5; - if (!o3tl::convertsToAtMost(fValue, std::numeric_limits<sal_Int64>::max())) { - return std::numeric_limits<sal_Int64>::max(); - } - if (!o3tl::convertsToAtLeast(fValue, std::numeric_limits<sal_Int64>::min())) { - return std::numeric_limits<sal_Int64>::min(); - } - return static_cast< sal_Int64 >( fValue ); + return o3tl::saturating_cast< sal_Int64 >( fValue + 0.5 ); } sal_Int32 ConversionHelper::decodeMeasureToHmm( const GraphicHelper& rGraphicHelper,