diff --git a/src/uu/stat/src/stat.rs b/src/uu/stat/src/stat.rs index 41fe5bf895c..e5e7e88b654 100644 --- a/src/uu/stat/src/stat.rs +++ b/src/uu/stat/src/stat.rs @@ -794,6 +794,17 @@ impl Stater { Self::process_flags(chars, i, bound, &mut flag); + // GNU rejects flag-only fragments closed by another '%', e.g. `%++-+%`. + if *i < bound && chars[*i] == '%' { + let invalid_directive: String = chars[old..=*i].iter().collect(); + return Err(DirectiveError::new( + format_str, + &invalid_directive, + old, + *i + 1, + )); + } + let mut width = 0; let mut precision = Precision::NotSpecified; let mut j = *i; diff --git a/tests/by-util/test_stat.rs b/tests/by-util/test_stat.rs index 2f7c3157723..47bfbe652ef 100644 --- a/tests/by-util/test_stat.rs +++ b/tests/by-util/test_stat.rs @@ -774,6 +774,15 @@ fn test_printf_invalid_directive() { .stderr_contains("'%9%': invalid directive"); } +#[test] +fn test_format_flags_closed_by_percent_are_invalid() { + // GNU rejects flag-only fragments ended by another '%', e.g. `%++-+%`. + new_ucmd!() + .args(&["--format=%++-+%1212x", "/"]) + .fails_with_code(1) + .stderr_is("stat: '%++-+%': invalid directive\n"); +} + #[test] fn test_invalid_directive_after_multibyte_char() { let ts = TestScenario::new(util_name!());