numfmt panics (index out of bounds) on a very large `--to=si`/`--to=iec` value
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 24.1k
- Forks
- 2k
- Avg merge
- 1d 5h
- Merged PRs (30d)
- 365
Description
Summary
numfmt --to=si (and --to=iec) panics with an index-out-of-bounds when the
input value falls in the top supported decade and rounding bumps the scaled
value back up to the next base. consider_suffix computes a suffix index i
that can be 10, then indexes the 10-element suffixes array (suffixes[i])
on the rounding-overflow branch — suffixes[10] is out of bounds.
GNU numfmt handles the same input cleanly: it prints
numfmt: value too large to be converted: '<n>' and exits 2.
Steps to reproduce
$ numfmt --to=si 999500000000000000000000000000000
thread 'main' panicked at src/uu/numfmt/src/format.rs:536:33:
index out of bounds: the len is 10 but the index is 10
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Aborted (core dumped)
$ echo $?
134
numfmt --to=si 1000000000000000000000000000000000 (10³³) panics the same way.
The --to=iec path has the same shape (with bases[10] = 1024¹⁰).
Expected behavior
Match GNU: report the value as too large and exit non-zero, without panicking.
$ /usr/bin/numfmt --to=si 999500000000000000000000000000000
/usr/bin/numfmt: value too large to be converted: ‘999500000000000000000000000000000’
$ echo $?
2
(numfmt already has the right error for even larger inputs — e.g.
numfmt --to=si 9995…e33 returns Number is too big and unsupported, exit 2.
This bug is the narrow band just below that, where it aborts instead.)
Actual behavior
The process panics and aborts (exit 134) with an index-out-of-bounds, instead of
a clean error.
Root cause
consider_suffix in src/uu/numfmt/src/format.rs:
let suffixes = [K, M, G, T, P, E, Z, Y, R, Q]; // length 10, valid indices 0..=9
let i = match abs_n {
...
_ if abs_n < bases[10] => 9,
_ if abs_n < bases[10] * 1000.0 => 10, // i can be 10
_ => return Err(translate!("numfmt-error-number-too-big")),
};
let v = /* n scaled by bases[i], rounded */;
if v.abs() >= bases[1] {
Ok((v / bases[1], Some((suffixes[i], with_i)))) // i == 10 -> suffixes[10] -> OOB panic
} else {
Ok((v, Some((suffixes[i - 1], with_i)))) // i == 10 -> suffixes[9] -> OK
}
When abs_n ∈ [bases[10], bases[10]·1000) the index is 10. Normally the value
then scales below bases[1] and the else branch (suffixes[i - 1] = suffixes[9],
the largest suffix) is taken. But when rounding lifts v to ≥ bases[1]
(e.g. n / bases[10] rounds up to 1000), the then branch runs suffixes[i]
with i == 10 → panic.
A fix should treat i == 10 in the rounding-overflow branch as "value too large"
(the same numfmt-error-number-too-big path the next match arm already uses),
since there is no SI/IEC suffix beyond the top base.
Environment
- uutils coreutils:
numfmt (uutils coreutils) 0.9.0(latestmain, commit0011d54, 2026-06-03;numfmt/format.rsunchanged across recent commits) - rustc: 1.89.0
- Reference: GNU coreutils 8.30
Found by our static analysis tooling.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in src/uu/numfmt/src/format.rs at consider_suffix and reproduce the issue with the provided --to=si and --to=iec commands. Trace the rounding-overflow branch for i == 10 and verify that the completed change reports numfmt-error-number-too-big, exits non-zero, and no longer panics for the boundary inputs.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- cli
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100