From b8a755a396ae47da5599a57e7e144be616bc295f Mon Sep 17 00:00:00 2001 From: jaggededgedjustice Date: Sun, 25 Dec 2022 20:11:34 +0000 Subject: [PATCH] date: Catch panic from invalid format string (#4240) * Catch panic from invalid date string --- src/uu/date/src/date.rs | 15 ++++++++++++++- tests/by-util/test_date.rs | 7 +++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/uu/date/src/date.rs b/src/uu/date/src/date.rs index 076cdbf43..03da2e46d 100644 --- a/src/uu/date/src/date.rs +++ b/src/uu/date/src/date.rs @@ -8,6 +8,7 @@ // spell-checker:ignore (chrono) Datelike Timelike ; (format) DATEFILE MMDDhhmm ; (vars) datetime datetimes +use chrono::format::{Item, StrftimeItems}; use chrono::{DateTime, FixedOffset, Local, Offset, Utc}; #[cfg(windows)] use chrono::{Datelike, Timelike}; @@ -243,7 +244,19 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { Ok(date) => { // GNU `date` uses `%N` for nano seconds, however crate::chrono uses `%f` let format_string = &format_string.replace("%N", "%f"); - let formatted = date.format(format_string).to_string().replace("%f", "%N"); + // Hack to work around panic in chrono, + // TODO - remove when a fix for https://github.com/chronotope/chrono/issues/623 is released + let format_items = StrftimeItems::new(format_string); + if format_items.clone().any(|i| i == Item::Error) { + return Err(USimpleError::new( + 1, + format!("invalid format {}", format_string.replace("%f", "%N")), + )); + } + let formatted = date + .format_with_items(format_items) + .to_string() + .replace("%f", "%N"); println!("{}", formatted); } Err((input, _err)) => show_error!("invalid date {}", input.quote()), diff --git a/tests/by-util/test_date.rs b/tests/by-util/test_date.rs index d17e9624e..6aa0031ca 100644 --- a/tests/by-util/test_date.rs +++ b/tests/by-util/test_date.rs @@ -225,3 +225,10 @@ fn test_date_set_valid_4() { assert!(result.stderr_str().starts_with("date: invalid date ")); } } + +#[test] +fn test_invalid_format_string() { + let result = new_ucmd!().arg("+%!").fails(); + result.no_stdout(); + assert!(result.stderr_str().starts_with("date: invalid format ")); +}