Merge pull request #421 from sahvx655-wq/times-pow10-int64-min

avoid signed negation overflow in integer_times_pow10
This commit is contained in:
Daniel Lemire 2026-10-06 19:48:48 -04:00 committed by GitHub
commit 54571f86e3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 7 additions and 1 deletions

View File

@ -503,7 +503,9 @@ FASTFLOAT_CONSTEXPR20
typename std::enable_if<is_supported_float_type<T>::value, T>::type
integer_times_pow10(int64_t mantissa, int decimal_exponent) noexcept {
const bool is_negative = mantissa < 0;
const uint64_t m = static_cast<uint64_t>(is_negative ? -mantissa : mantissa);
// Negate as unsigned: -mantissa overflows for the most negative int64_t.
const uint64_t m = is_negative ? uint64_t(0) - static_cast<uint64_t>(mantissa)
: static_cast<uint64_t>(mantissa);
T value;
if (clinger_fast_path_impl(m, decimal_exponent, is_negative, value))

View File

@ -2485,6 +2485,10 @@ TEST_CASE("integer_times_pow10") {
all::verify_integer_times_pow10(12345678901234567890ull, -42);
all::verify_integer_times_pow10(std::numeric_limits<int64_t>::max(), 42);
all::verify_integer_times_pow10(std::numeric_limits<int64_t>::max(), -42);
// the most negative int64_t has no positive counterpart to negate into
all::verify_integer_times_pow10(std::numeric_limits<int64_t>::min(), 0);
all::verify_integer_times_pow10(std::numeric_limits<int64_t>::min(), 42);
all::verify_integer_times_pow10(std::numeric_limits<int64_t>::min(), -42);
all::verify_integer_times_pow10(std::numeric_limits<uint64_t>::max(), 42);
all::verify_integer_times_pow10(std::numeric_limits<uint64_t>::max(), -42);
}