Fire events in append_metadata not in is_interesting (#1936)
* stuff * ok * Recalc filled slightly differently... (#1939) * Recalc filled slightly differently... * Make requested changes as per PR review * unused * fix --------- Co-authored-by: Dan Blackwell <danblackwell95@yahoo.co.uk>
This commit is contained in:
parent
b3ddab3bce
commit
ee6385c25b
@ -62,9 +62,10 @@ where
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn append_metadata<OT>(
|
||||
fn append_metadata<EM, OT>(
|
||||
&mut self,
|
||||
_state: &mut S,
|
||||
_manager: &mut EM,
|
||||
_observers: &OT,
|
||||
testcase: &mut Testcase<PacketData>,
|
||||
) -> Result<(), Error> {
|
||||
|
@ -455,7 +455,7 @@ pub fn run_observers_and_save_state<E, EM, OF, Z>(
|
||||
new_testcase.set_parent_id_optional(*state.corpus().current());
|
||||
fuzzer
|
||||
.objective_mut()
|
||||
.append_metadata(state, observers, &mut new_testcase)
|
||||
.append_metadata(state, event_mgr, observers, &mut new_testcase)
|
||||
.expect("Failed adding metadata");
|
||||
state
|
||||
.solutions_mut()
|
||||
|
@ -67,14 +67,16 @@ where
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
fn append_metadata<OT>(
|
||||
fn append_metadata<EM, OT>(
|
||||
&mut self,
|
||||
_state: &mut S,
|
||||
_manager: &mut EM,
|
||||
observers: &OT,
|
||||
testcase: &mut Testcase<S::Input>,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
OT: ObserversTuple<S>,
|
||||
EM: EventFirer<State = S>,
|
||||
{
|
||||
if let Some(metadata) = observers
|
||||
.match_name::<ConcolicObserver>(&self.name)
|
||||
|
@ -318,6 +318,8 @@ where
|
||||
{
|
||||
/// Contains information about untouched entries
|
||||
pub history_map: Vec<T>,
|
||||
/// Tells us how many non-initial entries there are in `history_map`
|
||||
pub num_covered_map_indexes: usize,
|
||||
}
|
||||
|
||||
libafl_bolts::impl_serdeany!(
|
||||
@ -327,21 +329,29 @@ libafl_bolts::impl_serdeany!(
|
||||
|
||||
impl<T> MapFeedbackMetadata<T>
|
||||
where
|
||||
T: Default + Copy + 'static + Serialize + DeserializeOwned,
|
||||
T: Default + Copy + 'static + Serialize + DeserializeOwned + PartialEq,
|
||||
{
|
||||
/// Create new `MapFeedbackMetadata`
|
||||
#[must_use]
|
||||
pub fn new(map_size: usize) -> Self {
|
||||
Self {
|
||||
history_map: vec![T::default(); map_size],
|
||||
num_covered_map_indexes: 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create new `MapFeedbackMetadata` using a name and a map.
|
||||
/// The map can be shared.
|
||||
/// `initial_elem_value` is used to calculate `Self.num_covered_map_indexes`
|
||||
#[must_use]
|
||||
pub fn with_history_map(history_map: Vec<T>) -> Self {
|
||||
Self { history_map }
|
||||
pub fn with_history_map(history_map: Vec<T>, initial_elem_value: T) -> Self {
|
||||
let num_covered_map_indexes = history_map
|
||||
.iter()
|
||||
.fold(0, |acc, x| acc + usize::from(*x != initial_elem_value));
|
||||
Self {
|
||||
history_map,
|
||||
num_covered_map_indexes,
|
||||
}
|
||||
}
|
||||
|
||||
/// Reset the map
|
||||
@ -350,6 +360,7 @@ where
|
||||
for i in 0..cnt {
|
||||
self.history_map[i] = T::default();
|
||||
}
|
||||
self.num_covered_map_indexes = 0;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -359,6 +370,9 @@ where
|
||||
for i in 0..cnt {
|
||||
self.history_map[i] = value;
|
||||
}
|
||||
// assume that resetting the map should indicate no coverage,
|
||||
// regardless of value
|
||||
self.num_covered_map_indexes = 0;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@ -366,8 +380,6 @@ where
|
||||
/// The most common AFL-like feedback type
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MapFeedback<N, O, R, S, T> {
|
||||
/// For tracking, always keep indexes and/or novelties, even if the map isn't considered `interesting`.
|
||||
always_track: bool,
|
||||
/// Indexes used in the last observation
|
||||
indexes: bool,
|
||||
/// New indexes observed in the last observation
|
||||
@ -418,7 +430,7 @@ where
|
||||
EM: EventFirer<State = S>,
|
||||
OT: ObserversTuple<S>,
|
||||
{
|
||||
self.is_interesting_default(state, manager, input, observers, exit_kind)
|
||||
Ok(self.is_interesting_default(state, manager, input, observers, exit_kind))
|
||||
}
|
||||
|
||||
#[rustversion::not(nightly)]
|
||||
@ -434,17 +446,19 @@ where
|
||||
EM: EventFirer<State = S>,
|
||||
OT: ObserversTuple<S>,
|
||||
{
|
||||
self.is_interesting_default(state, manager, input, observers, exit_kind)
|
||||
Ok(self.is_interesting_default(state, manager, input, observers, exit_kind))
|
||||
}
|
||||
|
||||
fn append_metadata<OT>(
|
||||
fn append_metadata<EM, OT>(
|
||||
&mut self,
|
||||
state: &mut S,
|
||||
manager: &mut EM,
|
||||
observers: &OT,
|
||||
testcase: &mut Testcase<S::Input>,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
OT: ObserversTuple<S>,
|
||||
EM: EventFirer<State = S>,
|
||||
{
|
||||
if let Some(novelties) = self.novelties.as_mut().map(core::mem::take) {
|
||||
let meta = MapNoveltiesMetadata::new(novelties);
|
||||
@ -471,6 +485,9 @@ where
|
||||
.enumerate()
|
||||
.filter(|(_, value)| *value != initial)
|
||||
{
|
||||
if history_map[i] == initial {
|
||||
map_state.num_covered_map_indexes += 1;
|
||||
}
|
||||
history_map[i] = R::reduce(history_map[i], value);
|
||||
indices.push(i);
|
||||
}
|
||||
@ -483,9 +500,43 @@ where
|
||||
.enumerate()
|
||||
.filter(|(_, value)| *value != initial)
|
||||
{
|
||||
if history_map[i] == initial {
|
||||
map_state.num_covered_map_indexes += 1;
|
||||
}
|
||||
history_map[i] = R::reduce(history_map[i], value);
|
||||
}
|
||||
}
|
||||
|
||||
debug_assert!(
|
||||
history_map
|
||||
.iter()
|
||||
.fold(0, |acc, x| acc + usize::from(*x != initial))
|
||||
== map_state.num_covered_map_indexes,
|
||||
"history_map had {} filled, but map_state.num_covered_map_indexes was {}",
|
||||
history_map
|
||||
.iter()
|
||||
.fold(0, |acc, x| acc + usize::from(*x != initial)),
|
||||
map_state.num_covered_map_indexes,
|
||||
);
|
||||
|
||||
// at this point you are executing this code, the testcase is always interesting
|
||||
let covered = map_state.num_covered_map_indexes;
|
||||
let len = history_map.len();
|
||||
// opt: if not tracking optimisations, we technically don't show the *current* history
|
||||
// map but the *last* history map; this is better than walking over and allocating
|
||||
// unnecessarily
|
||||
manager.fire(
|
||||
state,
|
||||
Event::UpdateUserStats {
|
||||
name: self.stats_name.to_string(),
|
||||
value: UserStats::new(
|
||||
UserStatsValue::Ratio(covered as u64, len as u64),
|
||||
AggregatorOps::Avg,
|
||||
),
|
||||
phantom: PhantomData,
|
||||
},
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@ -503,7 +554,7 @@ where
|
||||
fn is_interesting<EM, OT>(
|
||||
&mut self,
|
||||
state: &mut S,
|
||||
manager: &mut EM,
|
||||
_manager: &mut EM,
|
||||
_input: &S::Input,
|
||||
observers: &OT,
|
||||
_exit_kind: &ExitKind,
|
||||
@ -604,32 +655,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
let initial = observer.initial();
|
||||
if interesting {
|
||||
let len = history_map.len();
|
||||
let filled = history_map.iter().filter(|&&i| i != initial).count();
|
||||
// opt: if not tracking optimisations, we technically don't show the *current* history
|
||||
// map but the *last* history map; this is better than walking over and allocating
|
||||
// unnecessarily
|
||||
manager.fire(
|
||||
state,
|
||||
Event::UpdateUserStats {
|
||||
name: self.stats_name.to_string(),
|
||||
value: UserStats::new(
|
||||
UserStatsValue::Ratio(
|
||||
self.novelties
|
||||
.as_ref()
|
||||
.map_or(filled, |novelties| filled + novelties.len())
|
||||
as u64,
|
||||
len as u64,
|
||||
),
|
||||
AggregatorOps::Avg,
|
||||
),
|
||||
phantom: PhantomData,
|
||||
},
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(interesting)
|
||||
}
|
||||
}
|
||||
@ -678,7 +703,6 @@ where
|
||||
name: MAPFEEDBACK_PREFIX.to_string() + map_observer.name(),
|
||||
observer_name: map_observer.name().to_string(),
|
||||
stats_name: create_stats_name(map_observer.name()),
|
||||
always_track: false,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
@ -692,7 +716,6 @@ where
|
||||
name: MAPFEEDBACK_PREFIX.to_string() + map_observer.name(),
|
||||
observer_name: map_observer.name().to_string(),
|
||||
stats_name: create_stats_name(map_observer.name()),
|
||||
always_track: false,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
@ -707,17 +730,9 @@ where
|
||||
observer_name: observer_name.to_string(),
|
||||
stats_name: create_stats_name(name),
|
||||
phantom: PhantomData,
|
||||
always_track: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// For tracking, enable `always_track` mode, that also adds `novelties` or `indexes`,
|
||||
/// even if the map is not novel for this feedback.
|
||||
/// This is useful in combination with `load_initial_inputs_forced`, or other feedbacks.
|
||||
pub fn set_always_track(&mut self, always_track: bool) {
|
||||
self.always_track = always_track;
|
||||
}
|
||||
|
||||
/// Creating a new `MapFeedback` with a specific name. This is usefully whenever the same
|
||||
/// feedback is needed twice, but with a different history. Using `new()` always results in the
|
||||
/// same name and therefore also the same history.
|
||||
@ -729,7 +744,6 @@ where
|
||||
name: name.to_string(),
|
||||
observer_name: map_observer.name().to_string(),
|
||||
stats_name: create_stats_name(name),
|
||||
always_track: false,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
@ -748,7 +762,6 @@ where
|
||||
observer_name: observer_name.to_string(),
|
||||
stats_name: create_stats_name(name),
|
||||
name: name.to_string(),
|
||||
always_track: false,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
@ -759,11 +772,11 @@ where
|
||||
fn is_interesting_default<EM, OT>(
|
||||
&mut self,
|
||||
state: &mut S,
|
||||
manager: &mut EM,
|
||||
_manager: &mut EM,
|
||||
_input: &S::Input,
|
||||
observers: &OT,
|
||||
_exit_kind: &ExitKind,
|
||||
) -> Result<bool, Error>
|
||||
) -> bool
|
||||
where
|
||||
EM: EventFirer<State = S>,
|
||||
OT: ObserversTuple<S>,
|
||||
@ -816,32 +829,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
if interesting || self.always_track {
|
||||
let len = history_map.len();
|
||||
let filled = history_map.iter().filter(|&&i| i != initial).count();
|
||||
// opt: if not tracking optimisations, we technically don't show the *current* history
|
||||
// map but the *last* history map; this is better than walking over and allocating
|
||||
// unnecessarily
|
||||
manager.fire(
|
||||
state,
|
||||
Event::UpdateUserStats {
|
||||
name: self.stats_name.to_string(),
|
||||
value: UserStats::new(
|
||||
UserStatsValue::Ratio(
|
||||
self.novelties
|
||||
.as_ref()
|
||||
.map_or(filled, |novelties| filled + novelties.len())
|
||||
as u64,
|
||||
len as u64,
|
||||
),
|
||||
AggregatorOps::Avg,
|
||||
),
|
||||
phantom: PhantomData,
|
||||
},
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(interesting)
|
||||
interesting
|
||||
}
|
||||
}
|
||||
|
||||
@ -915,9 +903,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn append_metadata<OT>(
|
||||
fn append_metadata<EM, OT>(
|
||||
&mut self,
|
||||
_state: &mut S,
|
||||
_manager: &mut EM,
|
||||
_observers: &OT,
|
||||
testcase: &mut Testcase<S::Input>,
|
||||
) -> Result<(), Error>
|
||||
|
@ -109,14 +109,16 @@ where
|
||||
/// Append to the testcase the generated metadata in case of a new corpus item
|
||||
#[inline]
|
||||
#[allow(unused_variables)]
|
||||
fn append_metadata<OT>(
|
||||
fn append_metadata<EM, OT>(
|
||||
&mut self,
|
||||
state: &mut S,
|
||||
manager: &mut EM,
|
||||
observers: &OT,
|
||||
testcase: &mut Testcase<S::Input>,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
OT: ObserversTuple<S>,
|
||||
EM: EventFirer<State = S>,
|
||||
{
|
||||
Ok(())
|
||||
}
|
||||
@ -245,17 +247,21 @@ where
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn append_metadata<OT>(
|
||||
fn append_metadata<EM, OT>(
|
||||
&mut self,
|
||||
state: &mut S,
|
||||
manager: &mut EM,
|
||||
observers: &OT,
|
||||
testcase: &mut Testcase<S::Input>,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
OT: ObserversTuple<S>,
|
||||
EM: EventFirer<State = S>,
|
||||
{
|
||||
self.first.append_metadata(state, observers, testcase)?;
|
||||
self.second.append_metadata(state, observers, testcase)
|
||||
self.first
|
||||
.append_metadata(state, manager, observers, testcase)?;
|
||||
self.second
|
||||
.append_metadata(state, manager, observers, testcase)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -659,16 +665,19 @@ where
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn append_metadata<OT>(
|
||||
fn append_metadata<EM, OT>(
|
||||
&mut self,
|
||||
state: &mut S,
|
||||
manager: &mut EM,
|
||||
observers: &OT,
|
||||
testcase: &mut Testcase<S::Input>,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
OT: ObserversTuple<S>,
|
||||
EM: EventFirer<State = S>,
|
||||
{
|
||||
self.first.append_metadata(state, observers, testcase)
|
||||
self.first
|
||||
.append_metadata(state, manager, observers, testcase)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -915,14 +924,16 @@ where
|
||||
|
||||
/// Append to the testcase the generated metadata in case of a new corpus item
|
||||
#[inline]
|
||||
fn append_metadata<OT>(
|
||||
fn append_metadata<EM, OT>(
|
||||
&mut self,
|
||||
_state: &mut S,
|
||||
_manager: &mut EM,
|
||||
observers: &OT,
|
||||
testcase: &mut Testcase<S::Input>,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
OT: ObserversTuple<S>,
|
||||
EM: EventFirer<State = S>,
|
||||
{
|
||||
let observer = observers.match_name::<TimeObserver>(self.name()).unwrap();
|
||||
*testcase.exec_time_mut() = *observer.last_runtime();
|
||||
@ -1212,9 +1223,10 @@ pub mod pybind {
|
||||
})?)
|
||||
}
|
||||
|
||||
fn append_metadata<OT>(
|
||||
fn append_metadata<EM, OT>(
|
||||
&mut self,
|
||||
state: &mut PythonStdState,
|
||||
_manager: &mut EM,
|
||||
observers: &OT,
|
||||
testcase: &mut Testcase<BytesInput>,
|
||||
) -> Result<(), Error>
|
||||
@ -1655,17 +1667,19 @@ pub mod pybind {
|
||||
})
|
||||
}
|
||||
|
||||
fn append_metadata<OT>(
|
||||
fn append_metadata<EM, OT>(
|
||||
&mut self,
|
||||
state: &mut PythonStdState,
|
||||
manager: &mut EM,
|
||||
observers: &OT,
|
||||
testcase: &mut Testcase<BytesInput>,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
OT: ObserversTuple<PythonStdState>,
|
||||
EM: EventFirer<State = PythonStdState>,
|
||||
{
|
||||
unwrap_me_mut!(self.wrapper, f, {
|
||||
f.append_metadata(state, observers, testcase)
|
||||
f.append_metadata(state, manager, observers, testcase)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -99,9 +99,10 @@ where
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
fn append_metadata<OT>(
|
||||
fn append_metadata<EM, OT>(
|
||||
&mut self,
|
||||
state: &mut S,
|
||||
_manager: &mut EM,
|
||||
_observers: &OT,
|
||||
testcase: &mut Testcase<S::Input>,
|
||||
) -> Result<(), Error>
|
||||
|
@ -381,7 +381,7 @@ where
|
||||
// Add the input to the main corpus
|
||||
let mut testcase = Testcase::with_executions(input.clone(), *state.executions());
|
||||
self.feedback_mut()
|
||||
.append_metadata(state, observers, &mut testcase)?;
|
||||
.append_metadata(state, manager, observers, &mut testcase)?;
|
||||
let idx = state.corpus_mut().add(testcase)?;
|
||||
self.scheduler_mut().on_add(state, idx)?;
|
||||
|
||||
@ -419,7 +419,7 @@ where
|
||||
let mut testcase = Testcase::with_executions(input, *state.executions());
|
||||
testcase.set_parent_id_optional(*state.corpus().current());
|
||||
self.objective_mut()
|
||||
.append_metadata(state, observers, &mut testcase)?;
|
||||
.append_metadata(state, manager, observers, &mut testcase)?;
|
||||
state.solutions_mut().add(testcase)?;
|
||||
|
||||
if send_events {
|
||||
@ -517,7 +517,7 @@ where
|
||||
|
||||
if is_solution {
|
||||
self.objective_mut()
|
||||
.append_metadata(state, observers, &mut testcase)?;
|
||||
.append_metadata(state, manager, observers, &mut testcase)?;
|
||||
let idx = state.solutions_mut().add(testcase)?;
|
||||
|
||||
manager.fire(
|
||||
@ -546,7 +546,7 @@ where
|
||||
|
||||
// Add the input to the main corpus
|
||||
self.feedback_mut()
|
||||
.append_metadata(state, observers, &mut testcase)?;
|
||||
.append_metadata(state, manager, observers, &mut testcase)?;
|
||||
let idx = state.corpus_mut().add(testcase)?;
|
||||
self.scheduler_mut().on_add(state, idx)?;
|
||||
|
||||
|
@ -166,7 +166,7 @@ where
|
||||
let mut testcase = Testcase::with_executions(base, *state.executions());
|
||||
fuzzer
|
||||
.feedback_mut()
|
||||
.append_metadata(state, observers, &mut testcase)?;
|
||||
.append_metadata(state, manager, observers, &mut testcase)?;
|
||||
let prev = state.corpus_mut().replace(base_corpus_idx, testcase)?;
|
||||
fuzzer
|
||||
.scheduler_mut()
|
||||
|
@ -651,9 +651,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn append_metadata<OT>(
|
||||
fn append_metadata<EM, OT>(
|
||||
&mut self,
|
||||
_state: &mut S,
|
||||
_manager: &mut EM,
|
||||
_observers: &OT,
|
||||
testcase: &mut Testcase<S::Input>,
|
||||
) -> Result<(), Error>
|
||||
|
@ -131,9 +131,10 @@ where
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
fn append_metadata<OT>(
|
||||
fn append_metadata<EM, OT>(
|
||||
&mut self,
|
||||
_state: &mut S,
|
||||
_manager: &mut EM,
|
||||
_observers: &OT,
|
||||
testcase: &mut Testcase<S::Input>,
|
||||
) -> Result<(), Error>
|
||||
|
Loading…
x
Reference in New Issue
Block a user