Skip to content

datetime_from_str is too lenient, doesn't roundtrip #548

@koivunej

Description

@koivunej

For another crate cargo-fuzz found me the input "4\t3\t\u{c}\t\t3\t\u{c}\t5\t3\t60Z" which is parsed successfully with Utc.datetime_from_str(s, "%Y%m%d%H%M%S%.3fZ"). Minimal test case for version 0.4.19:

#[test]
fn fuzzed_roundtrip() {
    let fmt = "%Y%m%d%H%M%S%.3fZ";
    let input = "4\t3\t\u{c}\t\t3\t\u{c}\t5\t3\t60Z";
    let ts = Utc.datetime_from_str(input, fmt).unwrap();
    let fmted = ts.format(fmt).to_string(); // 00040303050360.000Z
    assert_eq!(input, fmted);
}

There are certainly more of these with fuzzing target:

#![no_main]
use libfuzzer_sys::fuzz_target;

use chrono::{TimeZone, Utc};

static FMT: &str = "%Y%m%d%H%M%S%.3fZ";

fuzz_target!(|data: &[u8]| {
    if let Ok(s) = std::str::from_utf8(data) {
        if let Ok(ts) = Utc.datetime_from_str(s, FMT) {
            let rt = ts.format(FMT).to_string();

            assert_eq!(s, rt);
        }
    }
});

As far as I understand by looking at the documentation, "4\t3" should not get through "%Y%m" as "%Y" should be zero padded 4 positive digits. Overall I think the format string in question should only allow input which is formatted exactly same, though I read that the %.xf might be lenient for the number of zeroes. I'll try to see if I can offer any help with this. Could be that what I am after is out of scope of chrono.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions