From e01637fd3a0a59ffea320a7df9770e73f486c91e Mon Sep 17 00:00:00 2001 From: John Turner Date: Tue, 18 Nov 2025 22:43:22 +0000 Subject: setup meson to allow building multiple fuzzers easily --- fuzz/atom/parser/fuzz.rs | 100 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 fuzz/atom/parser/fuzz.rs (limited to 'fuzz/atom/parser/fuzz.rs') diff --git a/fuzz/atom/parser/fuzz.rs b/fuzz/atom/parser/fuzz.rs new file mode 100644 index 0000000..610e08b --- /dev/null +++ b/fuzz/atom/parser/fuzz.rs @@ -0,0 +1,100 @@ +use core::slice; +use gentoo_utils::{Parseable, atom::Atom}; +use mon::{Parser, ParserFinishedError, input::InputIter}; +use std::{ + io::{BufRead, BufReader, Write}, + process::{ChildStdin, ChildStdout, Command, Stdio}, + sync::{LazyLock, Mutex}, +}; + +struct PyProcess { + stdin: Mutex, + stdout: Mutex>, + buffer: Mutex, +} + +#[allow(clippy::missing_safety_doc, clippy::needless_return)] +#[unsafe(no_mangle)] +pub unsafe extern "C" fn LLVMFuzzerTestOneInput(input: *const u8, len: usize) -> i32 { + static PY_PROCESS: LazyLock = LazyLock::new(|| { + #[allow(clippy::zombie_processes)] + let mut proc = Command::new("atom.py") + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::inherit()) + .spawn() + .expect("failed to spawn atom.py"); + + let stdin = Mutex::new(proc.stdin.take().unwrap()); + let stdout = Mutex::new(BufReader::new(proc.stdout.take().unwrap())); + + PyProcess { + stdin, + stdout, + buffer: Mutex::new(String::new()), + } + }); + + let slice = unsafe { slice::from_raw_parts(input, len) }; + + if slice.iter().any(|b| !b.is_ascii_graphic()) { + return -1; + } + + let str = match str::from_utf8(slice) { + Ok(str) => str, + Err(_) => return -1, + }; + + let atom = str.trim(); + + let mut stdin = PY_PROCESS.stdin.lock().expect("failed to get stdin lock"); + + writeln!(&mut stdin, "{atom}").expect("failed to write to python stdin"); + + let mut stdout = PY_PROCESS.stdout.lock().expect("failed to get stdout lock"); + + let mut buffer = PY_PROCESS.buffer.lock().expect("failed to get buffer lock"); + + buffer.clear(); + + stdout + .read_line(&mut buffer) + .expect("failed to readline from python"); + + let portage_result = match buffer.as_str().trim() { + "0" => true, + "1" => false, + result => panic!("got unexpected result from python: {result}"), + }; + + let gentoo_utils_result = Atom::parser().parse_finished(InputIter::new(atom)); + + match (portage_result, gentoo_utils_result) { + (true, Ok(_)) => { + eprintln!("agreement that {atom} is valid"); + } + (false, Err(_)) => { + eprintln!("agreement that {atom} is invalid"); + } + (true, Err(_)) => { + panic!("rejected valid atom: {atom}"); + } + (false, Ok(atom)) + if atom.usedeps().iter().any(|usedep| { + atom.usedeps() + .iter() + .filter(|u| usedep.flag() == u.flag()) + .count() + > 1 + }) => + { + eprintln!("disagreement due to duplicates in usedeps"); + } + (false, Ok(_)) => { + panic!("accpeted invalid atom: {atom}") + } + } + + return 0; +} -- cgit v1.2.3