Skip to content

#5306: reject numbers outside long range in sprintf %d conversion instead of saturating#5316

Merged
yegor256 merged 1 commit into
objectionary:masterfrom
morphqdd:5306-sprintf-d-conversion-range-guard
Jul 8, 2026
Merged

#5306: reject numbers outside long range in sprintf %d conversion instead of saturating#5316
yegor256 merged 1 commit into
objectionary:masterfrom
morphqdd:5306-sprintf-d-conversion-range-guard

Conversation

@morphqdd

@morphqdd morphqdd commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Closes #5306.

sprintf's %d conversion (SprintfArgs.CONVERSION.put('d', element -> element.asNumber().longValue()))
narrowed the argument's Double value to long via Double.longValue(), which doesn't throw for
a value outside long range — it saturates, returning Long.MAX_VALUE/Long.MIN_VALUE. So
sprintf("%d", *1e30) silently printed 9223372036854775807 instead of raising a domain error
naming the offending value. This is the same Double-to-integral narrowing-without-validation
defect already fixed for Expect.Natural/Expect.Int (#5295/#5307) and number.as-i64
(#5305/#5315), here in the %d conversion path used by every sprintf call in this codebase.

Added a SprintfArgs.toLong(double) helper that checks the value against Long.MIN_VALUE/
Long.MAX_VALUE before narrowing, and wired it into the 'd' entry of the CONVERSION map in
place of the raw .longValue() call.

Added throws-on-formatting-huge-number-as-decimal to tt/sprintf.eo, using 1.0e30 — the exact
reproduction value from the issue — mirroring the existing truncates-*-as-decimal tests for the
%d conversion.

Ran the full EO-generated sprintf test suite locally (EOtt.EOsprintfTest) — all 20 tests pass.

@sonarqubecloud

sonarqubecloud Bot commented Jul 4, 2026

Copy link
Copy Markdown

@github-actions

github-actions Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

🚀 Performance Analysis

All benchmarks are within the acceptable range. No critical degradation detected (threshold is 100%). Please refer to the detailed report for more information.

Click to see the detailed report
Test Base Score PR Score Change % Change Unit Mode
benchmarks.XmirBench.xmirToEO 13364.331 13078.302 -286.029 -2.14% ms/op Average Time

✅ Performance gain: benchmarks.XmirBench.xmirToEO is faster by 286.029 ms/op (2.14%)

@morphqdd

morphqdd commented Jul 4, 2026

Copy link
Copy Markdown
Contributor Author

@yegor256, please take a look when you have a moment.

@yegor256
yegor256 merged commit e8cf6c5 into objectionary:master Jul 8, 2026
25 of 26 checks passed
@0crat

0crat commented Jul 8, 2026

Copy link
Copy Markdown

@morphqdd Thanks for the contribution! You've earned +12 points for this: +16 as a basis; -4 for too few (28) hits-of-code. Please, keep them coming. Your running score is +548; don't forget to check your Zerocracy account too).

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.

sprintf's %d conversion incorrectly saturates out-of-range values instead of throwing an error

3 participants