diff --git a/src/find/matchers/printf.rs b/src/find/matchers/printf.rs index 31151db2..ff25d676 100644 --- a/src/find/matchers/printf.rs +++ b/src/find/matchers/printf.rs @@ -152,7 +152,7 @@ impl FormatStringParser<'_> { fn advance_one(&mut self) -> Result> { let c = self.front()?; - self.string = &self.string[1..]; + self.string = &self.string[c.len_utf8()..]; Ok(c) } @@ -727,6 +727,16 @@ mod tests { ); } + #[test] + fn test_parse_multibyte_char_after_directive() { + assert_eq!( + FormatString::parse("%€").unwrap().components, + vec![FormatComponent::Literal("€".to_owned())] + ); + assert!(FormatString::parse("\\€").is_err()); + assert!(FormatString::parse("%A€").is_err()); + } + #[test] fn test_parse_formatting() { fn unaligned_directive(directive: FormatDirective) -> FormatComponent { diff --git a/tests/test_find.rs b/tests/test_find.rs index 2fbdff37..99a8bde9 100644 --- a/tests/test_find.rs +++ b/tests/test_find.rs @@ -588,6 +588,22 @@ fn find_printf_width_too_large() { .stderr_contains("find: Invalid format width"); } +#[test] +fn find_printf_multibyte_char_after_directive() { + ucmd() + .args(&["./test_data/simple", "-maxdepth", "0", "-printf", "%€\\n"]) + .succeeds() + .stdout_only("€\n"); + ucmd() + .args(&["./test_data/simple", "-maxdepth", "0", "-printf", "\\€\\n"]) + .fails() + .stderr_contains("find: Invalid escape sequence"); + ucmd() + .args(&["./test_data/simple", "-maxdepth", "0", "-printf", "%A€"]) + .fails() + .stderr_contains("find: Invalid time specifier"); +} + #[cfg(unix)] #[test] fn find_perm() {