#Fuzzing random crates
23 messages ยท Page 1 of 1 (latest)
What would fuzzing experts suggest here https://github.com/chronotope/chrono/pull/559#discussion_r996480395 my intuition is that more successful fuzz passes would allow better fuzzing performance, but maybe I'm wrong and its not significant
for precedent, the built-in implementations in arbitrary prefer folding inputs into the valid range over rejecting them
and my experience is that writing a highly rejecting Arbitrary impl causes ineffective fuzzing
oh but in this case it's just the difference between 365 and 366? I wouldn't worry much about that failure rate
Another great way to help the ecosystem out is to check out the top crates on crates.io and seeing if any of them look easy to add a fuzzer for (or they may already have one!)
I tend to use https://github.com/rust-fuzz/cargo-fuzz which gives you a cargo fuzz init command you can run in any library crate. Then, it's largely like any other test suite.
https://github.com/pdf-rs/pdf/pull/104/files is a sample PR where I added a fuzzing harness to pdf.
Past that, it's mostly just running cargo fuzz run, passing it the target name, and waiting for it to find a bug. If you have sample files, you can put them in the corpus directory to help the fuzzer understand the structure of the file format quicker (For example, put in some PDFs from the tests directory if you're fuzzing a PDF parser).
If you're fuzzing something more complex than a parser, have a look at https://rust-fuzz.github.io/book/cargo-fuzz/structure-aware-fuzzing.html
hi @fervent fiber hi @solemn trellis you were interested in this thread i assume
yeah, just thought it would be a good idea
thanks for this 522
?play
use yaml_rust::{YamlLoader, YamlEmitter};
fn main() {
let data = "\u{e}:\nB{BB\u{8}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1}\u{1}\u{1}\u{1}\u{1}\u{1}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}uuu:\n<:\n::\n~\u{3}";
let mut emitted = String::new();
let mut emitter = YamlEmitter::new(&mut emitted);
if let Ok(yamls) = yaml_rust::YamlLoader::load_from_str(data) {
if yamls.len() == 1 {
let yaml = &yamls[0];
dbg!(yaml);
if emitter.dump(yaml).is_err() {
return;
}
let reloaded = YamlLoader::load_from_str(&emitted).unwrap();
//assert_eq!(reloaded, yamls);
}
}
}
[src/main.rs:12] yaml = Hash(
{
String(
"\u{e}",
): Null,
String(
"B{BB\u{8}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1}\u{1}\u{1}\u{1}\u{1}\u{1}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}uuu",
): Null,
String(
"<",
): Null,
String(
":",
): String(
"~\u{3}",
),
},
)
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: ScanError { mark: Marker { index: 16, line: 3, col: 0 }, info: "while parsing a block mapping, did not find expected key" }', src/main.rs:17:64
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
hmmmm
this is a WEIRD round trip bug
the emitter is generating invalid yaml
but why
To limit the amount of lookahead required, the โ:โ indicator must appear at most 1024 Unicode characters beyond the start of the key. In addition, the key is restricted to a single line.
ahhhh
"x"*1025 + ":\n" is invalid yaml
so the issue is that invalid yaml is being emitted

