boost/boost-1.83-multiprecision-convert-noexcept.patch
Kefu Chai dce3f3406f 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 <tchaikov@gmail.com>
2024-05-05 10:30:54 +08:00

78 lines
4 KiB
Diff

From ea786494db78efdf178cbe36810f3326156e3347 Mon Sep 17 00:00:00 2001
From: Kefu Chai <tchaikov@gmail.com>
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<float>() << 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<std::domain_error>'
what(): Error in function float_next<float>(float): Argument must be finite, but got inf
Program terminated with signal: SIGSEGV
```
because `float_next_imp()` throws 'boost::wrapexcept<std::domain_error>'
if the number is NAN of INF. and `eval_convert_to()` is marked as
`noexcept(boost::multiprecision::detail::is_arithmetic<R>::value &&
std::numeric_limits<R>::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<float>()` returns a NaN in this case.
Refs #553
Signed-off-by: Kefu Chai <tchaikov@gmail.com>
---
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<MinBits1, MaxBits1, SignType1,
template <class R, std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_floating_point<R>::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, void>::type
-eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& backend) noexcept(boost::multiprecision::detail::is_arithmetic<R>::value && std::numeric_limits<R>::has_infinity)
+eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& backend) noexcept(boost::multiprecision::detail::is_arithmetic<R>::value &&
+ (std::numeric_limits<R>::has_infinity ||
+ std::numeric_limits<R>::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<MinBits1, MaxBits1, SignType1,
if ((eval_lsb_imp(backend) < static_cast<std::size_t>(bits)) || eval_bit_test(backend, static_cast<std::size_t>(bits + 1)))
{
#ifdef BOOST_MP_MATH_AVAILABLE
- BOOST_IF_CONSTEXPR(std::numeric_limits<R>::has_infinity)
+ BOOST_IF_CONSTEXPR(std::numeric_limits<R>::has_infinity || std::numeric_limits<R>::has_quiet_NaN)
{
// Must NOT throw:
- *result = boost::math::float_next(*result, boost::math::policies::make_policy(boost::math::policies::overflow_error<boost::math::policies::ignore_error>()));
+ *result = boost::math::float_next(*result, boost::math::policies::make_policy(boost::math::policies::overflow_error<boost::math::policies::ignore_error>(),
+ boost::math::policies::domain_error<boost::math::policies::ignore_error>()));
}
else
{
--
2.44.0