From 383f28949b394116de6986219d066e3de6522efd Mon Sep 17 00:00:00 2001 From: weili <541602953@qq.com> Date: Wed, 5 Aug 2026 08:01:08 +0000 Subject: [PATCH] split: fix add-overflow in suffix-length calculation Suffix::from computed the auto suffix length from `start as u64 + chunks`, which overflows when the numeric/hex suffix start (--numeric-suffixes / --hex-suffixes) or the chunk count (-n) is near u64::MAX, panicking with `attempt to add with overflow` under overflow-checks. Widen the sum to u128 so it can't overflow; it only feeds a log for the digit count, so results are unchanged for every in-range input and the out-of-range case now reports the normal "suffix length needs to be at least N" error. --- src/uu/split/src/filenames.rs | 3 ++- tests/by-util/test_split.rs | 41 +++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/uu/split/src/filenames.rs b/src/uu/split/src/filenames.rs index bc7adfb58d2..175b08cb14b 100644 --- a/src/uu/split/src/filenames.rs +++ b/src/uu/split/src/filenames.rs @@ -199,7 +199,8 @@ 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) + // u128 keeps the sum from overflowing when start is near usize::MAX. + let required_length = ((start as u128 + chunks as u128) as f64) .log(stype.radix() as f64) .ceil() as usize; diff --git a/tests/by-util/test_split.rs b/tests/by-util/test_split.rs index bb76dceb31f..88e10ef520d 100644 --- a/tests/by-util/test_split.rs +++ b/tests/by-util/test_split.rs @@ -942,6 +942,47 @@ fn test_suffix_length_req() { .stderr_only("split: the suffix length needs to be at least 2\n"); } +#[test] +fn test_numeric_suffix_huge_start_requires_suffix_length() { + new_ucmd!() + .args(&[ + "-n", + "5", + "--numeric-suffixes=18446744073709551615", + "asciilowercase.txt", + ]) + .fails() + .stderr_only("split: the suffix length needs to be at least 20\n"); +} + +#[test] +fn test_hex_suffix_huge_start_requires_suffix_length() { + new_ucmd!() + .args(&[ + "-n", + "5", + "--hex-suffixes=ffffffffffffffff", + "asciilowercase.txt", + ]) + .fails() + .stderr_only("split: the suffix length needs to be at least 16\n"); +} + +#[test] +fn test_numeric_suffix_huge_chunk_count_requires_suffix_length() { + new_ucmd!() + .args(&[ + "-n", + "18446744073709551615", + "--numeric-suffixes=5", + "-a", + "2", + "asciilowercase.txt", + ]) + .fails() + .stderr_only("split: the suffix length needs to be at least 20\n"); +} + #[test] fn test_large_suffix_length_is_rejected() { new_ucmd!()