use ffsync::protocol::framing::Frame;
use ffsync::protocol::message::*;
use std::path::PathBuf;
fn dump(name: &str, dir: &str, frame: Frame) {
let p = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("fuzz/corpus")
.join(dir);
std::fs::create_dir_all(&p).unwrap();
std::fs::write(p.join(name), frame.payload).unwrap();
}
#[test]
fn dump_fuzz_corpus() {
let h = Hello {
version: ffsync::protocol::VERSION,
flags: FLAG_TRUST_TIMES,
role: Role::Sender,
cdc_min: 16384,
cdc_avg: 65536,
cdc_max: 262144,
file_size: 1024,
file_mtime: 1_700_000_000,
file_mtime_nanos: 5,
path: "a.bin".into(),
};
dump("hello_valid", "hello", h.clone().into_frame().unwrap());
dump(
"hello_zero",
"hello",
Hello {
version: 4,
flags: 0,
role: Role::Receiver,
cdc_min: 0,
cdc_avg: 0,
cdc_max: 0,
file_size: 0,
file_mtime: 0,
file_mtime_nanos: 0,
path: String::new(),
}
.into_frame()
.unwrap(),
);
let mc = ManifestChunk {
hash: blake3::Hash::from_bytes([7u8; 32]),
offset: 4096,
length: 65536,
};
dump("mc_valid", "manifest", mc.into_frame().unwrap());
let pl = PlanEntry::Local {
target_offset: 0,
length: 65536,
source_offset: 8192,
hash: blake3::Hash::from_bytes([1u8; 32]),
};
dump("plan_local", "plan", pl.into_frame().unwrap());
let pr = PlanEntry::Remote {
target_offset: 65536,
length: 262144,
hash: blake3::Hash::from_bytes([2u8; 32]),
};
dump("plan_remote", "plan", pr.into_frame().unwrap());
let tb = TreeBegin {
flags: TREE_FLAG_PARALLEL | TREE_FLAG_METADATA | TREE_FLAG_EXCLUDES | TREE_FLAG_NEGATION,
parallel: 4,
excludes: vec!["*.log".into(), "!keep.log".into()],
entries: vec![
TreeEntryWire {
rel_path: "a/b/c.bin".into(),
kind: 0,
size: 12345,
mtime_secs: 1_700_000_000,
mtime_nanos: 9,
mode: 0o644,
},
TreeEntryWire {
rel_path: "d/".into(),
kind: 1,
size: 0,
mtime_secs: 0,
mtime_nanos: 0,
mode: 0,
},
],
};
dump("tree_begin_full", "tree_begin", tb.into_frame().unwrap());
dump(
"tree_begin_min",
"tree_begin",
TreeBegin {
flags: 0,
parallel: 0,
excludes: vec![],
entries: vec![],
}
.into_frame()
.unwrap(),
);
dump(
"tw",
"tree_small",
TreeWorker { worker_index: 3 }.into_frame().unwrap(),
);
dump(
"tf",
"tree_small",
TreeFile {
rel_path: "x/y.txt".into(),
}
.into_frame()
.unwrap(),
);
dump(
"te",
"tree_small",
TreeEnd {
deleted_count: 2,
deleted_bytes: 999,
}
.into_frame()
.unwrap(),
);
dump(
"err",
"tree_small",
encode_error(ErrorCode::BadFrame, "boom").unwrap(),
);
let p = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("fuzz/corpus/frame");
std::fs::create_dir_all(&p).unwrap();
let mut stream = Vec::new();
stream.extend_from_slice(&4u32.to_le_bytes());
stream.extend_from_slice(&ffsync::protocol::framing::T_HELLO.to_le_bytes());
stream.extend_from_slice(b"FFSY");
std::fs::write(p.join("tiny_valid"), &stream).unwrap();
let mut bad = Vec::new();
bad.extend_from_slice(&u32::MAX.to_le_bytes()); std::fs::write(p.join("absurd_len"), &bad).unwrap();
std::fs::write(p.join("empty"), b"").unwrap();
}