diff --git a/Cargo.toml b/Cargo.toml index bcb32da..2826b68 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,10 @@ thiserror = "2.0.17" [profile.dev] debug = true +[[bin]] +path = "fuzz/gencorpus.rs" +name = "gencorpus" + [[test]] path = "fuzz/fuzz.rs" name = "fuzz" \ No newline at end of file diff --git a/fuzz/fuzz.rs b/fuzz/fuzz.rs index 69804e8..72f751b 100644 --- a/fuzz/fuzz.rs +++ b/fuzz/fuzz.rs @@ -19,7 +19,7 @@ pub unsafe extern "C" fn LLVMFuzzerTestOneInput(input: *const u8, len: usize) -> let mut proc = Command::new("atom.py") .stdin(Stdio::piped()) .spawn() - .unwrap(); + .expect("failed to start atom.py"); proc.stdin .as_mut() diff --git a/fuzz/gencorpus.rs b/fuzz/gencorpus.rs new file mode 100644 index 0000000..67ba1e3 --- /dev/null +++ b/fuzz/gencorpus.rs @@ -0,0 +1,64 @@ +use std::{ + env, + error::Error, + fs::{self, OpenOptions}, + io::Write, + path::PathBuf, +}; + +use gentoo_utils::{ + atom::Atom, + ebuild::{Depend, repo::Repo}, +}; + +fn main() -> Result<(), Box> { + let corpus_dir = PathBuf::from( + env::args() + .nth(1) + .expect("expected corpus directory as first argument"), + ); + + fs::create_dir_all(&corpus_dir)?; + + let repo = Repo::new("/var/db/repos/gentoo"); + let mut atoms = Vec::new(); + + for category in repo.categories()? { + for ebuild in category?.ebuilds()? { + let depend = ebuild?.depend().to_vec(); + + for expr in depend { + walk_expr(&mut atoms, &expr); + } + } + } + + for (i, atom) in atoms.iter().enumerate() { + let path = corpus_dir.as_path().join(i.to_string()); + let mut file = OpenOptions::new() + .write(true) + .truncate(true) + .create(true) + .open(path)?; + + write!(file, "{atom}")?; + } + + Ok(()) +} + +fn walk_expr(atoms: &mut Vec, depend: &Depend) { + match depend { + Depend::Element(atom) => { + atoms.push(atom.clone()); + } + Depend::AllOf(exprs) + | Depend::OneOf(exprs) + | Depend::AnyOf(exprs) + | Depend::ConditionalGroup(_, exprs) => { + for expr in exprs { + walk_expr(atoms, expr); + } + } + } +} diff --git a/fuzz/meson.build b/fuzz/meson.build index c4b5e8d..d6809f6 100644 --- a/fuzz/meson.build +++ b/fuzz/meson.build @@ -1,5 +1,20 @@ cbindgen = find_program('cbindgen') +gencorpus = executable( + 'gencorpus', + 'gencorpus.rs', + dependencies: [mon], + link_with: [gentoo_utils], +) + +corpus_directory = meson.current_build_dir() / 'corpus' + +corpus = custom_target( + 'corpus', + output: 'corpus', + command: [gencorpus, corpus_directory], +) + fuzz_h = custom_target( 'fuzz_h', input: 'fuzz.rs', @@ -20,8 +35,10 @@ fuzz_rs = static_library( link_with: [gentoo_utils], ) -fuzz_cpp = executable( +fuzz = executable( 'fuzz', link_args: ['-fsanitize=fuzzer'], link_with: [fuzz_rs], ) + +test('fuzz', fuzz, args: [corpus_directory], depends: [corpus], timeout: 0) diff --git a/meson.build b/meson.build index 401adf6..c415bf4 100644 --- a/meson.build +++ b/meson.build @@ -6,6 +6,7 @@ project( ) rust = import('rust') +fs = import('fs') mon = dependency('mon-0.1-rs') get = dependency('get-0.1-rs')