Skip to content

Fix silent overflow in from_string() decimal parsing - #370

Open
cavdarahmet wants to merge 1 commit into
chfast:mainfrom
cavdarahmet:fix-from-string-decimal-overflow
Open

Fix silent overflow in from_string() decimal parsing#370
cavdarahmet wants to merge 1 commit into
chfast:mainfrom
cavdarahmet:fix-from-string-decimal-overflow

Conversation

@cavdarahmet

Copy link
Copy Markdown

Fixes #343.

The decimal-parsing loop in from_string() only checked for overflow
after the fact, via if (x < d) — which only catches overflow in the
final addition, not in the preceding x * Int{10} multiplication. For
an input at the maximum valid digit count (digits10), most values
above max() wrap around silently instead of throwing
std::out_of_range.

I verified this isn't limited to the one input in the issue:
cross-checking ~2200 randomized boundary-length decimal strings against
Python's arbitrary-precision arithmetic as an oracle, 89% of the
out-of-range cases silently wrapped with the current code, for
uint256. The same bug reproduces identically for uint128.

Fix: check the bound before multiplying (x > (max() - d) / 10)
instead of inspecting the result afterward — this can't be fooled by
wraparound since it never lets the multiplication overflow in the
first place.

Added a regression test parameterized over all five uint<N> widths
(128/192/256/384/512): for each type, a decimal string of max()'s
digit length filled with 9s must be rejected. Confirmed this test
fails (silently accepts invalid input) on all five widths without the
fix, and passes with it.

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<N> width (128/192/256/384/512).

Replace it with a pre-multiplication bound check.
@sonarqubecloud

Copy link
Copy Markdown

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 this pull request may close these issues.

Silent overflow when parsing some 78-digit decimal numbers as uint256.

1 participant