From ad1c4f5e39fb660d3fc8a5e2f5386b2cacf42b6a Mon Sep 17 00:00:00 2001 From: ChroniCat Date: Tue, 6 Apr 2021 20:22:07 +0800 Subject: [PATCH] [fix] crashing issues when the given timestamp is out of range (#3271) * add support for timestamp-based time conversion by specifing timezone or 'UTC/Local' * [fix] fix the wrong test sample * code formating * code formating and import missing mod to test * code formating again * [fix] it won't crash when given timestamp is too big. * [fix] code formatting =_=b --- .../src/commands/str_/to_datetime.rs | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/crates/nu-command/src/commands/str_/to_datetime.rs b/crates/nu-command/src/commands/str_/to_datetime.rs index 057ac7e2c..36d12d20f 100644 --- a/crates/nu-command/src/commands/str_/to_datetime.rs +++ b/crates/nu-command/src/commands/str_/to_datetime.rs @@ -110,13 +110,13 @@ impl WholeStreamCommand for SubCommand { result: None, }, Example { - description: "Convert to datetime using a specified timezone", + description: "Convert timestamp (no larger than 8e+12) to datetime using a specified timezone", example: "echo '1614434140' | str to-datetime -z 'UTC'", result: None, }, Example { description: - "Convert to datetime using a specified timezone offset (between -12 and 12)", + "Convert timestamp (no larger than 8e+12) to datetime using a specified timezone offset (between -12 and 12)", example: "echo '1614434140' | str to-datetime -o '+9'", result: None, }, @@ -203,7 +203,17 @@ fn action( let ts = s.parse::(); // if timezone if specified, first check if the input is a timestamp. if let Some(tz) = timezone { + const TIMESTAMP_BOUND: i64 = 8.2e+12 as i64; + // Since the timestamp method of chrono itself don't throw an error (it just panicked) + // We have to manually guard it. if let Ok(t) = ts { + if t.abs() > TIMESTAMP_BOUND { + return Err(ShellError::labeled_error( + "could not parse input as a valid timestamp", + "given timestamp is out of range, it should between -8e+12 and 8e+12", + tag.into().span, + )); + } const HOUR: i32 = 3600; let stampout = match tz.item { Zone::Utc => UntaggedValue::date(Utc.timestamp(t, 0)), @@ -347,6 +357,18 @@ mod tests { } } + #[test] + fn takes_invalid_timestamp() { + let date_str = string("10440970000000"); + let timezone_option = Some(Tagged { + item: Zone::Utc, + tag: Tag::unknown(), + }); + let actual = action(&date_str, &timezone_option, &None, Tag::unknown()); + + assert!(actual.is_err()); + } + #[test] fn communicates_parsing_error_given_an_invalid_datetimelike_string() { let date_str = string("16.11.1984 8:00 am Oops0000");