Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent string slicing inside char boundaries #1024

Merged
merged 2 commits into from Apr 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/format/parse.rs
Expand Up @@ -997,3 +997,11 @@ fn test_rfc3339() {
}
}
}

#[cfg(test)]
#[test]
fn test_issue_1010() {
let dt = crate::NaiveDateTime::parse_from_str("\u{c}SUN\u{e}\u{3000}\0m@J\u{3000}\0\u{3000}\0m\u{c}!\u{c}\u{b}\u{c}\u{c}\u{c}\u{c}%A\u{c}\u{b}\0SU\u{c}\u{c}",
"\u{c}\u{c}%A\u{c}\u{b}\0SUN\u{c}\u{c}\u{c}SUNN\u{c}\u{c}\u{c}SUN\u{c}\u{c}!\u{c}\u{b}\u{c}\u{c}\u{c}\u{c}%A\u{c}\u{b}%a");
assert_eq!(dt, Err(ParseError(ParseErrorKind::Invalid)));
}
12 changes: 6 additions & 6 deletions src/format/scan.rs
Expand Up @@ -12,8 +12,8 @@ use crate::Weekday;

/// Returns true when two slices are equal case-insensitively (in ASCII).
/// Assumes that the `pattern` is already converted to lower case.
fn equals(s: &str, pattern: &str) -> bool {
let mut xs = s.as_bytes().iter().map(|&c| match c {
fn equals(s: &[u8], pattern: &str) -> bool {
let mut xs = s.iter().map(|&c| match c {
b'A'..=b'Z' => c + 32,
_ => c,
});
Expand Down Expand Up @@ -152,7 +152,7 @@ pub(super) fn short_or_long_month0(s: &str) -> ParseResult<(&str, u8)> {

// tries to consume the suffix if possible
let suffix = LONG_MONTH_SUFFIXES[month0 as usize];
if s.len() >= suffix.len() && equals(&s[..suffix.len()], suffix) {
if s.len() >= suffix.len() && equals(&s.as_bytes()[..suffix.len()], suffix) {
s = &s[suffix.len()..];
}

Expand All @@ -170,7 +170,7 @@ pub(super) fn short_or_long_weekday(s: &str) -> ParseResult<(&str, Weekday)> {

// tries to consume the suffix if possible
let suffix = LONG_WEEKDAY_SUFFIXES[weekday.num_days_from_monday() as usize];
if s.len() >= suffix.len() && equals(&s[..suffix.len()], suffix) {
if s.len() >= suffix.len() && equals(&s.as_bytes()[..suffix.len()], suffix) {
s = &s[suffix.len()..];
}

Expand Down Expand Up @@ -322,7 +322,7 @@ pub(super) fn timezone_offset_2822(s: &str) -> ParseResult<(&str, Option<i32>)>
})
.unwrap_or(s.len());
if upto > 0 {
let name = &s[..upto];
let name = &s.as_bytes()[..upto];
let s = &s[upto..];
let offset_hours = |o| Ok((s, Some(o * 3600)));
if equals(name, "gmt") || equals(name, "ut") {
Expand All @@ -338,7 +338,7 @@ pub(super) fn timezone_offset_2822(s: &str) -> ParseResult<(&str, Option<i32>)>
} else if equals(name, "pst") {
offset_hours(-8)
} else if name.len() == 1 {
match name.as_bytes()[0] {
match 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)),
Expand Down