fix(printf): compute asterisk width magnitude in unsigned arithmetic - #13800
fix(printf): compute asterisk width magnitude in unsigned arithmetic#13800bolverk wants to merge 1 commit into
Conversation
|
GNU testsuite comparison: |
8728f09 to
2d76eba
Compare
|
Updated the integration test to be portable: on 32-bit targets ( |
2d76eba to
2864ff4
Compare
|
|
||
| #[test] | ||
| fn test_asterisk_width_i64_min_no_panic() { | ||
| // Regression test for https://github.com/uutils/coreutils/issues/13766 |
There was a problem hiding this comment.
Please make the comment shorter
A negative '*' field width argument of i64::MIN used to panic with attempt to negate with overflow because |i64::MIN| = 2^63 is not representable in i64/isize. Use nb.unsigned_abs() to compute the magnitude in unsigned arithmetic, which can represent 2^63. Add a unit test for the width resolution and an end-to-end regression test verifying printf fails gracefully with a write error instead of panicking. Fixes uutils#13766
2864ff4 to
afbc154
Compare
Merging this PR will improve performance by 5.1%
Performance Changes
Tip Curious why this is faster? Comment Comparing Footnotes
|
Fixes #13766
Summary
A negative
*field-width argument ofi64::MIN(printf '%*d' -9223372036854775808 1) maderesolve_asterisk_widthpanic withattempt to negate with overflow: the old code computed the magnitude as-(nb as isize), and|i64::MIN| = 2^63is not representable ini64/isize.The fix computes the magnitude with
nb.unsigned_abs(), which is designed for exactly this case and returns2^63in unsigned (u64) arithmetic.Behavior
panic/ exit 134 (attempt to negate with overflow)2^63exceedsMAX_FORMAT_WIDTH, soprintffails gracefully withprintf: write error: formatting width too large(exit 1), matching the handling of other oversized widths.Verification
Formal verification of the width-resolution arithmetic was done in Dafny (4.11): it specifies the intended behavior (negative width ⇒ left-align with magnitude), proves
|i64::MIN|overflowsi64but fitsu64/usize, and proves theunsigned_abs()-based implementation is overflow-free and matches the spec. Proof:15 verified, 0 errors.Tests
resolve_asterisk_width::asterisk_i64_min_width(bothSignedIntandUnparsedargument forms)test_printf::test_asterisk_width_i64_min_no_panicprintfsuite passes: 131 passed, 0 failed, 1 ignored;cargo fmtandclippyclean.