Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions src/uu/split/src/filenames.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,9 +199,11 @@ impl Suffix {
// Auto pre-calculate new suffix length (auto-width) if necessary
if let Strategy::Number(number_type) = strategy {
let chunks = number_type.num_chunks();
let required_length = ((start as u64 + chunks) as f64)
.log(stype.radix() as f64)
.ceil() as usize;
// The last suffix is the start plus the chunk count, and either of
// those alone can be as large as the type allows, so the sum needs
// room the type does not have.
let last = start as u128 + u128::from(chunks);
let required_length = (last as f64).log(stype.radix() as f64).ceil() as usize;

if (start as u64) < chunks && !(is_length_cmd_opt && length > 0) {
// with auto-width ON the auto-widening is OFF
Expand Down
42 changes: 42 additions & 0 deletions tests/by-util/test_split.rs
Original file line number Diff line number Diff line change
Expand Up @@ -942,6 +942,48 @@ fn test_suffix_length_req() {
.stderr_only("split: the suffix length needs to be at least 2\n");
}

/// The width the suffixes need is worked out from the start value plus the
/// number of chunks, and either of those on its own can be the largest value
/// there is, so the sum of them does not fit where they do.
///
/// `u64::MAX` only reaches `--numeric-suffixes`'s `start` at all on a target
/// where `usize` is 64 bits -- on a 32-bit target the value is already
/// rejected by the `usize` parse, before the overflow this guards against
/// could occur.
#[test]
#[cfg(target_pointer_width = "64")]
fn test_suffix_start_at_the_top_of_the_range() {
new_ucmd!()
.args(&["-n", "5", "--numeric-suffixes=18446744073709551615", "-"])
.pipe_in("")
.fails_with_code(1)
.stderr_only("split: the suffix length needs to be at least 20\n");

// The hexadecimal start is read in base 16, so it takes fewer digits to
// reach the same place.
new_ucmd!()
.args(&["-n", "5", "--hex-suffixes=ffffffffffffffff", "-"])
.pipe_in("")
.fails_with_code(1)
.stderr_only("split: the suffix length needs to be at least 16\n");

// A suffix wide enough for the start is accepted, and the first name is
// the start itself.
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&[
"-n",
"5",
"--numeric-suffixes=18446744073709551615",
"-a",
"20",
"-",
])
.pipe_in("")
.fails_with_code(1)
.stderr_only("split: output file suffixes exhausted\n");
assert!(at.file_exists("x18446744073709551615"));
}

#[test]
fn test_large_suffix_length_is_rejected() {
new_ucmd!()
Expand Down
Loading