From 7992536061518856770c92e40662630c9669d42d Mon Sep 17 00:00:00 2001 From: taichong Date: Wed, 17 Jul 2024 15:59:52 +0800 Subject: [PATCH] Enhanced time zone check --- src/lib.rs | 33 +++++++++++++++++++++++++++------ src/tests/fuzzing.rs | 37 ++++++++++++++++++++++++++++++++++++- 2 files changed, 63 insertions(+), 7 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index e85a684..fee9b0f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -851,13 +851,29 @@ impl Parser { 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::()?); - // if timezone is wrong format like "-03:" just return a Err, should not panic. - min_offset = if i + 3 > l.len() - 1 { - return Err(ParseError::TimezoneUnsupported); + 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 { - Some(l[i + 3].parse::()?) - }; + 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 timezone_len <= 2 { // -[0]3 @@ -866,6 +882,11 @@ impl Parser { 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 88048cf..8cc3c05 100644 --- a/src/tests/fuzzing.rs +++ b/src/tests/fuzzing.rs @@ -115,7 +115,42 @@ fn github_46() { parse("2000-01-01 12:00:00+00:"), Err(ParseError::TimezoneUnsupported) ); - let parse_result = parse("2000-01-01 12:00:00+0811"); + 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());