From 2aa8a3502fd049a3ce13164aa8b289daf2940e04 Mon Sep 17 00:00:00 2001 From: Sudhakar Verma Date: Fri, 12 Jan 2024 16:08:47 +0530 Subject: [PATCH] printf : no infinite loop --- src/uu/printf/src/printf.rs | 10 +++++++++- tests/by-util/test_printf.rs | 5 +++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/uu/printf/src/printf.rs b/src/uu/printf/src/printf.rs index ad42e3894..64a3a35a7 100644 --- a/src/uu/printf/src/printf.rs +++ b/src/uu/printf/src/printf.rs @@ -11,7 +11,7 @@ use std::ops::ControlFlow; use clap::{crate_version, Arg, ArgAction, Command}; use uucore::error::{UResult, UUsageError}; -use uucore::format::{parse_spec_and_escape, FormatArgument}; +use uucore::format::{parse_spec_and_escape, FormatArgument, FormatItem}; use uucore::{format_usage, help_about, help_section, help_usage}; const VERSION: &str = "version"; @@ -46,6 +46,14 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { }; } + // See #5815 - We don't need to iter on args if no format string seen + let format_seen = parse_spec_and_escape(format_string.as_ref()) + .into_iter() + .any(|r| matches!(r, Ok(FormatItem::Spec(_)))); + if !format_seen { + return Ok(()); + } + while args.peek().is_some() { for item in parse_spec_and_escape(format_string.as_ref()) { match item?.write(stdout(), &mut args)? { diff --git a/tests/by-util/test_printf.rs b/tests/by-util/test_printf.rs index 4f2e1dc10..411285a0c 100644 --- a/tests/by-util/test_printf.rs +++ b/tests/by-util/test_printf.rs @@ -649,3 +649,8 @@ fn partial_char() { fn char_as_byte() { new_ucmd!().args(&["%c", "🙃"]).succeeds().stdout_only("ð"); } + +#[test] +fn no_infinite_loop() { + new_ucmd!().args(&["a", "b"]).succeeds().stdout_only("a"); +}