fuzz/fuzz_targets/wav_chunks.rs
what this file is for · fuzz · 46 lines · the same file on GitHub
The file as it is in the tree, in the colours you chose. A line number is a link, and so is every box in this file’s diagram: it opens here with the function it names marked.
// SPDX-License-Identifier: GPL-3.0-or-later
//! The RIFF chunk walker in `veilvoice-meta`, coverage-guided.
//!
//! This one walks a flat list of chunks whose sizes come from the file, so its
//! termination depends on values an attacker chooses -- the shape F-4 had.
//!
//! The interesting property is not only "does not crash": a *cleaned* WAV is
//! handed back to the user as safe, so it has to actually be a WAV, and its
//! RIFF size field has to describe the bytes that were written. A cleaner that
//! returns a corrupt file has failed even though it did not panic.
#![no_main]
use libfuzzer_sys::fuzz_target;
use veilvoice_meta::{clean_wav_bytes, is_wav, Policy};
fuzz_target!(|data: &[u8]| {
for policy in [Policy::Strip, Policy::Realistic] {
let Ok((cleaned, _report)) = clean_wav_bytes(data, policy) else {
continue;
};
assert!(
is_wav(&cleaned),
"the cleaner returned something that is not a WAV"
);
// The size field must describe the file, or the result does not open.
let declared = u32::from_le_bytes([cleaned[4], cleaned[5], cleaned[6], cleaned[7]]) as u64;
assert_eq!(
declared + 8,
cleaned.len() as u64,
"RIFF size field does not match the length written"
);
// Cleaning is idempotent: a file this crate produced must survive being
// cleaned again, and must not change. If it does not, the output was
// not really clean.
if policy == Policy::Strip {
let (twice, report) =
clean_wav_bytes(&cleaned, Policy::Strip).expect("a cleaned WAV must re-clean");
assert!(!report.changed, "a cleaned WAV still had something to strip");
assert_eq!(twice, cleaned, "re-cleaning changed the bytes");
}
}
});