Summary
numfmt --padding=N sizes an output String directly from the user-supplied
width and allocates it unconditionally with String::with_capacity(width). The
width is unbounded, so a large --padding makes numfmt attempt an enormous
allocation and crash:
- a large width (≤
isize::MAX) → allocation failure → abort (SIGABRT, exit 134);
--padding=-9223372036854775808 (isize::MIN) → unsigned_abs() is
isize::MAX + 1, which exceeds isize::MAX → String::with_capacity
panics with capacity overflow (deterministic, regardless of available RAM).
GNU numfmt handles the same inputs cleanly: it prints numfmt: memory exhausted
and exits 1.
This is effectively a regression introduced by the fix for the format!-width
bug (gh-numfmt-11411): that fix replaced format!'s u16-capped width specifier
with a pad_string helper, removing the u16 cap but leaving the width unbounded
at the allocation level.
Steps to reproduce
# large width -> allocation failure -> SIGABRT
$ numfmt --padding=9000000000000000000 1
memory allocation of 9000000000000000000 bytes failed
Aborted (core dumped)
$ echo $?
134
# isize::MIN: unsigned_abs() = isize::MAX + 1 > isize::MAX -> capacity overflow panic
$ numfmt --padding=-9223372036854775808 1
thread 'main' panicked at .../alloc: capacity overflow
$ echo $?
134
Expected behavior
Match GNU: report the failure and exit non-zero, without aborting/panicking.
$ /usr/bin/numfmt --padding=9000000000000000000 1
/usr/bin/numfmt: memory exhausted
$ echo $?
1
$ /usr/bin/numfmt --padding=-9223372036854775808 1
/usr/bin/numfmt: memory exhausted
$ echo $?
1
Actual behavior
The process aborts (exit 134) — either an allocator abort
(memory allocation of N bytes failed) or a capacity overflow panic — instead
of a clean diagnostic.
Root cause
pad_string in src/uu/numfmt/src/format.rs — the helper added by the
gh-numfmt-11411 fix — allocates the full padded width up front:
fn pad_string(s: &str, width: usize, fill: char, right_align: bool) -> String {
...
let mut result = String::with_capacity(width); // width is the --padding value
...
}
--padding is parsed as an isize and passed through as p as usize /
p.unsigned_abs(), with no upper bound. A fix should bound the padding to a
sane limit (or use try_reserve and report an error) rather than eagerly
allocating the full width.
(The neighbouring "0".repeat(precision) is the same class but is guarded by
is_too_large_to_format on the normal paths.)
Environment
- uutils coreutils:
numfmt (uutils coreutils) 0.8.0 (commit bcdd1343, 2026-06-01)
- rustc: 1.89.0
- Reference: GNU coreutils 8.30
Found by our static analysis tooling.
Summary
numfmt --padding=Nsizes an outputStringdirectly from the user-suppliedwidth and allocates it unconditionally with
String::with_capacity(width). Thewidth is unbounded, so a large
--paddingmakesnumfmtattempt an enormousallocation and crash:
isize::MAX) → allocation failure → abort (SIGABRT, exit 134);--padding=-9223372036854775808(isize::MIN) →unsigned_abs()isisize::MAX + 1, which exceedsisize::MAX→String::with_capacitypanics with
capacity overflow(deterministic, regardless of available RAM).GNU
numfmthandles the same inputs cleanly: it printsnumfmt: memory exhaustedand exits 1.
This is effectively a regression introduced by the fix for the
format!-widthbug (gh-numfmt-11411): that fix replaced
format!'s u16-capped width specifierwith a
pad_stringhelper, removing the u16 cap but leaving the width unboundedat the allocation level.
Steps to reproduce
Expected behavior
Match GNU: report the failure and exit non-zero, without aborting/panicking.
Actual behavior
The process aborts (exit 134) — either an allocator abort
(
memory allocation of N bytes failed) or acapacity overflowpanic — insteadof a clean diagnostic.
Root cause
pad_stringinsrc/uu/numfmt/src/format.rs— the helper added by thegh-numfmt-11411 fix — allocates the full padded width up front:
--paddingis parsed as anisizeand passed through asp as usize/p.unsigned_abs(), with no upper bound. A fix should bound the padding to asane limit (or use
try_reserveand report an error) rather than eagerlyallocating the full width.
(The neighbouring
"0".repeat(precision)is the same class but is guarded byis_too_large_to_formaton the normal paths.)Environment
numfmt (uutils coreutils) 0.8.0(commitbcdd1343, 2026-06-01)Found by our static analysis tooling.