AFL++ persistent mode runs the fuzz target in a loop. Because static initialization (like OnceLock, lazy_static, or once_cell::Lazy) only executes once, subsequent iterations skip these paths, which can cause AFL's stability metric to drop.
To fix this, use the fuzz_with_reset! macro. It accepts two closures:
- The fuzzing closure: Receives the input
data: &[u8] and contains your fuzzing logic. - The reset closure: Executed after each successful iteration to clear or reset your static state.
use std::sync::Mutex;
static CACHE: Mutex<Option<Vec<u8>>> = Mutex::new(None);
fn main() {
afl::fuzz_with_reset!(|data: &[u8]| {
let mut cache = CACHE.lock().unwrap();
if cache.is_none() {
*cache = Some(data.to_vec());
}
drop(cache);
// ... fuzz logic ...
}, || {
// Reset closure: called after each successful iteration
*CACHE.lock().unwrap() = None;
});
}