Skip to content

Commit

Permalink
Remove incomplete parsing support for -0000 offset
Browse files Browse the repository at this point in the history
  • Loading branch information
pitdicker committed Feb 7, 2024
1 parent 76af9a0 commit 18d8459
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 30 deletions.
14 changes: 5 additions & 9 deletions src/format/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,7 @@ fn parse_rfc2822<'a>(parsed: &mut Parsed, mut s: &'a str) -> ParseResult<(&'a st
}

s = scan::space(s)?; // mandatory
if let Some(offset) = try_consume!(scan::timezone_offset_2822(s)) {
// only set the offset when it is definitely known (i.e. not `-0000`)
parsed.set_offset(i64::from(offset))?;
}
parsed.set_offset(i64::from(try_consume!(scan::timezone_offset_2822(s))))?;

// optional comments
while let Ok((s_out, ())) = scan::comment_2822(s) {
Expand Down Expand Up @@ -1644,7 +1641,6 @@ mod tests {
("Tue, 20 Jan 2015 17:35:90 -0800", Err(OUT_OF_RANGE)), // bad second
("Tue, 20 Jan 2015 17:35:20 -0890", Err(OUT_OF_RANGE)), // bad offset
("6 Jun 1944 04:00:00Z", Err(INVALID)), // bad offset (zulu not allowed)
("Tue, 20 Jan 2015 17:35:20 HAS", Err(NOT_ENOUGH)), // bad named time zone
// named timezones that have specific timezone offsets
// see https://www.rfc-editor.org/rfc/rfc2822#section-4.3
("Tue, 20 Jan 2015 17:35:20 GMT", Ok(ymd_hmsn(2015, 1, 20, 17, 35, 20, 0, 0))),
Expand All @@ -1666,14 +1662,14 @@ mod tests {
("Tue, 20 Jan 2015 17:35:20 K", Ok(ymd_hmsn(2015, 1, 20, 17, 35, 20, 0, 0))),
("Tue, 20 Jan 2015 17:35:20 k", Ok(ymd_hmsn(2015, 1, 20, 17, 35, 20, 0, 0))),
// named single-letter timezone "J" is specifically not valid
("Tue, 20 Jan 2015 17:35:20 J", Err(NOT_ENOUGH)),
("Tue, 20 Jan 2015 17:35:20 J", Err(INVALID)),
("Tue, 20 Jan 2015 17:35:20 -0890", Err(OUT_OF_RANGE)), // bad offset minutes
("Tue, 20 Jan 2015 17:35:20Z", Err(INVALID)), // bad offset: zulu not allowed
("Tue, 20 Jan 2015 17:35:20 Zulu", Err(NOT_ENOUGH)), // bad offset: zulu not allowed
("Tue, 20 Jan 2015 17:35:20 ZULU", Err(NOT_ENOUGH)), // bad offset: zulu not allowed
("Tue, 20 Jan 2015 17:35:20 Zulu", Err(INVALID)), // bad offset: zulu not allowed
("Tue, 20 Jan 2015 17:35:20 ZULU", Err(INVALID)), // bad offset: zulu not allowed
("Tue, 20 Jan 2015 17:35:20 −0800", Err(INVALID)), // bad offset: timezone offset using MINUS SIGN (U+2212), not specified for RFC 2822
("Tue, 20 Jan 2015 17:35:20 0800", Err(INVALID)), // missing offset sign
("Tue, 20 Jan 2015 17:35:20 HAS", Err(NOT_ENOUGH)), // bad named timezone
("Tue, 20 Jan 2015 17:35:20 HAS", Err(INVALID)), // bad named timezone
("Tue, 20 Jan 2015😈17:35:20 -0800", Err(INVALID)), // bad character!
];

Expand Down
44 changes: 23 additions & 21 deletions src/format/scan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,37 +287,39 @@ where
/// See [RFC 2822 Section 4.3].
///
/// [RFC 2822 Section 4.3]: https://tools.ietf.org/html/rfc2822#section-4.3
pub(super) fn timezone_offset_2822(s: &str) -> ParseResult<(&str, Option<i32>)> {
pub(super) fn timezone_offset_2822(s: &str) -> ParseResult<(&str, i32)> {
// tries to parse legacy time zone names
let upto = s.as_bytes().iter().position(|&c| !c.is_ascii_alphabetic()).unwrap_or(s.len());
if upto > 0 {
let name = &s.as_bytes()[..upto];
let s = &s[upto..];
let offset_hours = |o| Ok((s, Some(o * 3600)));
if name.eq_ignore_ascii_case(b"gmt") || name.eq_ignore_ascii_case(b"ut") {
offset_hours(0)
let offset_hours = |o| Ok((s, o * 3600));
// RFC 2822 requires support for some named North America timezones, a small subset of all
// named timezones.
if name.eq_ignore_ascii_case(b"gmt")
|| name.eq_ignore_ascii_case(b"ut")
|| name.eq_ignore_ascii_case(b"z")
{
return offset_hours(0);
} else if name.eq_ignore_ascii_case(b"edt") {
offset_hours(-4)
return offset_hours(-4);
} else if name.eq_ignore_ascii_case(b"est") || name.eq_ignore_ascii_case(b"cdt") {
offset_hours(-5)
return offset_hours(-5);
} else if name.eq_ignore_ascii_case(b"cst") || name.eq_ignore_ascii_case(b"mdt") {
offset_hours(-6)
return offset_hours(-6);
} else if name.eq_ignore_ascii_case(b"mst") || name.eq_ignore_ascii_case(b"pdt") {
offset_hours(-7)
return offset_hours(-7);
} else if name.eq_ignore_ascii_case(b"pst") {
offset_hours(-8)
return offset_hours(-8);
} else if name.len() == 1 {
match name[0] {
if let b'a'..=b'i' | b'k'..=b'y' | b'A'..=b'I' | b'K'..=b'Y' = name[0] {
// recommended by RFC 2822: consume but treat it as -0000
b'a'..=b'i' | b'k'..=b'z' | b'A'..=b'I' | b'K'..=b'Z' => offset_hours(0),
_ => Ok((s, None)),
return Ok((s, 0));
}
} else {
Ok((s, None))
}
Err(INVALID)
} else {
let (s_, offset) = timezone_offset(s, |s| Ok(s), false, false, false)?;
Ok((s_, Some(offset)))
timezone_offset(s, |s| Ok(s), false, false, false)
}
}

Expand Down Expand Up @@ -396,11 +398,11 @@ mod tests {

#[test]
fn test_timezone_offset_2822() {
assert_eq!(timezone_offset_2822("cSt").unwrap(), ("", Some(-21600)));
assert_eq!(timezone_offset_2822("pSt").unwrap(), ("", Some(-28800)));
assert_eq!(timezone_offset_2822("mSt").unwrap(), ("", Some(-25200)));
assert_eq!(timezone_offset_2822("-1551").unwrap(), ("", Some(-57060)));
assert_eq!(timezone_offset_2822("Gp").unwrap(), ("", None));
assert_eq!(timezone_offset_2822("cSt").unwrap(), ("", -21600));
assert_eq!(timezone_offset_2822("pSt").unwrap(), ("", -28800));
assert_eq!(timezone_offset_2822("mSt").unwrap(), ("", -25200));
assert_eq!(timezone_offset_2822("-1551").unwrap(), ("", -57060));
assert_eq!(timezone_offset_2822("Gp"), Err(INVALID));
}

#[test]
Expand Down

0 comments on commit 18d8459

Please sign in to comment.