Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exception in cpp_int convert_to terminates program #553

Closed
martindolezal opened this issue May 12, 2023 · 0 comments · Fixed by #555
Closed

Exception in cpp_int convert_to terminates program #553

martindolezal opened this issue May 12, 2023 · 0 comments · Fixed by #555

Comments

@martindolezal
Copy link

martindolezal commented May 12, 2023

See the following code: https://godbolt.org/z/cs6cbjnPr

#include <boost/multiprecision/cpp_int.hpp>
#include <iostream>

int main() {
    std::string strNumber = "179769313486231590617005494896502488139538923424507473845653439431848569886227202866765261632299351819569917639009010788373365912036255753178371299382143631760131695224907130882552454362167933328609537509415576609030163673758148226168953269623548572115351901405836315903312675793605327103910016259918212890625";
    boost::multiprecision::cpp_int number(strNumber);

    try {
        std::cout << number.convert_to<double>() << "\n";
    } catch (...) {
        std::cout << "some exception caught" << "\n";
    }
    
    std::cout << "finished" << "\n";
}

convert_to<double>() throws exception here, but it terminates the program, cannot be caught. It seems to be due to noexcept qualifier somewhere on the way, probably eval_convert_to in cpp_int/misc.hpp

The behavior change between boost 1.78 and boost 1.79.

@martindolezal martindolezal changed the title Exception in cpp_int::convert_to terminates program Exception in cpp_int convert_to terminates program May 12, 2023
@mclow mclow transferred this issue from boostorg/boost May 12, 2023
tchaikov added a commit to tchaikov/multiprecision that referenced this issue May 3, 2024
this change is a follow-up of d51f2e9. 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 boostorg#553

Signed-off-by: Kefu Chai <[email protected]>
tchaikov added a commit to tchaikov/multiprecision that referenced this issue May 4, 2024
this change is a follow-up of d51f2e9. 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 boostorg#553

Signed-off-by: Kefu Chai <[email protected]>
avikivity added a commit to avikivity/scylladb that referenced this issue May 6, 2024
…rs to floats

In [1] a bug casting large multiprecision integers to floats is documented. Until
the fix propagates, work around it by detecting the conditions that trigger the bug
and returning the expected result.

Fixes scylladb#18508

[1] boostorg/multiprecision#553
avikivity added a commit to avikivity/scylladb that referenced this issue May 6, 2024
…rs to floats

In [1] a bug casting large multiprecision integers to floats is documented (note that it
received two fixes, the most recent and relevant is [2]). Until the fix propagates, work
around it by detecting the conditions that trigger the bug and returning the expected result.

Fixes scylladb#18508

[1] boostorg/multiprecision#553
[2] boostorg/multiprecision@ea78649
avikivity added a commit to avikivity/scylladb that referenced this issue May 12, 2024
…integers to floats behavior

In [1] a bug casting large multiprecision integers to floats is documented (note that it
received two fixes, the most recent and relevant is [2]). Even with the fix, boost now
returns NaN instead of ±∞ as it did before [3].

Since we cannot rely on boost, detect the conditions that trigger the bug and return
the expected result.

The unit test is extended to cover large negative numbers.

Boost version behavior:
 - 1.78 - returns ±∞
 - 1.79 - terminates
 - 1.79 + fix - returns NaN

Fixes scylladb#18508

[1] boostorg/multiprecision#553
[2] boostorg/multiprecision@ea78649
[3] boostorg/math#1132
nyh pushed a commit to scylladb/scylladb that referenced this issue May 13, 2024
…integers to floats behavior

In [1] a bug casting large multiprecision integers to floats is documented (note that it
received two fixes, the most recent and relevant is [2]). Even with the fix, boost now
returns NaN instead of ±∞ as it did before [3].

Since we cannot rely on boost, detect the conditions that trigger the bug and return
the expected result.

The unit test is extended to cover large negative numbers.

Boost version behavior:
 - 1.78 - returns ±∞
 - 1.79 - terminates
 - 1.79 + fix - returns NaN

Fixes #18508

[1] boostorg/multiprecision#553
[2] boostorg/multiprecision@ea78649
[3] boostorg/math#1132

Closes #18532
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant