diff --git a/crates/libafl/src/corpus/inmemory.rs b/crates/libafl/src/corpus/inmemory.rs index 11dafc75b2b..ff81157bcce 100644 --- a/crates/libafl/src/corpus/inmemory.rs +++ b/crates/libafl/src/corpus/inmemory.rs @@ -286,8 +286,9 @@ impl TestcaseStorage { id } + /// Insert a testcase with a specific `CorpusId`. Handle with care! #[cfg(not(feature = "corpus_btreemap"))] - fn insert_inner_with_id( + pub fn insert_inner_with_id( &mut self, testcase: RefCell>, is_disabled: bool, @@ -325,8 +326,9 @@ impl TestcaseStorage { Ok(()) } + /// Insert a testcase with a specific `CorpusId`. Handle with care! #[cfg(feature = "corpus_btreemap")] - fn insert_inner_with_id( + pub fn insert_inner_with_id( &mut self, testcase: RefCell>, is_disabled: bool, @@ -716,4 +718,63 @@ mod tests { Ok(()) } + + #[test] + #[cfg(not(feature = "corpus_btreemap"))] + fn test_corpus_linked_list_integrity() -> Result<(), Error> { + let (mut corpus, ids) = setup_corpus(); + // ids: [0, 1, 2] + // Enabled: 0 -> 1 -> 2 + // First: 0, Last: 2 + + assert_eq!(corpus.first(), Some(ids[0])); + assert_eq!(corpus.last(), Some(ids[2])); + assert_eq!(corpus.next(ids[0]), Some(ids[1])); + assert_eq!(corpus.next(ids[1]), Some(ids[2])); + assert_eq!(corpus.next(ids[2]), None); + assert_eq!(corpus.prev(ids[0]), None); + assert_eq!(corpus.prev(ids[1]), Some(ids[0])); + assert_eq!(corpus.prev(ids[2]), Some(ids[1])); + + // Disable first (0) + corpus.disable(ids[0])?; + // Enabled: 1 -> 2 + // Disabled: 0 + assert_eq!(corpus.first(), Some(ids[1])); + assert_eq!(corpus.last(), Some(ids[2])); + assert_eq!(corpus.prev(ids[1]), None); + assert_eq!(corpus.next(ids[1]), Some(ids[2])); + + // Disable last (2) + corpus.disable(ids[2])?; + // Enabled: 1 + // Disabled: 0 -> 2 + assert_eq!(corpus.first(), Some(ids[1])); + assert_eq!(corpus.last(), Some(ids[1])); + assert_eq!(corpus.prev(ids[1]), None); + assert_eq!(corpus.next(ids[1]), None); + + // Disable remaining (1) + corpus.disable(ids[1])?; + // Enabled: (empty) + // Disabled: 0 -> 2 -> 1 + assert_eq!(corpus.first(), None); + assert_eq!(corpus.last(), None); + + // Enable 0 + corpus.enable(ids[0])?; + // Enabled: 0 + assert_eq!(corpus.first(), Some(ids[0])); + assert_eq!(corpus.last(), Some(ids[0])); + + // Enable 1 + corpus.enable(ids[1])?; + // Enabled: 0 -> 1 + assert_eq!(corpus.first(), Some(ids[0])); + assert_eq!(corpus.last(), Some(ids[1])); + assert_eq!(corpus.next(ids[0]), Some(ids[1])); + assert_eq!(corpus.prev(ids[1]), Some(ids[0])); + + Ok(()) + } } diff --git a/crates/libafl/src/corpus/mod.rs b/crates/libafl/src/corpus/mod.rs index 1ff4732e550..47b34eb6f29 100644 --- a/crates/libafl/src/corpus/mod.rs +++ b/crates/libafl/src/corpus/mod.rs @@ -212,10 +212,12 @@ pub trait HasCurrentCorpusId { /// Set the current corpus index; we have started processing this corpus entry fn set_corpus_id(&mut self, id: CorpusId) -> Result<(), Error>; - /// Clear the current corpus index; we are done with this entry + /// Clear the current corpus index; we are done with this entry. + /// This can also be used by as stage to signal that subsequent stages should be skipped. fn clear_corpus_id(&mut self) -> Result<(), Error>; - /// Fetch the current corpus index -- typically used after a state recovery or transfer + /// Fetch the current corpus index -- typically used after a state recovery or transfer. + /// If it is `None`, the corpus scheduler should be called to schedule the next testcase. fn current_corpus_id(&self) -> Result, Error>; } diff --git a/crates/libafl/src/corpus/testcase.rs b/crates/libafl/src/corpus/testcase.rs index 0b7dc8ddbb6..f88f32752b9 100644 --- a/crates/libafl/src/corpus/testcase.rs +++ b/crates/libafl/src/corpus/testcase.rs @@ -199,7 +199,7 @@ impl Testcase { /// Get `disabled` #[inline] - pub fn disabled(&mut self) -> bool { + pub fn disabled(&self) -> bool { self.disabled } diff --git a/crates/libafl/src/events/simple.rs b/crates/libafl/src/events/simple.rs index e5b4dc16207..cb81361e81d 100644 --- a/crates/libafl/src/events/simple.rs +++ b/crates/libafl/src/events/simple.rs @@ -1,5 +1,4 @@ //! A very simple event manager, that just supports log outputs, but no multiprocessing - use alloc::vec::Vec; #[cfg(feature = "std")] use core::sync::atomic::{Ordering, compiler_fence}; @@ -189,7 +188,6 @@ impl SimpleEventManager where I: Debug, MT: Monitor, - S: Stoppable, { /// Creates a new [`SimpleEventManager`]. pub fn new(monitor: MT) -> Self { diff --git a/crates/libafl/src/executors/forkserver.rs b/crates/libafl/src/executors/forkserver.rs index 232cb59d9d9..299f7c398d7 100644 --- a/crates/libafl/src/executors/forkserver.rs +++ b/crates/libafl/src/executors/forkserver.rs @@ -119,26 +119,30 @@ const FAILED_TO_START_FORKSERVER_MSG: &str = "Failed to start forkserver"; fn report_error_and_exit(status: i32) -> Result<(), Error> { /* Report on the error received via the forkserver controller and exit */ match status { - FS_ERROR_MAP_SIZE => - Err(Error::unknown( - format!( - "{AFL_MAP_SIZE_ENV_VAR} is not set and fuzzing target reports that the required size is very large. Solution: Run the fuzzing target stand-alone with the environment variable AFL_DEBUG=1 set and set the value for __afl_final_loc in the {AFL_MAP_SIZE_ENV_VAR} environment variable for afl-fuzz."))), - FS_ERROR_MAP_ADDR => - Err(Error::unknown( - "the fuzzing target reports that hardcoded map address might be the reason the mmap of the shared memory failed. Solution: recompile the target with either afl-clang-lto and do not set AFL_LLVM_MAP_ADDR or recompile with afl-clang-fast.".to_string())), - FS_ERROR_SHM_OPEN => - Err(Error::unknown("the fuzzing target reports that the shm_open() call failed.".to_string())), - FS_ERROR_SHMAT => - Err(Error::unknown("the fuzzing target reports that the shmat() call failed.".to_string())), - FS_ERROR_MMAP => - Err(Error::unknown("the fuzzing target reports that the mmap() call to the shared memory failed.".to_string())), - FS_ERROR_OLD_CMPLOG => - Err(Error::unknown( - "the -c cmplog target was instrumented with an too old AFL++ version, you need to recompile it.".to_string())), - FS_ERROR_OLD_CMPLOG_QEMU => - Err(Error::unknown("The AFL++ QEMU/FRIDA loaders are from an older version, for -c you need to recompile it.".to_string())), - _ => - Err(Error::unknown(format!("unknown error code {status} from fuzzing target!"))), + FS_ERROR_MAP_SIZE => Err(Error::unknown(format!( + "{AFL_MAP_SIZE_ENV_VAR} is not set and fuzzing target reports that the required size is very large. Solution: Run the fuzzing target stand-alone with the environment variable AFL_DEBUG=1 set and set the value for __afl_final_loc in the {AFL_MAP_SIZE_ENV_VAR} environment variable for afl-fuzz." + ))), + FS_ERROR_MAP_ADDR => Err(Error::unknown( + "the fuzzing target reports that hardcoded map address might be the reason the mmap of the shared memory failed. Solution: recompile the target with either afl-clang-lto and do not set AFL_LLVM_MAP_ADDR or recompile with afl-clang-fast.", + )), + FS_ERROR_SHM_OPEN => Err(Error::unknown( + "the fuzzing target reports that the shm_open() call failed.", + )), + FS_ERROR_SHMAT => Err(Error::unknown( + "the fuzzing target reports that the shmat() call failed.", + )), + FS_ERROR_MMAP => Err(Error::unknown( + "the fuzzing target reports that the mmap() call to the shared memory failed.", + )), + FS_ERROR_OLD_CMPLOG => Err(Error::unknown( + "the -c cmplog target was instrumented with an too old AFL++ version, you need to recompile it.", + )), + FS_ERROR_OLD_CMPLOG_QEMU => Err(Error::unknown( + "The AFL++ QEMU/FRIDA loaders are from an older version, for -c you need to recompile it.", + )), + _ => Err(Error::unknown(format!( + "unknown error code {status} from fuzzing target!" + ))), } } @@ -422,7 +426,9 @@ impl Forkserver { }; if env::var(SHM_ENV_VAR).is_err() { - return Err(Error::unknown("__AFL_SHM_ID not set. It is necessary to set this env, otherwise the forkserver cannot communicate with the fuzzer".to_string())); + return Err(Error::unknown( + "__AFL_SHM_ID not set. It is necessary to set this env, otherwise the forkserver cannot communicate with the fuzzer", + )); } let afl_debug = if let Ok(afl_debug) = env::var("AFL_DEBUG") { diff --git a/crates/libafl/src/executors/inprocess/mod.rs b/crates/libafl/src/executors/inprocess/mod.rs index 2a1f5c03a0b..dfccc71c5b1 100644 --- a/crates/libafl/src/executors/inprocess/mod.rs +++ b/crates/libafl/src/executors/inprocess/mod.rs @@ -388,6 +388,8 @@ pub fn run_observers_and_save_state( #[cfg(test)] mod tests { use libafl_bolts::{rands::XkcdRand, tuples::tuple_list}; + #[cfg(feature = "serial_test")] + use serial_test::serial; use crate::{ StdFuzzer, @@ -401,6 +403,7 @@ mod tests { }; #[test] + #[cfg_attr(feature = "std", serial)] fn test_inmem_exec() { let mut harness = |_buf: &NopInput| ExitKind::Ok; let rand = XkcdRand::new(); diff --git a/crates/libafl/src/fuzzer/mod.rs b/crates/libafl/src/fuzzer/mod.rs index 21a55625430..c0475397b62 100644 --- a/crates/libafl/src/fuzzer/mod.rs +++ b/crates/libafl/src/fuzzer/mod.rs @@ -1409,6 +1409,7 @@ mod tests { use core::cell::RefCell; use libafl_bolts::rands::StdRand; + use serial_test::serial; use crate::{ StdFuzzer, @@ -1422,6 +1423,7 @@ mod tests { }; #[test] + #[serial] fn filtered_execution() { let execution_count = RefCell::new(0); let scheduler = StdScheduler::new(); diff --git a/crates/libafl/src/lib.rs b/crates/libafl/src/lib.rs index c896896d7e0..b35f6d5a1d9 100644 --- a/crates/libafl/src/lib.rs +++ b/crates/libafl/src/lib.rs @@ -108,6 +108,7 @@ mod tests { rands::{RomuDuoJrRand, StdRand}, tuples::tuple_list, }; + use serial_test::serial; #[cfg(miri)] use crate::stages::ExecutionCountRestartHelperMetadata; @@ -127,6 +128,7 @@ mod tests { }; #[test] + #[serial] fn test_fuzzer() { // # Safety // No concurrency per testcase diff --git a/crates/libafl/src/observers/map/mod.rs b/crates/libafl/src/observers/map/mod.rs index d07a49592f0..02e5a0a0dc2 100644 --- a/crates/libafl/src/observers/map/mod.rs +++ b/crates/libafl/src/observers/map/mod.rs @@ -79,8 +79,8 @@ pub use owned_map::*; /// # &mut feedback, /// # &mut (), /// # ).unwrap(); -/// let scheduler = IndexesLenTimeMinimizerScheduler::new(&edges_observer, QueueScheduler::new()); -/// # scheduler.cull(&state).unwrap(); +/// let mut scheduler = IndexesLenTimeMinimizerScheduler::new(&edges_observer, QueueScheduler::new()); +/// # scheduler.cull(&mut state).unwrap(); /// ``` /// /// [`MapObserver`] implementors: see [`StdMapObserver`] for an example implementation. diff --git a/crates/libafl/src/schedulers/accounting.rs b/crates/libafl/src/schedulers/accounting.rs index 87ba1c0084d..76250f15821 100644 --- a/crates/libafl/src/schedulers/accounting.rs +++ b/crates/libafl/src/schedulers/accounting.rs @@ -16,7 +16,7 @@ use crate::{ corpus::{Corpus, CorpusId}, observers::CanTrack, schedulers::{ - Scheduler, + RemovableScheduler, Scheduler, minimizer::{DEFAULT_SKIP_NON_FAVORED_PROB, IsFavoredMetadata, MinimizerScheduler}, }, state::{HasCorpus, HasRand}, @@ -112,7 +112,7 @@ pub struct CoverageAccountingScheduler<'a, CS, I, O> { impl Scheduler for CoverageAccountingScheduler<'_, CS, I, O> where - CS: Scheduler, + CS: Scheduler + RemovableScheduler, S: HasCorpus + HasMetadata + HasRand, I: HasLen, O: CanTrack, diff --git a/crates/libafl/src/schedulers/minimizer.rs b/crates/libafl/src/schedulers/minimizer.rs index 4d9f192053d..d21386294e3 100644 --- a/crates/libafl/src/schedulers/minimizer.rs +++ b/crates/libafl/src/schedulers/minimizer.rs @@ -84,7 +84,7 @@ where CS: RemovableScheduler + Scheduler, F: TestcasePenalty, M: for<'a> AsIter<'a, Item = usize> + SerdeAny + HasRefCnt, - S: HasCorpus + HasMetadata + HasRand, + S: HasCorpus + HasMetadata, { /// Replaces the [`Testcase`] at the given [`CorpusId`] fn on_replace( @@ -189,7 +189,7 @@ where impl Scheduler for MinimizerScheduler where - CS: Scheduler, + CS: Scheduler + RemovableScheduler, F: TestcasePenalty, M: for<'a> AsIter<'a, Item = usize> + SerdeAny + HasRefCnt, S: HasCorpus + HasMetadata + HasRand, @@ -268,24 +268,33 @@ where new_favoreds.push(*elem); // always retain current; we'll drop it later otherwise continue; } - let mut old = state.corpus().get(*old_id)?.borrow_mut(); - if factor > F::compute(state, &mut *old)? { - continue; - } - - let must_remove = { - let old_meta = old.metadata_map_mut().get_mut::().ok_or_else(|| { - Error::key_not_found(format!( - "{} needed for MinimizerScheduler not found in testcase #{old_id}", - type_name::() - )) - })?; - *old_meta.refcnt_mut() -= 1; - old_meta.refcnt() <= 0 - }; + match state.corpus().get(*old_id) { + Ok(testcase) => { + let mut old = testcase.borrow_mut(); + if factor > F::compute(state, &mut *old)? { + continue; + } - if must_remove && self.remove_metadata { - drop(old.metadata_map_mut().remove::()); + let must_remove = { + let old_meta = old.metadata_map_mut().get_mut::().ok_or_else(|| { + Error::key_not_found(format!( + "{} needed for MinimizerScheduler not found in testcase #{old_id}", + type_name::() + )) + })?; + *old_meta.refcnt_mut() -= 1; + old_meta.refcnt() <= 0 + }; + + if must_remove && self.remove_metadata { + drop(old.metadata_map_mut().remove::()); + } + } + Err(Error::KeyNotFound(_, _)) => { + log::warn!("Corpus entry {old_id} not found"); + continue; + } + Err(e) => return Err(e), } } @@ -319,9 +328,12 @@ where } /// Cull the [`Corpus`] using the [`MinimizerScheduler`] - pub fn cull(&self, state: &S) -> Result<(), Error> + pub fn cull(&mut self, state: &mut S) -> Result<(), Error> where - S: HasCorpus + HasMetadata, + S: HasCorpus + HasMetadata + HasRand, + CS: RemovableScheduler, + CS: Scheduler, + F: TestcasePenalty, { let Some(top_rated) = state.metadata_map().get::() else { return Ok(()); @@ -331,18 +343,34 @@ where for (key, id) in &top_rated.map { if !acc.contains(key) { - let mut entry = state.corpus().get(*id)?.borrow_mut(); - let meta = entry.metadata_map().get::().ok_or_else(|| { - Error::key_not_found(format!( - "{} needed for MinimizerScheduler not found in testcase #{id}", - type_name::() - )) - })?; - for elem in meta.as_iter() { - acc.insert(*elem); - } + let entry = state.corpus().get(*id); + match entry { + Ok(entry) => { + let mut entry = entry.borrow_mut(); + let meta = entry.metadata_map().get::().ok_or_else(|| { + Error::key_not_found(format!( + "{} needed for MinimizerScheduler not found in testcase #{id}", + type_name::() + )) + })?; + for elem in meta.as_iter() { + acc.insert(*elem); + } - entry.add_metadata(IsFavoredMetadata {}); + entry.add_metadata(IsFavoredMetadata {}); + } + Err(Error::KeyNotFound(_, _)) => { + // Fallback for disabled and removed testcases. + log::info!( + "Removing testcase #{id} from top rateds as it was no longer in the corpus!" + ); + self.on_remove(state, *id, &None)?; + return self.cull(state); + } + Err(err) => { + return Err(err); + } + } } } @@ -425,3 +453,53 @@ pub type LenTimeMinimizerScheduler = /// that exercise all the entries registered in the [`MapIndexesMetadata`]. pub type IndexesLenTimeMinimizerScheduler = MinimizerScheduler; + +#[cfg(test)] +mod tests { + use libafl_bolts::rands::StdRand; + + use crate::{ + HasMetadata, + corpus::{Corpus, InMemoryCorpus, Testcase}, + feedbacks::MapIndexesMetadata, + inputs::NopInput, + observers::{CanTrack, StdMapObserver}, + schedulers::{ + IndexesLenTimeMinimizerScheduler, MinimizerScheduler, QueueScheduler, Scheduler, + minimizer::TopRatedsMetadata, + }, + state::{HasCorpus, StdState}, + }; + + #[test] + fn test_minimizer_scheduler_update_score_crash() { + #[cfg(not(feature = "serdeany_autoreg"))] + unsafe { + libafl_bolts::serdeany::RegistryBuilder::register::(); + libafl_bolts::serdeany::RegistryBuilder::register::(); + } + let rand = StdRand::with_seed(0); + let observer = StdMapObserver::owned("map", vec![0u8; 16]).track_indices(); + let mut scheduler: IndexesLenTimeMinimizerScheduler = + MinimizerScheduler::new(&observer, QueueScheduler::new()); + + let mut corpus = InMemoryCorpus::new(); + let t1 = Testcase::new(NopInput {}); + let _id1 = corpus.add(t1).unwrap(); + + let mut state = + StdState::new(rand, corpus, InMemoryCorpus::new(), &mut (), &mut ()).unwrap(); + + state.add_metadata(TopRatedsMetadata::new()); + let top_rateds = state.metadata_mut::().unwrap(); + + top_rateds.map.insert(0, 999_usize.into()); + + let mut t2 = Testcase::new(NopInput {}); + let map_meta = MapIndexesMetadata::new(vec![0]); + t2.add_metadata(map_meta); + let id2 = state.corpus_mut().add(t2).unwrap(); + + scheduler.on_add(&mut state, id2).unwrap(); + } +} diff --git a/crates/libafl/src/schedulers/mod.rs b/crates/libafl/src/schedulers/mod.rs index 0b29ae2e094..31831253d29 100644 --- a/crates/libafl/src/schedulers/mod.rs +++ b/crates/libafl/src/schedulers/mod.rs @@ -78,10 +78,13 @@ where let current_id = *state.corpus().current(); let mut depth = match current_id { - Some(parent_idx) => state - .testcase(parent_idx)? - .metadata::()? - .depth(), + Some(parent_idx) => state.corpus().get_from_all(parent_idx).map_or_else( + |_| { + log::warn!("Parent testcase with id {parent_idx} not found! Removed?"); + Ok::(0) + }, + |v| Ok(v.borrow().metadata::()?.depth()), + )?, None => 0, }; @@ -138,7 +141,17 @@ where let current_id = *state.corpus().current(); if let Some(id) = current_id { - let mut testcase = state.testcase_mut(id)?; + let Ok(testcase) = state.corpus().get_from_all(id) else { + log::info!("Current testcase with id {id} not found! Removed?"); + return Ok(()); + }; + let mut testcase = testcase.borrow_mut(); + + if testcase.disabled() { + log::info!("Current testcase with id {id} is disabled!"); + return Ok(()); + } + let tcmeta = testcase.metadata_mut::()?; if tcmeta.handicap() >= 4 { diff --git a/crates/libafl/src/schedulers/queue.rs b/crates/libafl/src/schedulers/queue.rs index c9c8551479e..b4f7840fd3b 100644 --- a/crates/libafl/src/schedulers/queue.rs +++ b/crates/libafl/src/schedulers/queue.rs @@ -4,7 +4,7 @@ use alloc::borrow::ToOwned; use crate::{ Error, - corpus::{Corpus, CorpusId}, + corpus::{Corpus, CorpusId, Testcase}, schedulers::{HasQueueCycles, RemovableScheduler, Scheduler}, state::HasCorpus, }; @@ -16,7 +16,17 @@ pub struct QueueScheduler { runs_in_current_cycle: u64, } -impl RemovableScheduler for QueueScheduler {} +impl RemovableScheduler for QueueScheduler { + fn on_remove( + &mut self, + _state: &mut S, + _id: CorpusId, + _testcase: &Option>, + ) -> Result<(), Error> { + self.runs_in_current_cycle = self.runs_in_current_cycle.saturating_sub(1); + Ok(()) + } +} impl Scheduler for QueueScheduler where @@ -50,7 +60,7 @@ where .unwrap_or_else(|| state.corpus().first().unwrap()); self.runs_in_current_cycle += 1; - // TODO deal with corpus_counts decreasing due to removals + if self.runs_in_current_cycle >= state.corpus().count() as u64 { self.queue_cycles += 1; self.runs_in_current_cycle = 0; @@ -102,10 +112,10 @@ mod tests { use libafl_bolts::rands::StdRand; use crate::{ - corpus::{Corpus, OnDiskCorpus, Testcase}, + corpus::{Corpus, InMemoryCorpus, OnDiskCorpus, Testcase}, feedbacks::ConstFeedback, inputs::bytes::BytesInput, - schedulers::{QueueScheduler, Scheduler}, + schedulers::{QueueScheduler, RemovableScheduler, Scheduler}, state::{HasCorpus, StdState}, }; @@ -139,9 +149,54 @@ mod tests { .as_ref() .unwrap() .clone(); - assert_eq!(filename, "fancyfile"); fs::remove_dir_all("target/.test/fancy/path").unwrap(); } + + #[test] + fn test_queue_scheduler_removal() { + let rand = StdRand::with_seed(42); + let mut scheduler = QueueScheduler::new(); + + let mut q = InMemoryCorpus::::new(); + let t1 = Testcase::with_filename(BytesInput::new(vec![0_u8; 4]), "t1".into()); + let t2 = Testcase::with_filename(BytesInput::new(vec![0_u8; 4]), "t2".into()); + let t3 = Testcase::with_filename(BytesInput::new(vec![0_u8; 4]), "t3".into()); + + let id1 = q.add(t1).unwrap(); + let id2 = q.add(t2).unwrap(); + let id3 = q.add(t3).unwrap(); + + let mut feedback = ConstFeedback::new(false); + let mut objective = ConstFeedback::new(false); + + let mut state = StdState::new( + rand, + q, + InMemoryCorpus::new(), + &mut feedback, + &mut objective, + ) + .unwrap(); + + let next_id = scheduler.next(&mut state).unwrap(); + assert_eq!(next_id, id1); + assert_eq!(scheduler.runs_in_current_cycle, 1); + + state.corpus_mut().remove(id1).unwrap(); + scheduler + .on_remove(&mut state, id1, &None::>) + .unwrap(); + + let next_id = scheduler.next(&mut state).unwrap(); + assert_eq!(next_id, id2); + + assert_eq!(scheduler.queue_cycles, 0, "Cycle finished prematurely!"); + + let next_id = scheduler.next(&mut state).unwrap(); + assert_eq!(next_id, id3); + + assert_eq!(scheduler.queue_cycles, 1); + } } diff --git a/crates/libafl/src/schedulers/testcase_score.rs b/crates/libafl/src/schedulers/testcase_score.rs index a6259ae97da..582c46eb275 100644 --- a/crates/libafl/src/schedulers/testcase_score.rs +++ b/crates/libafl/src/schedulers/testcase_score.rs @@ -1,5 +1,5 @@ //! The `TestcaseScore` is an evaluator providing scores of corpus items. -use alloc::string::{String, ToString}; +use alloc::string::String; use libafl_bolts::{HasLen, HasRefCnt}; use num_traits::Zero; @@ -102,7 +102,7 @@ where let mut perf_score = 100.0; let q_exec_us = entry .exec_time() - .ok_or_else(|| Error::key_not_found("exec_time not set".to_string()))? + .ok_or_else(|| Error::key_not_found("exec_time not set when computing corpus power. This happens if CalibrationStage fails to set it or is not added to stages."))? .as_nanos() as f64; let avg_exec_us = psmeta.exec_time().as_nanos() as f64 / psmeta.cycles() as f64; @@ -290,7 +290,7 @@ where let q_exec_us = entry .exec_time() - .ok_or_else(|| Error::key_not_found("exec_time not set".to_string()))? + .ok_or_else(|| Error::key_not_found("exec_time not set when computing corpus weight. This happens if CalibrationStage fails to set it or is not added to stages."))? .as_nanos() as f64; let favored = entry.has_metadata::(); diff --git a/crates/libafl/src/schedulers/weighted.rs b/crates/libafl/src/schedulers/weighted.rs index b2434e54125..e49cfdc7fce 100644 --- a/crates/libafl/src/schedulers/weighted.rs +++ b/crates/libafl/src/schedulers/weighted.rs @@ -389,3 +389,62 @@ where /// The standard corpus weight, same as in `AFL++` pub type StdWeightedScheduler = WeightedScheduler; + +#[cfg(test)] +mod tests { + use core::time::Duration; + + use libafl_bolts::rands::StdRand; + + use crate::{ + corpus::{Corpus, EnableDisableCorpus, InMemoryCorpus, Testcase}, + inputs::NopInput, + observers::StdMapObserver, + schedulers::{Scheduler, StdWeightedScheduler}, + state::{HasCorpus, StdState}, + }; + + #[test] + fn test_weighted_scheduler_testcase_removal() { + #[cfg(not(feature = "serdeany_autoreg"))] + unsafe { + libafl_bolts::serdeany::RegistryBuilder::register::< + crate::schedulers::powersched::SchedulerMetadata, + >(); + libafl_bolts::serdeany::RegistryBuilder::register::(); + libafl_bolts::serdeany::RegistryBuilder::register::< + crate::corpus::SchedulerTestcaseMetadata, + >(); + } + + let mut corpus = InMemoryCorpus::new(); + let mut testcase1 = Testcase::new(NopInput {}); + testcase1.set_exec_time(Duration::from_millis(1)); // High weight + let idx1 = corpus.add(testcase1).unwrap(); + + let mut testcase2 = Testcase::new(NopInput {}); + testcase2.set_exec_time(Duration::from_millis(1000)); // Low weight + let idx2 = corpus.add(testcase2).unwrap(); + + let observer = StdMapObserver::owned("map", vec![0u8; 16]); + let mut state = StdState::new( + StdRand::with_seed(0), + corpus, + InMemoryCorpus::new(), + &mut (), + &mut (), + ) + .unwrap(); + + let mut scheduler = StdWeightedScheduler::new(&mut state, &observer); + scheduler.on_add(&mut state, idx1).unwrap(); + scheduler.on_add(&mut state, idx2).unwrap(); + + *state.corpus_mut().current_mut() = Some(idx1); + + state.corpus_mut().disable(idx1).unwrap(); + *state.corpus_mut().current_mut() = None; + + assert_eq!(scheduler.next(&mut state).unwrap(), idx2); + } +} diff --git a/crates/libafl/src/stages/calibrate.rs b/crates/libafl/src/stages/calibrate.rs index 49006ebf79c..87c1bf4d5a5 100644 --- a/crates/libafl/src/stages/calibrate.rs +++ b/crates/libafl/src/stages/calibrate.rs @@ -14,7 +14,7 @@ use serde::{Deserialize, Serialize}; use crate::{ Error, HasMetadata, HasNamedMetadata, HasScheduler, - corpus::{Corpus, HasCurrentCorpusId, SchedulerTestcaseMetadata}, + corpus::{Corpus, EnableDisableCorpus, HasCurrentCorpusId, SchedulerTestcaseMetadata}, events::{Event, EventFirer, EventWithStats, LogSeverity}, executors::{Executor, ExitKind, HasObservers}, feedbacks::{HasObserverHandle, map::MapFeedbackMetadata}, @@ -48,6 +48,11 @@ pub struct UnstableEntriesMetadata { } impl_serdeany!(UnstableEntriesMetadata); +/// Metadata to mark a testcase as disabled in the calibration stage due to crash or timeout. +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct DisabledInCalibrationStageMetadata; +impl_serdeany!(DisabledInCalibrationStageMetadata); + impl UnstableEntriesMetadata { #[must_use] /// Create a new [`struct@UnstableEntriesMetadata`] @@ -376,19 +381,34 @@ where impl Restartable for CalibrationStage where - S: HasMetadata + HasNamedMetadata + HasCurrentCorpusId, + S: HasMetadata + HasNamedMetadata + HasCurrentCorpusId + HasCorpus + HasCurrentTestcase, + S::Corpus: EnableDisableCorpus, { fn should_restart(&mut self, state: &mut S) -> Result { // Calibration stage disallow restarts // If a testcase that causes crash/timeout in the queue, we need to remove it from the queue immediately. - RetryCountRestartHelper::no_retry(state, &self.name) - - // todo - // remove this guy from corpus queue + let retry = RetryCountRestartHelper::no_retry(state, &self.name)?; + if !retry { + let id = state + .current_corpus_id()? + .ok_or_else(|| Error::illegal_state("No current corpus id"))?; + log::info!("Disabling crashing/timeouting testcase {id} during calibration"); + let insert_result = state + .current_testcase_mut()? + .try_add_metadata(DisabledInCalibrationStageMetadata); + if let Err(err) = insert_result { + log::warn!("Calibration stage called on already disabled testcase {id}: {err:?}."); + } else { + state.corpus_mut().disable(id)?; + state.clear_corpus_id()?; + self.clear_progress(state)?; + return Err(Error::skip_remaining_stages()); + } + } + Ok(retry) } fn clear_progress(&mut self, state: &mut S) -> Result<(), Error> { - // TODO: Make sure this is the correct way / there may be a better way? RetryCountRestartHelper::clear_progress(state, &self.name) } } @@ -436,3 +456,64 @@ impl Named for CalibrationStage { &self.name } } + +#[cfg(test)] +mod tests { + #[cfg(not(feature = "serdeany_autoreg"))] + use libafl_bolts::serdeany::RegistryBuilder; + use libafl_bolts::{Error, rands::StdRand}; + + #[cfg(not(feature = "serdeany_autoreg"))] + use super::DisabledInCalibrationStageMetadata; + use crate::{ + corpus::{Corpus, HasCurrentCorpusId, InMemoryCorpus, Testcase}, + feedbacks::{MaxMapFeedback, StateInitializer}, + inputs::NopInput, + observers::StdMapObserver, + stages::{CalibrationStage, Restartable}, + state::{HasCorpus, StdState}, + }; + + #[test] + fn test_calibration_restart() -> Result<(), Error> { + #[cfg(not(feature = "serdeany_autoreg"))] + // # Safety + // This is called once at the start of the test + unsafe { + RegistryBuilder::register::(); + RegistryBuilder::register::>(); + RegistryBuilder::register::(); + } + + // Setup + let mut state = StdState::new( + StdRand::with_seed(0), + InMemoryCorpus::new(), + InMemoryCorpus::new(), + &mut (), + &mut (), + )?; + + let input = NopInput {}; + let testcase = Testcase::new(input); + let id = state.corpus_mut().add(testcase)?; + state.set_corpus_id(id)?; + + let observer = StdMapObserver::owned("map", vec![0u8; 16]); + let mut feedback = MaxMapFeedback::new(&observer); + feedback.init_state(&mut state)?; + let mut stage: CalibrationStage<_, _, _, (), _> = CalibrationStage::new(&feedback); + + assert!(stage.should_restart(&mut state)?); + + match stage.should_restart(&mut state) { + Err(Error::SkipRemainingStages) => (), + res => panic!("Expected SkipRemainingStages, got {res:?}"), + } + + assert!(state.corpus().get(id).is_err()); + assert!(state.corpus().get_from_all(id).is_ok()); + + Ok(()) + } +} diff --git a/crates/libafl/src/stages/mod.rs b/crates/libafl/src/stages/mod.rs index ab23116c603..907208a7cf3 100644 --- a/crates/libafl/src/stages/mod.rs +++ b/crates/libafl/src/stages/mod.rs @@ -177,7 +177,14 @@ where let stage = &mut self.0; - stage.perform_restartable(fuzzer, executor, state, manager)?; + match stage.perform_restartable(fuzzer, executor, state, manager) { + Ok(()) => {} + Err(Error::SkipRemainingStages) => { + state.clear_stage_id()?; + return Ok(()); + } + Err(e) => return Err(e), + } state.clear_stage_id()?; } @@ -190,7 +197,14 @@ where let stage = &mut self.0; - stage.perform_restartable(fuzzer, executor, state, manager)?; + match stage.perform_restartable(fuzzer, executor, state, manager) { + Ok(()) => {} + Err(Error::SkipRemainingStages) => { + state.clear_stage_id()?; + return Ok(()); + } + Err(e) => return Err(e), + } state.clear_stage_id()?; } @@ -207,7 +221,10 @@ where } // Execute the remaining stages - self.1.perform_all(fuzzer, executor, state, manager) + match self.1.perform_all(fuzzer, executor, state, manager) { + Ok(()) | Err(Error::SkipRemainingStages) => Ok(()), + Err(e) => Err(e), + } } } @@ -290,14 +307,28 @@ where state: &mut S, manager: &mut EM, ) -> Result<(), Error> { - self.iter_mut().try_for_each(|stage| { - if state.stop_requested() { - state.discard_stop_request(); - manager.on_shutdown()?; - return Err(Error::shutting_down()); - } - stage.perform_restartable(fuzzer, executor, state, manager) - }) + self.iter_mut() + .try_for_each(|stage| { + if state.stop_requested() { + state.discard_stop_request(); + manager.on_shutdown()?; + return Err(Error::shutting_down()); + } + match stage.perform_restartable(fuzzer, executor, state, manager) { + Ok(()) => Ok(()), + Err(Error::SkipRemainingStages) => { + // Skip the remaining stages + // We return an error to stop the iterator, but we want to return Ok(()) from perform_all + + Err(Error::SkipRemainingStages) + } + Err(e) => Err(e), + } + }) + .or_else(|e| match e { + Error::SkipRemainingStages => Ok(()), + _ => Err(e), + }) } } diff --git a/crates/libafl/src/state/mod.rs b/crates/libafl/src/state/mod.rs index 28dcf97ebe4..7c183e6eaae 100644 --- a/crates/libafl/src/state/mod.rs +++ b/crates/libafl/src/state/mod.rs @@ -566,8 +566,7 @@ pub trait HasCurrentStageId { /// Trait for types which track nested stages. Stages which themselves contain stage tuples should /// ensure that they constrain the state with this trait accordingly. pub trait HasNestedStage: HasCurrentStageId { - /// Enter a stage scope, potentially resuming to an inner stage status. Returns Ok(true) if - /// resumed. + /// Enter a stage scope, potentially resuming to an inner stage status. fn enter_inner_stage(&mut self) -> Result<(), Error>; /// Exit a stage scope diff --git a/crates/libafl_core/src/lib.rs b/crates/libafl_core/src/lib.rs index f675bb36edd..2248627cbe1 100644 --- a/crates/libafl_core/src/lib.rs +++ b/crates/libafl_core/src/lib.rs @@ -159,6 +159,8 @@ pub enum Error { IllegalArgument(String, ErrorBacktrace), /// The performed action is not supported on the current platform Unsupported(String, ErrorBacktrace), + /// Raise this from a stage to skip the remaining stages for a given input, not really an error. + SkipRemainingStages, /// Shutting down, not really an error. ShuttingDown, /// OS error, wrapping a [`io::Error`] @@ -336,6 +338,12 @@ impl Error { { Error::Runtime(arg.into(), ErrorBacktrace::capture()) } + + /// Skip the remaining stages for this input + #[must_use] + pub fn skip_remaining_stages() -> Self { + Error::SkipRemainingStages + } } impl core::error::Error for Error { @@ -422,6 +430,7 @@ impl Display for Error { write!(f, "Encountered an invalid input: {0}", &s)?; display_error_backtrace(f, b) } + Self::SkipRemainingStages => write!(f, "Skip remaining stages"), } } } diff --git a/crates/libafl_frida/src/lib.rs b/crates/libafl_frida/src/lib.rs index afb436f2b37..ee8a29655ef 100644 --- a/crates/libafl_frida/src/lib.rs +++ b/crates/libafl_frida/src/lib.rs @@ -366,6 +366,7 @@ mod tests { AsSlice, SimpleStdoutLogger, cli::FuzzerOptions, rands::StdRand, tuples::tuple_list, }; use mimalloc::MiMalloc; + use serial_test::serial; use crate::{ asan::{ @@ -563,6 +564,7 @@ mod tests { } #[test] + #[serial] fn run_test_asan() { // Read RUST_LOG from the environment and set the log level accordingly (not using env_logger) // Note that in cargo test, the output of successfull tests is suppressed by default, diff --git a/crates/libafl_libfuzzer/runtime/src/corpus.rs b/crates/libafl_libfuzzer/runtime/src/corpus.rs index 6ab44143b58..ec466d1282e 100644 --- a/crates/libafl_libfuzzer/runtime/src/corpus.rs +++ b/crates/libafl_libfuzzer/runtime/src/corpus.rs @@ -140,6 +140,31 @@ where } } +impl libafl::corpus::EnableDisableCorpus for LibfuzzerCorpus +where + I: Input + Serialize + for<'de> Deserialize<'de>, +{ + fn disable(&mut self, id: CorpusId) -> Result<(), Error> { + if let Some(testcase) = self.mapping.enabled.remove(id) { + self.mapping.insert_inner_with_id(testcase, true, id) + } else { + Err(Error::key_not_found(format!( + "Index {id} not found in enabled testcases. Couldn't disable." + ))) + } + } + + fn enable(&mut self, id: CorpusId) -> Result<(), Error> { + if let Some(testcase) = self.mapping.disabled.remove(id) { + self.mapping.insert_inner_with_id(testcase, false, id) + } else { + Err(Error::key_not_found(format!( + "Index {id} not found in disabled testcases. Couldn't enable." + ))) + } + } +} + impl Corpus for LibfuzzerCorpus where I: Input + Serialize + for<'de> Deserialize<'de>, diff --git a/crates/libafl_qemu/libvharness_sys/build.rs b/crates/libafl_qemu/libvharness_sys/build.rs index bc785d11ada..64f9d59c2b1 100644 --- a/crates/libafl_qemu/libvharness_sys/build.rs +++ b/crates/libafl_qemu/libvharness_sys/build.rs @@ -7,6 +7,8 @@ const LIBVHARNESS_COMMIT: &str = "9a316966ce7aa4bd9f733491511e6ac4be6dd980"; fn main() { let runs_in_docs_rs = env::var("DOCS_RS").is_ok(); + let is_linux = env::var("CARGO_CFG_TARGET_OS").unwrap() == "linux"; + let src_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); let src_dir = PathBuf::from(src_dir).join("src"); @@ -22,7 +24,8 @@ fn main() { let gen_binding = out_dir.join("bindings.rs"); let vharness_stub = src_dir.join("stub.rs"); - if runs_in_docs_rs || cfg!(feature = "clippy") { + if runs_in_docs_rs || cfg!(feature = "clippy") || !is_linux { + println!("cargo:warning=libvharness_sys only builds for Linux targets"); fs::copy(vharness_stub, gen_binding).unwrap(); } else { println!("cargo:rerun-if-env-changed=LIBVHARNESS_GEN_STUBS"); diff --git a/crates/libafl_targets/src/sancov_pcguard.rs b/crates/libafl_targets/src/sancov_pcguard.rs index 23884d44e10..341c341702c 100644 --- a/crates/libafl_targets/src/sancov_pcguard.rs +++ b/crates/libafl_targets/src/sancov_pcguard.rs @@ -30,7 +30,7 @@ use crate::coverage::MAX_EDGES_FOUND; use crate::{EDGES_MAP_ALLOCATED_SIZE, coverage::EDGES_MAP_PTR}; #[cfg(all(feature = "sancov_pcguard_edges", feature = "sancov_pcguard_hitcounts"))] -#[cfg(not(any(doc, feature = "clippy")))] +#[cfg(not(any(doc, feature = "clippy", test)))] compile_error!( "the libafl_targets `sancov_pcguard_edges` and `sancov_pcguard_hitcounts` features are mutually exclusive." ); @@ -220,13 +220,13 @@ pub unsafe extern "C" fn __sanitizer_cov_trace_pc_guard(guard: *mut u32) { #[cfg(any(feature = "sancov_ngram4", feature = "sancov_ngram8"))] { pos = update_ngram(pos); - // println!("Wrinting to {} {}", pos, EDGES_MAP_DEFAULT_SIZE); + // println!("Writing to {} {}", pos, EDGES_MAP_DEFAULT_SIZE); } #[cfg(feature = "sancov_ctx")] { pos ^= __afl_prev_ctx as usize; - // println!("Wrinting to {} {}", pos, EDGES_MAP_DEFAULT_SIZE); + // println!("Writing to {} {}", pos, EDGES_MAP_DEFAULT_SIZE); } #[cfg(feature = "pointer_maps")] diff --git a/crates/libafl_tinyinst/src/executor.rs b/crates/libafl_tinyinst/src/executor.rs index e509addc707..1e34ac371d5 100644 --- a/crates/libafl_tinyinst/src/executor.rs +++ b/crates/libafl_tinyinst/src/executor.rs @@ -93,7 +93,7 @@ where RunResult::OTHER_ERROR => Err(Error::unknown( "Tinyinst RunResult is other error".to_string(), )), - _ => Err(Error::unknown("Tinyinst RunResult is unknown".to_string())), + _ => Err(Error::unknown("Tinyinst RunResult is unknown")), } } } diff --git a/fuzzers/forkserver/libafl-fuzz/Cargo.lock b/fuzzers/forkserver/libafl-fuzz/Cargo.lock index fc3ca185e5c..a8bc4fdcfaf 100644 --- a/fuzzers/forkserver/libafl-fuzz/Cargo.lock +++ b/fuzzers/forkserver/libafl-fuzz/Cargo.lock @@ -176,7 +176,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.110", + "syn 2.0.111", ] [[package]] @@ -188,7 +188,7 @@ dependencies = [ "arbitrary-int 1.3.0", "proc-macro2", "quote", - "syn 2.0.110", + "syn 2.0.111", ] [[package]] @@ -244,16 +244,16 @@ dependencies = [ "quote", "serde", "serde_json", - "syn 2.0.110", + "syn 2.0.111", "tempfile", "toml", ] [[package]] name = "cc" -version = "1.2.45" +version = "1.2.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35900b6c8d709fb1d854671ae27aeaa9eec2f8b01b364e1619a40da3e6fe2afe" +checksum = "cd405d82c84ff7f35739f175f67d8b9fb7687a0e84ccdc78bd3568839827cf07" dependencies = [ "find-msvc-tools", "jobserver", @@ -295,9 +295,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.51" +version = "4.5.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c26d721170e0295f191a69bd9a1f93efcdb0aff38684b61ab5750468972e5f5" +checksum = "c9e340e012a1bf4935f5282ed1436d1489548e8f72308207ea5df0e23d2d03f8" dependencies = [ "clap_builder", "clap_derive", @@ -305,9 +305,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.51" +version = "4.5.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75835f0c7bf681bfd05abe44e965760fea999a5286c6eb2d59883634fd02011a" +checksum = "d76b5d13eaa18c901fd2f7fca939fefe3a0727a953561fefdf3b2922b8569d00" dependencies = [ "anstream", "anstyle", @@ -325,7 +325,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.110", + "syn 2.0.111", ] [[package]] @@ -407,9 +407,9 @@ dependencies = [ [[package]] name = "ctor" -version = "0.4.3" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec09e802f5081de6157da9a75701d6c713d8dc3ba52571fd4bd25f412644e8a6" +checksum = "3ffc71fcdcdb40d6f087edddf7f8f1f8f79e6cf922f555a9ee8779752d4819bd" dependencies = [ "ctor-proc-macro", "dtor", @@ -417,9 +417,9 @@ dependencies = [ [[package]] name = "ctor-proc-macro" -version = "0.0.6" +version = "0.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2931af7e13dc045d8e9d26afccc6fa115d64e115c9c84b1166288b46f6782c2" +checksum = "52560adf09603e58c9a7ee1fe1dcb95a16927b17c127f0ac02d6e768a0e25bc1" [[package]] name = "derivative" @@ -446,18 +446,18 @@ checksum = "780955b8b195a21ab8e4ac6b60dd1dbdcec1dc6c51c0617964b08c81785e12c9" [[package]] name = "dtor" -version = "0.0.6" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97cbdf2ad6846025e8e25df05171abfb30e3ababa12ee0a0e44b9bbe570633a8" +checksum = "404d02eeb088a82cfd873006cb713fe411306c7d182c344905e101fb1167d301" dependencies = [ "dtor-proc-macro", ] [[package]] name = "dtor-proc-macro" -version = "0.0.5" +version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7454e41ff9012c00d53cf7f475c5e3afa3b91b7c90568495495e8d9bf47a1055" +checksum = "f678cf4a922c215c63e0de95eb1ff08a958a81d47e485cf9da1e27bf6305cfa5" [[package]] name = "either" @@ -569,9 +569,9 @@ checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "find-msvc-tools" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127" +checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" [[package]] name = "foldhash" @@ -636,14 +636,15 @@ checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" [[package]] name = "hashbrown" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" dependencies = [ "allocator-api2", "equivalent", "foldhash", "serde", + "serde_core", ] [[package]] @@ -721,7 +722,7 @@ checksum = "980af8b43c3ad5d8d349ace167ec8170839f753a42d233ba19e08afe1850fa69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.110", + "syn 2.0.111", ] [[package]] @@ -827,7 +828,7 @@ dependencies = [ "libc", "ll_mp", "log", - "mach2 0.5.0", + "mach2", "minibsod", "miniz_oxide", "nix 0.30.1", @@ -870,7 +871,7 @@ version = "0.16.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.110", + "syn 2.0.111", ] [[package]] @@ -1020,21 +1021,9 @@ checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" [[package]] name = "mach2" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d640282b302c0bb0a2a8e0233ead9035e3bed871f0b7e81fe4a1ec829765db44" -dependencies = [ - "libc", -] - -[[package]] -name = "mach2" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a1b95cd5421ec55b445b5ae102f5ea0e768de1f82bd3001e11f426c269c3aea" -dependencies = [ - "libc", -] +checksum = "dae608c151f68243f2b000364e1f7b186d9c29845f7d2d85bd31b9ad77ad552b" [[package]] name = "memchr" @@ -1085,7 +1074,7 @@ version = "0.16.0" dependencies = [ "exceptional", "libc", - "mach2 0.4.3", + "mach2", "rustversion", "windows", ] @@ -1175,7 +1164,7 @@ checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.110", + "syn 2.0.111", ] [[package]] @@ -1280,7 +1269,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.110", + "syn 2.0.111", ] [[package]] @@ -1368,9 +1357,9 @@ dependencies = [ [[package]] name = "rangemap" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93e7e49bb0bf967717f7bd674458b3d6b0c5f48ec7e3038166026a69fc22223" +checksum = "acbbbbea733ec66275512d0b9694f34102e7d5406fdbe2ad8d21b28dce92887c" [[package]] name = "redox_syscall" @@ -1554,7 +1543,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.110", + "syn 2.0.111", ] [[package]] @@ -1600,7 +1589,7 @@ checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.110", + "syn 2.0.111", ] [[package]] @@ -1769,9 +1758,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.110" +version = "2.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b280aea" +checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" dependencies = [ "proc-macro2", "quote", @@ -1818,7 +1807,7 @@ checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", - "syn 2.0.110", + "syn 2.0.111", ] [[package]] @@ -1929,22 +1918,22 @@ dependencies = [ [[package]] name = "typed-builder" -version = "0.22.0" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "398a3a3c918c96de527dc11e6e846cd549d4508030b8a33e1da12789c856b81a" +checksum = "31aa81521b70f94402501d848ccc0ecaa8f93c8eb6999eb9747e72287757ffda" dependencies = [ "typed-builder-macro", ] [[package]] name = "typed-builder-macro" -version = "0.22.0" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e48cea23f68d1f78eb7bc092881b6bb88d3d6b5b7e6234f6f9c911da1ffb221" +checksum = "076a02dc54dd46795c2e9c8282ed40bcfb1e22747e955de9389a1de28190fb26" dependencies = [ "proc-macro2", "quote", - "syn 2.0.110", + "syn 2.0.111", ] [[package]] @@ -2072,7 +2061,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.110", + "syn 2.0.111", "wasm-bindgen-shared", ] @@ -2087,9 +2076,9 @@ dependencies = [ [[package]] name = "wide" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7966aa4bc1b7ead85802bd41dc4f35e2ef69bc23b6d3c73d3d5df5e643384012" +checksum = "13ca908d26e4786149c48efcf6c0ea09ab0e06d1fe3c17dc1b4b0f1ca4a7e788" dependencies = [ "bytemuck", "safe_arch", @@ -2170,7 +2159,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.110", + "syn 2.0.111", ] [[package]] @@ -2181,7 +2170,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.110", + "syn 2.0.111", ] [[package]] @@ -2427,5 +2416,5 @@ checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" dependencies = [ "proc-macro2", "quote", - "syn 2.0.110", + "syn 2.0.111", ] diff --git a/fuzzers/forkserver/libafl-fuzz/src/scheduler.rs b/fuzzers/forkserver/libafl-fuzz/src/scheduler.rs index bb84de69372..3066e8c68e3 100644 --- a/fuzzers/forkserver/libafl-fuzz/src/scheduler.rs +++ b/fuzzers/forkserver/libafl-fuzz/src/scheduler.rs @@ -18,7 +18,6 @@ impl RemovableScheduler for SupportedSchedulers where Q: Scheduler + RemovableScheduler, W: Scheduler + RemovableScheduler, - S: HasTestcase, { fn on_remove( &mut self,