From b0aede8402bae547407c54bbe4897d6ffcf3a35a Mon Sep 17 00:00:00 2001 From: Ahmet Date: Wed, 22 Jul 2026 18:47:21 +0300 Subject: [PATCH] Fix silent overflow in from_string() decimal parsing The overflow check only validated the final addition (`x < d`), missing overflow in the preceding multiplication by 10. As a result, most out-of-range decimal inputs of the maximum digit length wrapped around silently instead of throwing, for every uint width (128/192/256/384/512). Replace it with a pre-multiplication bound check. --- include/intx/intx.hpp | 6 ++++-- test/unittests/test_intx.cpp | 9 +++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/include/intx/intx.hpp b/include/intx/intx.hpp index 20967468..90e74909 100644 --- a/include/intx/intx.hpp +++ b/include/intx/intx.hpp @@ -840,9 +840,11 @@ constexpr Int from_string(const char* str) throw_(str); const auto d = from_dec_digit(c); - x = x * Int{10} + d; - if (x < d) + // Check for overflow before multiplying, since checking after could be fooled by + // wraparound. + if (x > (std::numeric_limits::max() - d) / Int{10}) throw_(str); + x = x * Int{10} + d; } return x; } diff --git a/test/unittests/test_intx.cpp b/test/unittests/test_intx.cpp index 02f9f8f4..880d1c2a 100644 --- a/test/unittests/test_intx.cpp +++ b/test/unittests/test_intx.cpp @@ -348,6 +348,15 @@ TYPED_TEST(uint_test, string_conversions) } } +TYPED_TEST(uint_test, from_string_decimal_overflow) +{ + // A decimal string with as many digits as TypeParam::max() but consisting of all 9s + // is always greater than max() and must be rejected, not silently wrapped around. + const auto digits = to_string(std::numeric_limits::max()).size(); + const auto s = std::string(digits, '9'); + EXPECT_THROW_MESSAGE(from_string(s), std::out_of_range, s.c_str()); +} + TYPED_TEST(uint_test, to_string_base) { auto x = TypeParam{1024};