Skip to content

Commit 54571f8

Browse files
authored
Merge pull request #421 from sahvx655-wq/times-pow10-int64-min
avoid signed negation overflow in integer_times_pow10
2 parents f3f02c8 + 1271675 commit 54571f8

2 files changed

Lines changed: 7 additions & 1 deletion

File tree

‎include/fast_float/parse_number.h‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,9 @@ FASTFLOAT_CONSTEXPR20
503503
typename std::enable_if<is_supported_float_type<T>::value, T>::type
504504
integer_times_pow10(int64_t mantissa, int decimal_exponent) noexcept {
505505
const bool is_negative = mantissa < 0;
506-
const uint64_t m = static_cast<uint64_t>(is_negative ? -mantissa : mantissa);
506+
// Negate as unsigned: -mantissa overflows for the most negative int64_t.
507+
const uint64_t m = is_negative ? uint64_t(0) - static_cast<uint64_t>(mantissa)
508+
: static_cast<uint64_t>(mantissa);
507509

508510
T value;
509511
if (clinger_fast_path_impl(m, decimal_exponent, is_negative, value))

‎tests/basictest.cpp‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2485,6 +2485,10 @@ TEST_CASE("integer_times_pow10") {
24852485
all::verify_integer_times_pow10(12345678901234567890ull, -42);
24862486
all::verify_integer_times_pow10(std::numeric_limits<int64_t>::max(), 42);
24872487
all::verify_integer_times_pow10(std::numeric_limits<int64_t>::max(), -42);
2488+
// the most negative int64_t has no positive counterpart to negate into
2489+
all::verify_integer_times_pow10(std::numeric_limits<int64_t>::min(), 0);
2490+
all::verify_integer_times_pow10(std::numeric_limits<int64_t>::min(), 42);
2491+
all::verify_integer_times_pow10(std::numeric_limits<int64_t>::min(), -42);
24882492
all::verify_integer_times_pow10(std::numeric_limits<uint64_t>::max(), 42);
24892493
all::verify_integer_times_pow10(std::numeric_limits<uint64_t>::max(), -42);
24902494
}

0 commit comments

Comments
 (0)