diff --git a/src/uu/truncate/src/truncate.rs b/src/uu/truncate/src/truncate.rs index 2fc9928cac..289da5ac37 100644 --- a/src/uu/truncate/src/truncate.rs +++ b/src/uu/truncate/src/truncate.rs @@ -279,6 +279,21 @@ fn file_truncate( } })?; + // A size above i64::MAX is not a valid file offset; reject it up front like + // GNU, instead of creating the file and failing when it is opened. + if truncate_size > i64::MAX as u64 { + let error = match size_argument { + None => translate!("truncate-error-value-too-large"), + Some(arg) => { + translate!("truncate-error-value-too-large-arg", "arg" => arg.quote()) + } + }; + return Err(USimpleError::new( + 1, + translate!("truncate-error-invalid-number", "error" => error), + )); + } + do_file_truncate(path, !no_create, truncate_size) } diff --git a/tests/by-util/test_truncate.rs b/tests/by-util/test_truncate.rs index 2a6eb18464..2ce100c562 100644 --- a/tests/by-util/test_truncate.rs +++ b/tests/by-util/test_truncate.rs @@ -38,6 +38,16 @@ fn test_increase_file_size_kb() { assert_eq!(expected, actual, "expected '{expected}' got '{actual}'"); } +#[test] +fn test_size_above_i64_max_is_rejected_without_creating_file() { + // A size above i64::MAX is rejected up front and the file is not created. + let (at, mut ucmd) = at_and_ucmd!(); + ucmd.args(&["-s", "9223372036854775808", "new-file"]) + .fails_with_code(1) + .stderr_contains("Value too large for defined data type"); + assert!(!at.file_exists("new-file")); +} + #[test] fn test_reference() { let expected = 5 * 1000;