From f279f75a19172c9f8761c1fb9b5cbd1066175cc8 Mon Sep 17 00:00:00 2001 From: John Turner Date: Mon, 8 Dec 2025 01:38:48 +0000 Subject: [PATCH] hookup atom parser fuzzer to read and write to stdin/stdout --- fuzz/atom/parser/fuzz.rs | 110 ++++++++++++----------------------- fuzz/atom/parser/meson.build | 1 - 2 files changed, 37 insertions(+), 74 deletions(-) diff --git a/fuzz/atom/parser/fuzz.rs b/fuzz/atom/parser/fuzz.rs index 9af41f2..db41eff 100644 --- a/fuzz/atom/parser/fuzz.rs +++ b/fuzz/atom/parser/fuzz.rs @@ -1,100 +1,64 @@ +#![allow(clippy::missing_safety_doc)] + 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}, + io::{self, Write}, sync::{LazyLock, Mutex}, }; -struct PyProcess { - stdin: Mutex, - stdout: Mutex>, - buffer: Mutex, +#[derive(Debug)] +struct State { + input: io::Stdin, + output: io::Stdout, } -#[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()), - } + static PIPES: LazyLock> = LazyLock::new(|| { + Mutex::new(State { + input: io::stdin(), + output: io::stdout(), + }) }); let slice = unsafe { slice::from_raw_parts(input, len) }; + let str = str::from_utf8(slice).expect("expected ascii input"); - if slice.iter().any(|b| !b.is_ascii_graphic()) { + if str.chars().any(|c| !c.is_ascii_graphic()) { return -1; } - let str = match str::from_utf8(slice) { - Ok(str) => str, - Err(_) => return -1, + let mut state = PIPES.lock().unwrap(); + + writeln!(&mut state.output, "{str}").unwrap(); + + let mut buffer = String::new(); + + state.input.read_line(&mut buffer).unwrap(); + + let control = match buffer.as_str().trim() { + "0" => Ok(()), + "1" => Err(()), + other => panic!("unexpected input from pipes: {other}"), }; - let atom = str.trim(); + let gentoo_utils = Atom::parse(str); - 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"); + match (control, gentoo_utils) { + (Ok(_), Ok(_)) => { + eprintln!("agreement that {str} is valid"); } - (false, Err(_)) => { - eprintln!("agreement that {atom} is invalid"); + (Err(_), Err(_)) => { + eprintln!("agreement that {str} is invalid"); } - (true, Err(ParserFinishedError::Err(it) | ParserFinishedError::Unfinished(it))) => { - panic!("rejected valid atom: {atom}: {}", it.rest()); + (Ok(_), Err(rest)) => { + panic!("disagreement on {str}\ncontrol:Ok\ngentoo-utils:Err({rest})"); } - (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}") + (Err(_), Ok(_)) => { + panic!("disagreement on {str}\ncontrol:Err\ngentoo-utils:Ok") } } - return 0; + 0 } diff --git a/fuzz/atom/parser/meson.build b/fuzz/atom/parser/meson.build index 9272a27..24ee1b7 100644 --- a/fuzz/atom/parser/meson.build +++ b/fuzz/atom/parser/meson.build @@ -20,7 +20,6 @@ fuzz_rs = static_library( '-Cllvm-args=-sanitizer-coverage-level=3', '-Cllvm-args=-sanitizer-coverage-inline-8bit-counters', ], - dependencies: [mon], link_with: [gentoo_utils], )