Skip to content

Commit

Permalink
Merge pull request #2748 from jamescowens/fix_fraction_class_addition…
Browse files Browse the repository at this point in the history
…_overflow

util: Adjust Fraction class addition overload overflow tests
  • Loading branch information
jamescowens committed Mar 4, 2024
2 parents 3044941 + 1269669 commit 325a127
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 5 deletions.
8 changes: 4 additions & 4 deletions src/test/util_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1648,8 +1648,8 @@ BOOST_AUTO_TEST_CASE(util_Fraction_addition_overflow_2)

BOOST_AUTO_TEST_CASE(util_Fraction_addition_overflow_3)
{
Fraction lhs(-(std::numeric_limits<int64_t>::max() / 2 + 1), 1);
Fraction rhs(-(std::numeric_limits<int64_t>::max() / 2 + 1), 1);
Fraction lhs(std::numeric_limits<int64_t>::min() / 2 + 1, 1);
Fraction rhs(std::numeric_limits<int64_t>::min() / 2, 1);

std::string err;

Expand All @@ -1664,8 +1664,8 @@ BOOST_AUTO_TEST_CASE(util_Fraction_addition_overflow_3)

BOOST_AUTO_TEST_CASE(util_Fraction_addition_overflow_4)
{
Fraction lhs(-(std::numeric_limits<int64_t>::max() / 2 + 1), 1);
Fraction rhs(-(std::numeric_limits<int64_t>::max() / 2 + 2), 1);
Fraction lhs(std::numeric_limits<int64_t>::min() / 2, 1);
Fraction rhs(std::numeric_limits<int64_t>::min() / 2, 1);

std::string err;

Expand Down
9 changes: 8 additions & 1 deletion src/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -684,7 +684,14 @@ class Fraction {

if (a < 0 && b < 0) {
// Remember b is negative here, so the difference below is GREATER than std::numeric_limits<int64_t>::min().
if (a >= std::numeric_limits<int64_t>::min() - b) {
//
// The reason for the + 1 below is that the first case handled in the addition overflow operator method above,
// the fraction addition with a common denominator, also specifies simplification of the resultant fraction.
// This will call std::gcd on the numerator and denominator, which then calls std::abs. If std::abs is called on
// std::numeric_limits<int64_t>::min(), and -D_GLIBCXX_ASSERTIONS is set, then the program will abort on a glibc
// assertion, because the abs will overflow. To prevent this, we increase (make less negative) by 1, which will
// ensure the call to std::abs will succeed at the extreme case.
if (a >= std::numeric_limits<int64_t>::min() + 1 - b) {
return a + b;
} else {
throw std::overflow_error("fraction addition of a + b where a < 0 and b < 0 results in an overflow");
Expand Down

0 comments on commit 325a127

Please sign in to comment.