diff --git a/fuzz/fuzz_targets/cranelift-fuzzgen.rs b/fuzz/fuzz_targets/cranelift-fuzzgen.rs index 2a502ef198..234feb8ea2 100644 --- a/fuzz/fuzz_targets/cranelift-fuzzgen.rs +++ b/fuzz/fuzz_targets/cranelift-fuzzgen.rs @@ -7,14 +7,17 @@ use cranelift_filetests::function_runner::{CompiledFunction, SingleFunctionCompi use cranelift_fuzzgen::*; use cranelift_interpreter::environment::FuncIndex; use cranelift_interpreter::environment::FunctionStore; -use cranelift_interpreter::interpreter::{Interpreter, InterpreterState}; +use cranelift_interpreter::interpreter::{Interpreter, InterpreterError, InterpreterState}; use cranelift_interpreter::step::ControlFlow; use cranelift_interpreter::step::CraneliftTrap; +const INTERPRETER_FUEL: u64 = 4096; + #[derive(Debug)] enum RunResult { Success(Vec), Trap(CraneliftTrap), + Timeout, Error(Box), } @@ -36,7 +39,8 @@ fn run_in_interpreter(interpreter: &mut Interpreter, args: &[DataValue]) -> RunR Ok(ControlFlow::Return(results)) => RunResult::Success(results.to_vec()), Ok(ControlFlow::Trap(trap)) => RunResult::Trap(trap), Ok(cf) => RunResult::Error(format!("Unrecognized exit ControlFlow: {:?}", cf).into()), - Err(e) => RunResult::Error(format!("InterpreterError: {:?}", e).into()), + Err(InterpreterError::FuelExhausted) => RunResult::Timeout, + Err(e) => RunResult::Error(e.into()), } } @@ -46,12 +50,12 @@ fn run_in_host(compiled_fn: &CompiledFunction, args: &[DataValue]) -> RunResult } fuzz_target!(|testcase: TestCase| { - let mut interpreter = { + let build_interpreter = || { let mut env = FunctionStore::default(); env.add(testcase.func.name.to_string(), &testcase.func); let state = InterpreterState::default().with_function_store(env); - let interpreter = Interpreter::new(state); + let interpreter = Interpreter::new(state).with_fuel(Some(INTERPRETER_FUEL)); interpreter }; @@ -60,6 +64,9 @@ fuzz_target!(|testcase: TestCase| { let compiled_fn = host_compiler.compile(testcase.func.clone()).unwrap(); for args in &testcase.inputs { + // We rebuild the interpreter every run so that we don't accidentally carry over any state + // between runs, such as fuel remaining. + let mut interpreter = build_interpreter(); let int_res = run_in_interpreter(&mut interpreter, args); match int_res { RunResult::Success(_) => {} @@ -71,6 +78,10 @@ fuzz_target!(|testcase: TestCase| { // not justify implementing it again here. return; } + RunResult::Timeout => { + // We probably generated an infinite loop, we can ignore this + return; + } RunResult::Error(_) => panic!("interpreter failed: {:?}", int_res), }