From dce3f3406f4fde3e9896cd2b186b2e2924918ee5 Mon Sep 17 00:00:00 2001 From: Kefu Chai Date: Sun, 5 May 2024 10:30:54 +0800 Subject: [PATCH] Add patch for addressing a Boost.Multiprecision bug This change addresses the issue of https://github.com/boostorg/multiprecision/issues/553, the fix prevents an application from crash due to an exception thrown in a function marked `noexcept`, when converting a `cpp_int` to a float, if the value of this `cpp_int` cannot be represented with a float. this issue is a regression in Boost 1.79, see more details at https://github.com/boostorg/multiprecision/pull/618 Signed-off-by: Kefu Chai --- ...1.83-multiprecision-convert-noexcept.patch | 78 +++++++++++++++++++ boost.spec | 9 ++- 2 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 boost-1.83-multiprecision-convert-noexcept.patch diff --git a/boost-1.83-multiprecision-convert-noexcept.patch b/boost-1.83-multiprecision-convert-noexcept.patch new file mode 100644 index 0000000..cdf5a09 --- /dev/null +++ b/boost-1.83-multiprecision-convert-noexcept.patch @@ -0,0 +1,78 @@ +From ea786494db78efdf178cbe36810f3326156e3347 Mon Sep 17 00:00:00 2001 +From: Kefu Chai +Date: Fri, 3 May 2024 15:08:05 +0800 +Subject: [PATCH] make sure eval_convert_to() do not terminate with super large + number + +this change is a follow-up of d51f2e9dbb. it intends to +address the exception thrown in a noexcept functon. + +a minimal reproducer looks like + +```c++ + +int main() { + std::string s = "32767456456456456456545678943512357658768763546575675"; + boost::multiprecision::cpp_int num(s); + std::cout << num.convert_to() << std::endl; +} +``` + +since boost 1.79, the code above terminates like +``` +Program returned: 139 +Program stderr +terminate called after throwing an instance of 'boost::wrapexcept' + what(): Error in function float_next(float): Argument must be finite, but got inf +Program terminated with signal: SIGSEGV +``` + +because `float_next_imp()` throws 'boost::wrapexcept' +if the number is NAN of INF. and `eval_convert_to()` is marked as +`noexcept(boost::multiprecision::detail::is_arithmetic::value && + std::numeric_limits::has_infinity)`, +but only `overflow_error` is ignored in the policy passed to +`float_next()`. + +so, in this change, `std::domain_error` is ignored as well, so that +``num.convert_to()` returns a NaN in this case. + +Refs #553 + +Signed-off-by: Kefu Chai +--- + include/boost/multiprecision/cpp_int/misc.hpp | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/include/boost/multiprecision/cpp_int/misc.hpp b/include/boost/multiprecision/cpp_int/misc.hpp +index cdae2f75..a8a76400 100644 +--- a/boost/multiprecision/cpp_int/misc.hpp ++++ b/boost/multiprecision/cpp_int/misc.hpp +@@ -184,7 +184,9 @@ eval_convert_to(R* result, const cpp_int_backend + inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if::value && !is_trivial_cpp_int >::value, void>::type +-eval_convert_to(R* result, const cpp_int_backend& backend) noexcept(boost::multiprecision::detail::is_arithmetic::value && std::numeric_limits::has_infinity) ++eval_convert_to(R* result, const cpp_int_backend& backend) noexcept(boost::multiprecision::detail::is_arithmetic::value && ++ (std::numeric_limits::has_infinity || ++ std::numeric_limits::has_quiet_NaN)) + { + BOOST_MP_FLOAT128_USING using std::ldexp; + if (eval_is_zero(backend)) +@@ -244,10 +246,11 @@ eval_convert_to(R* result, const cpp_int_backend(bits)) || eval_bit_test(backend, static_cast(bits + 1))) + { + #ifdef BOOST_MP_MATH_AVAILABLE +- BOOST_IF_CONSTEXPR(std::numeric_limits::has_infinity) ++ BOOST_IF_CONSTEXPR(std::numeric_limits::has_infinity || std::numeric_limits::has_quiet_NaN) + { + // Must NOT throw: +- *result = boost::math::float_next(*result, boost::math::policies::make_policy(boost::math::policies::overflow_error())); ++ *result = boost::math::float_next(*result, boost::math::policies::make_policy(boost::math::policies::overflow_error(), ++ boost::math::policies::domain_error())); + } + else + { +-- +2.44.0 + diff --git a/boost.spec b/boost.spec index b61d3d9..87ff47d 100644 --- a/boost.spec +++ b/boost.spec @@ -46,7 +46,7 @@ Name: boost %global real_name boost Summary: The free peer-reviewed portable C++ source libraries Version: 1.83.0 -Release: 3%{?dist} +Release: 4%{?dist} License: BSL-1.0 AND MIT AND Python-2.0.1 # Replace each . with _ in %%{version} @@ -162,6 +162,9 @@ Patch7: boost-1.81.0-random-test-fixes.patch Patch8: boost-1.83-regex-test-fixes.patch +# https://github.com/boostorg/multiprecision/commit/ea786494db78efdf178cbe36810f3326156e3347 +Patch9: boost-1.83-multiprecision-convert-noexcept.patch + %bcond_with tests %bcond_with docs_generated @@ -1291,6 +1294,10 @@ fi %{_mandir}/man1/b2.1* %changelog +* Sun May 05 2024 Kefu Chai - 1.83.0-4 +- Add patch for Boost.Multiprecision bug + See https://github.com/boostorg/multiprecision/pull/618 + * Wed Jan 31 2024 Pete Walter - 1.83.0-3 - Rebuild for ICU 74