From 7867769ecd49ab9856b1ba7ec584a136133f69c9 Mon Sep 17 00:00:00 2001 From: taichong Date: Mon, 19 Aug 2024 09:12:53 +0800 Subject: [PATCH] fix: invalid timezone should return err not panic 1. Enhanced time zone check 2. modify default NaiveDate value set 1970-01-01 not today --- src/lib.rs | 45 ++++++++++++++++++++++++------ src/tests/fuzzing.rs | 66 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 102 insertions(+), 9 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 8a9e717..2548248 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -713,9 +713,12 @@ impl Parser { ignoretz: bool, tzinfos: &HashMap, ) -> ParseResult<(NaiveDateTime, Option, Option>)> { - let default_date = default.unwrap_or(&Local::now().naive_local()).date(); - - let default_ts = NaiveDateTime::new(default_date, NaiveTime::from_hms_opt(0, 0, 0).unwrap()); + // If default is none, 1970-01-01 00:00:00 as default value is better. + let default_date = default + .unwrap_or(&NaiveDate::default().and_hms_opt(0, 0, 0).unwrap()) + .date(); + let default_ts = + NaiveDateTime::new(default_date, NaiveTime::from_hms_opt(0, 0, 0).unwrap()); let (res, tokens) = self.parse_with_tokens(timestr, dayfirst, yearfirst, fuzzy, fuzzy_with_tokens)?; @@ -840,28 +843,54 @@ impl Parser { } } else if res.hour.is_some() && (l[i] == "+" || l[i] == "-") { let signal = if l[i] == "+" { 1 } else { -1 }; - let len_li = l[i].len(); + // check next index's length + let timezone_len = l[i + 1].len(); let mut hour_offset: Option = None; let mut min_offset: Option = None; // TODO: check that l[i + 1] is integer? - if len_li == 4 { + if timezone_len == 4 { // -0300 hour_offset = Some(l[i + 1][..2].parse::()?); min_offset = Some(l[i + 1][2..4].parse::()?); } else if i + 2 < len_l && l[i + 2] == ":" { // -03:00 - hour_offset = Some(l[i + 1].parse::()?); - min_offset = Some(l[i + 3].parse::()?); + let hour_offset_len = l[i + 1].len(); + // -003:00 need err + if hour_offset_len <= 2 { + let range_len = min(hour_offset_len, 2); + hour_offset = Some(l[i + 1][..range_len].parse::()?); + } else { + return Err(ParseError::TimezoneUnsupported); + } + + // if timezone is wrong format like "-03:" just return a Err, should not panic. + if i + 3 > l.len() - 1 { + return Err(ParseError::TimezoneUnsupported); + } + + let min_offset_len = l[i + 3].len(); + // -09:003 need err + if min_offset_len <= 2 { + let range_len = min(min_offset_len, 2); + min_offset = Some(l[i + 3][..range_len].parse::()?); + } else { + return Err(ParseError::TimezoneUnsupported); + } i += 2; - } else if len_li <= 2 { + } else if timezone_len <= 2 { // -[0]3 let range_len = min(l[i + 1].len(), 2); hour_offset = Some(l[i + 1][..range_len].parse::()?); min_offset = Some(0); } + // like +09123 + if hour_offset.is_none() && min_offset.is_none() { + return Err(ParseError::TimezoneUnsupported); + } + res.tzoffset = Some(signal * (hour_offset.unwrap() * 3600 + min_offset.unwrap() * 60)); diff --git a/src/tests/fuzzing.rs b/src/tests/fuzzing.rs index 2e7400b..d27f2f3 100644 --- a/src/tests/fuzzing.rs +++ b/src/tests/fuzzing.rs @@ -103,4 +103,68 @@ fn github_45() { assert!(parse("/2018-fifa-").is_err()); assert!(parse("/2009/07/").is_err()); assert!(parse("2021-09-").is_err()); -} \ No newline at end of file +} + +#[test] +fn github_46() { + assert_eq!( + parse("2000-01-01 12:00:00+00:"), + Err(ParseError::TimezoneUnsupported) + ); + assert_eq!( + parse("2000-01-01 12:00:00+09123"), + Err(ParseError::TimezoneUnsupported) + ); + assert_eq!( + parse("2000-01-01 13:00:00+00:003"), + Err(ParseError::TimezoneUnsupported) + ); + assert_eq!( + parse("2000-01-01 13:00:00+009:03"), + Err(ParseError::TimezoneUnsupported) + ); + assert_eq!( + parse("2000-01-01 13:00:00+xx:03"), + Err(ParseError::InvalidNumeric( + "invalid digit found in string".to_owned() + )) + ); + assert_eq!( + parse("2000-01-01 13:00:00+00:yz"), + Err(ParseError::InvalidNumeric( + "invalid digit found in string".to_owned() + )) + ); + let mut parse_result = parse("2000-01-01 13:00:00+00:03"); + match parse_result { + Ok((dt, offset)) => { + assert_eq!(format!("{:?}", dt), "2000-01-01T13:00:00".to_string()); + assert_eq!(format!("{:?}", offset), "Some(+00:03)".to_string()); + } + Err(_) => { + panic!(); + } + }; + + parse_result = parse("2000-01-01 12:00:00+0811"); + match parse_result { + Ok((dt, offset)) => { + assert_eq!(format!("{:?}", dt), "2000-01-01T12:00:00".to_string()); + assert_eq!(format!("{:?}", offset), "Some(+08:11)".to_string()); + } + Err(_) => { + panic!(); + } + } + + parse_result = parse("2000"); + match parse_result { + Ok((dt, offset)) => { + assert_eq!(format!("{:?}", dt), "2000-01-01T00:00:00".to_string()); + assert!(offset.is_none()); + } + Err(_) => { + panic!(); + } + } +}