test: three more cargo-fuzz targets + test-fuzz-long recipe
- command_roundtrip: structure-aware (via arbitrary crate) Command encode → parse → equal. Symmetric to cobs_roundtrip. - cobs_decoder_multi_frame: chunked feeding with arbitrary split sizes; asserts bounded payload and that command count never exceeds sentinel count. - cobs_chunk_invariant: same stream through two decoders (chunked vs all-at-once) must produce the same command sequence. Adds test-fuzz-long recipe (600s per target, ~1h 10m total) for CI cron / pre-release. All seven targets smoke-tested at 100k runs each with zero findings.
This commit is contained in:
5 files changed
+274
No files matched your search
@@ -0,0 +1,41 @@
|
||||
//! Chunk-boundary invariance: the same input stream fed into two
|
||||
//! decoders — one in arbitrary chunks, one all-at-once — must produce
|
||||
//! the same command sequence.
|
||||
|
||||
#![no_main]
|
||||
|
||||
use donglora_protocol::Command;
|
||||
use donglora_protocol::framing::CobsDecoder;
|
||||
use libfuzzer_sys::fuzz_target;
|
||||
|
||||
fn drain(stream: &[u8], chunk_sched: &[u8]) -> Vec<Command> {
|
||||
let mut out: Vec<Command> = Vec::new();
|
||||
let mut decoder = CobsDecoder::new();
|
||||
let mut cursor = 0;
|
||||
let mut idx = 0;
|
||||
while cursor < stream.len() {
|
||||
let split = if idx < chunk_sched.len() {
|
||||
((chunk_sched[idx] as usize) % 64) + 1
|
||||
} else {
|
||||
16
|
||||
};
|
||||
idx += 1;
|
||||
let end = (cursor + split).min(stream.len());
|
||||
decoder.feed(&stream[cursor..end], |c| out.push(c));
|
||||
cursor = end;
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
fuzz_target!(|data: &[u8]| {
|
||||
let split = 32.min(data.len());
|
||||
let (sched, stream) = data.split_at(split);
|
||||
|
||||
let whole: Vec<Command> = {
|
||||
let mut v = Vec::new();
|
||||
CobsDecoder::new().feed(stream, |c| v.push(c));
|
||||
v
|
||||
};
|
||||
let chunked = drain(stream, sched);
|
||||
assert_eq!(whole, chunked);
|
||||
});
|
||||
Reference in new issue
Block a user