diff --git a/src/find/matchers/printf.rs b/src/find/matchers/printf.rs index 038ec7fb..949d27bc 100644 --- a/src/find/matchers/printf.rs +++ b/src/find/matchers/printf.rs @@ -207,7 +207,7 @@ impl FormatStringParser<'_> { } } - fn parse_format_width(&mut self) -> Option { + fn parse_format_width(&mut self) -> Result, Box> { let start = self.string; let mut digits = 0; @@ -218,11 +218,16 @@ impl FormatStringParser<'_> { } if digits > 0 { - // safe to unwrap: we already know all the digits are valid due to - // the above checks. - Some((start[0..digits]).parse().unwrap()) + let digits = &start[0..digits]; + let width: usize = digits + .parse() + .map_err(|_| format!("Invalid format width: {digits}"))?; + if width > u16::MAX as usize { + return Err(format!("Format width too large: {digits}").into()); + } + Ok(Some(width)) } else { - None + Ok(None) } } @@ -258,7 +263,7 @@ impl FormatStringParser<'_> { self.advance_one().unwrap(); } - let width = self.parse_format_width(); + let width = self.parse_format_width()?; let first = self.advance_one()?; if first == '%' { diff --git a/tests/test_find.rs b/tests/test_find.rs index cfee583f..89a767ed 100644 --- a/tests/test_find.rs +++ b/tests/test_find.rs @@ -519,6 +519,30 @@ fn find_printf_octal_escape_before_multibyte_char() { .stdout_only("\0€\n"); } +#[test] +fn find_printf_width_too_large() { + ucmd() + .args(&[ + "./test_data/simple", + "-maxdepth", + "0", + "-printf", + "%70000s\\n", + ]) + .fails() + .stderr_contains("find: Format width too large"); + ucmd() + .args(&[ + "./test_data/simple", + "-maxdepth", + "0", + "-printf", + "%99999999999999999999s\\n", + ]) + .fails() + .stderr_contains("find: Invalid format width"); +} + #[cfg(unix)] #[test] fn find_perm() {