diff --git a/src/parse.rs b/src/parse.rs index b263d915..f1dc3c2f 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -9,6 +9,7 @@ use std::ascii::AsciiExt; #[cfg(feature = "percent-encode")] use percent_encoding::percent_decode; +use time::error::InvalidVariant; use time::{PrimitiveDateTime, Duration, OffsetDateTime}; use time::{parsing::Parsable, macros::format_description, format_description::FormatItem}; @@ -31,6 +32,8 @@ pub enum ParseError { EmptyName, /// Decoding the cookie's name or value resulted in invalid UTF-8. Utf8Error(Utf8Error), + /// The year cannot be less than 1601. RFC 6265, Page 15 + InvalidYear, } impl ParseError { @@ -41,7 +44,8 @@ impl ParseError { ParseError::EmptyName => "the cookie's name is empty", ParseError::Utf8Error(_) => { "decoding the cookie's name or value resulted in invalid UTF-8" - } + }, + ParseError::InvalidYear => "the year cannot be less than 1601" } } } @@ -199,6 +203,15 @@ fn parse_inner<'c>(s: &str, decode: bool) -> Result, ParseError> { if let Ok(time) = tm { cookie.expires = Some(time.into()) } + + match tm { + Ok(time) => { + cookie.expires = Some(time.into()) + } + Err(_) => { + return Err(ParseError::InvalidYear) + }, + } } _ => { // We're going to be permissive here. If we have no idea what @@ -225,13 +238,20 @@ pub(crate) fn parse_date(s: &str, format: &impl Parsable) -> Result 2000, - 69..=99 => 1900, + 0..=69 => 2000, + 70..=99 => 1900, _ => 0, }; - date.set_year(y + offset); + let year = y + offset; + // RFC 6265, Page 15 + if year < 1601 { + return Err(time::Error::InvalidVariant(InvalidVariant)); + } + + date.set_year(year); } Ok(PrimitiveDateTime::try_from(date)?.assume_utc()) @@ -240,7 +260,7 @@ pub(crate) fn parse_date(s: &str, format: &impl Parsable) -> Result