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().check_finished(InputIter::new(atom)).is_ok(); match (portage_result, gentoo_utils_result) { (true, true) => { eprintln!("agreement that {atom} is valid"); } (false, false) => { eprintln!("agreement that {atom} is invalid"); } (true, false) => { panic!("rejected valid atom: {atom}"); } (false, true) => { panic!("accpeted invalid atom: {atom}") } } return 0; }