cranelift: CLIF Fuzzer limit instructions executed in interpreter
This commit is contained in:
@@ -7,14 +7,17 @@ use cranelift_filetests::function_runner::{CompiledFunction, SingleFunctionCompi
|
|||||||
use cranelift_fuzzgen::*;
|
use cranelift_fuzzgen::*;
|
||||||
use cranelift_interpreter::environment::FuncIndex;
|
use cranelift_interpreter::environment::FuncIndex;
|
||||||
use cranelift_interpreter::environment::FunctionStore;
|
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::ControlFlow;
|
||||||
use cranelift_interpreter::step::CraneliftTrap;
|
use cranelift_interpreter::step::CraneliftTrap;
|
||||||
|
|
||||||
|
const INTERPRETER_FUEL: u64 = 4096;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum RunResult {
|
enum RunResult {
|
||||||
Success(Vec<DataValue>),
|
Success(Vec<DataValue>),
|
||||||
Trap(CraneliftTrap),
|
Trap(CraneliftTrap),
|
||||||
|
Timeout,
|
||||||
Error(Box<dyn std::error::Error>),
|
Error(Box<dyn std::error::Error>),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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::Return(results)) => RunResult::Success(results.to_vec()),
|
||||||
Ok(ControlFlow::Trap(trap)) => RunResult::Trap(trap),
|
Ok(ControlFlow::Trap(trap)) => RunResult::Trap(trap),
|
||||||
Ok(cf) => RunResult::Error(format!("Unrecognized exit ControlFlow: {:?}", cf).into()),
|
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| {
|
fuzz_target!(|testcase: TestCase| {
|
||||||
let mut interpreter = {
|
let build_interpreter = || {
|
||||||
let mut env = FunctionStore::default();
|
let mut env = FunctionStore::default();
|
||||||
env.add(testcase.func.name.to_string(), &testcase.func);
|
env.add(testcase.func.name.to_string(), &testcase.func);
|
||||||
|
|
||||||
let state = InterpreterState::default().with_function_store(env);
|
let state = InterpreterState::default().with_function_store(env);
|
||||||
let interpreter = Interpreter::new(state);
|
let interpreter = Interpreter::new(state).with_fuel(Some(INTERPRETER_FUEL));
|
||||||
interpreter
|
interpreter
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -60,6 +64,9 @@ fuzz_target!(|testcase: TestCase| {
|
|||||||
let compiled_fn = host_compiler.compile(testcase.func.clone()).unwrap();
|
let compiled_fn = host_compiler.compile(testcase.func.clone()).unwrap();
|
||||||
|
|
||||||
for args in &testcase.inputs {
|
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);
|
let int_res = run_in_interpreter(&mut interpreter, args);
|
||||||
match int_res {
|
match int_res {
|
||||||
RunResult::Success(_) => {}
|
RunResult::Success(_) => {}
|
||||||
@@ -71,6 +78,10 @@ fuzz_target!(|testcase: TestCase| {
|
|||||||
// not justify implementing it again here.
|
// not justify implementing it again here.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
RunResult::Timeout => {
|
||||||
|
// We probably generated an infinite loop, we can ignore this
|
||||||
|
return;
|
||||||
|
}
|
||||||
RunResult::Error(_) => panic!("interpreter failed: {:?}", int_res),
|
RunResult::Error(_) => panic!("interpreter failed: {:?}", int_res),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user