Skip to content

Commit 0250384

Browse files
authored
Don't confuse corpus and solutions (#3397)
* don't confuse corpus and solutions * fix import * fix test * ver
1 parent acadc8e commit 0250384

File tree

6 files changed

+133
-154
lines changed

6 files changed

+133
-154
lines changed

crates/libafl/src/fuzzer/mod.rs

Lines changed: 114 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ pub trait Evaluator<E, EM, I, S> {
217217
executor: &mut E,
218218
manager: &mut EM,
219219
input: I,
220-
) -> Result<(CorpusId, ExecuteInputResult), Error>;
220+
) -> Result<CorpusId, Error>;
221221

222222
/// Adds the input to the corpus as a disabled input.
223223
/// Used during initial corpus loading.
@@ -273,45 +273,15 @@ pub trait Fuzzer<E, EM, I, S, ST> {
273273
iters: u64,
274274
) -> Result<CorpusId, Error>;
275275
}
276-
277-
/// The corpus this input should be added to
278-
#[derive(Debug, PartialEq, Eq, Default)]
279-
pub struct ExecuteInputResult {
280-
is_corpus: bool,
281-
is_solution: bool,
282-
}
283-
284-
impl ExecuteInputResult {
285-
/// Constructor
286-
#[must_use]
287-
pub fn new(is_corpus: bool, is_solution: bool) -> Self {
288-
Self {
289-
is_corpus,
290-
is_solution,
291-
}
292-
}
293-
294-
/// if this is corpus worthy
295-
#[must_use]
296-
pub fn is_corpus(&self) -> bool {
297-
self.is_corpus
298-
}
299-
300-
/// if this is solution worthy
301-
#[must_use]
302-
pub fn is_solution(&self) -> bool {
303-
self.is_solution
304-
}
305-
306-
/// tell that this is corpus
307-
pub fn set_is_corpus(&mut self, v: bool) {
308-
self.is_corpus = v;
309-
}
310-
311-
/// tell that this is solution
312-
pub fn set_is_solution(&mut self, v: bool) {
313-
self.is_solution = v;
314-
}
276+
/// The result of harness execution
277+
#[derive(Debug, PartialEq, Eq)]
278+
pub enum ExecuteInputResult {
279+
/// No special input
280+
None,
281+
/// This input should be stored in the corpus
282+
Corpus,
283+
/// This input leads to a solution
284+
Solution,
315285
}
316286

317287
/// Your default fuzzer instance, for everyday use.
@@ -403,7 +373,7 @@ where
403373
observers: &OT,
404374
exit_kind: &ExitKind,
405375
) -> Result<ExecuteInputResult, Error> {
406-
let mut res = ExecuteInputResult::default();
376+
let mut res = ExecuteInputResult::None;
407377

408378
#[cfg(not(feature = "introspection"))]
409379
let is_solution = self
@@ -416,22 +386,21 @@ where
416386
.is_interesting_introspection(state, manager, input, observers, exit_kind)?;
417387

418388
if is_solution {
419-
res.set_is_solution(true);
420-
}
421-
422-
#[cfg(not(feature = "introspection"))]
423-
let corpus_worthy = self
424-
.feedback_mut()
425-
.is_interesting(state, manager, input, observers, exit_kind)?;
426-
#[cfg(feature = "introspection")]
427-
let corpus_worthy = self
428-
.feedback_mut()
429-
.is_interesting_introspection(state, manager, input, observers, exit_kind)?;
430-
431-
if corpus_worthy {
432-
res.set_is_corpus(true);
389+
res = ExecuteInputResult::Solution;
390+
} else {
391+
#[cfg(not(feature = "introspection"))]
392+
let corpus_worthy = self
393+
.feedback_mut()
394+
.is_interesting(state, manager, input, observers, exit_kind)?;
395+
#[cfg(feature = "introspection")]
396+
let corpus_worthy = self
397+
.feedback_mut()
398+
.is_interesting_introspection(state, manager, input, observers, exit_kind)?;
399+
400+
if corpus_worthy {
401+
res = ExecuteInputResult::Corpus;
402+
}
433403
}
434-
435404
Ok(res)
436405
}
437406

@@ -444,42 +413,42 @@ where
444413
manager: &mut EM,
445414
input: &I,
446415
exec_res: &ExecuteInputResult,
447-
exit_kind: &ExitKind,
416+
_exit_kind: &ExitKind,
448417
observers: &OT,
449418
) -> Result<Option<CorpusId>, Error> {
450-
let corpus = if exec_res.is_corpus() {
451-
// Add the input to the main corpus
452-
let mut testcase = Testcase::from(input.clone());
453-
testcase.set_executions(*state.executions());
454-
#[cfg(feature = "track_hit_feedbacks")]
455-
self.feedback_mut()
456-
.append_hit_feedbacks(testcase.hit_feedbacks_mut())?;
457-
self.feedback_mut()
458-
.append_metadata(state, manager, observers, &mut testcase)?;
459-
let id = state.corpus_mut().add(testcase)?;
460-
self.scheduler_mut().on_add(state, id)?;
461-
Ok(Some(id))
462-
} else {
463-
Ok(None)
464-
};
465-
466-
if exec_res.is_solution() {
467-
// The input is a solution, add it to the respective corpus
468-
let mut testcase = Testcase::from(input.clone());
469-
testcase.set_executions(*state.executions());
470-
testcase.add_metadata(*exit_kind);
471-
testcase.set_parent_id_optional(*state.corpus().current());
472-
if let Ok(mut tc) = state.current_testcase_mut() {
473-
tc.found_objective();
419+
match exec_res {
420+
ExecuteInputResult::None => Ok(None),
421+
ExecuteInputResult::Corpus => {
422+
// Not a solution
423+
// Add the input to the main corpus
424+
let mut testcase = Testcase::from(input.clone());
425+
#[cfg(feature = "track_hit_feedbacks")]
426+
self.feedback_mut()
427+
.append_hit_feedbacks(testcase.hit_feedbacks_mut())?;
428+
self.feedback_mut()
429+
.append_metadata(state, manager, observers, &mut testcase)?;
430+
let id = state.corpus_mut().add(testcase)?;
431+
self.scheduler_mut().on_add(state, id)?;
432+
433+
Ok(Some(id))
434+
}
435+
ExecuteInputResult::Solution => {
436+
// The input is a solution, add it to the respective corpus
437+
let mut testcase = Testcase::from(input.clone());
438+
testcase.set_parent_id_optional(*state.corpus().current());
439+
if let Ok(mut tc) = state.current_testcase_mut() {
440+
tc.found_objective();
441+
}
442+
#[cfg(feature = "track_hit_feedbacks")]
443+
self.objective_mut()
444+
.append_hit_feedbacks(testcase.hit_objectives_mut())?;
445+
self.objective_mut()
446+
.append_metadata(state, manager, observers, &mut testcase)?;
447+
state.solutions_mut().add(testcase)?;
448+
449+
Ok(None)
474450
}
475-
#[cfg(feature = "track_hit_feedbacks")]
476-
self.objective_mut()
477-
.append_hit_feedbacks(testcase.hit_objectives_mut())?;
478-
self.objective_mut()
479-
.append_metadata(state, manager, observers, &mut testcase)?;
480-
state.solutions_mut().add(testcase)?;
481451
}
482-
corpus
483452
}
484453

485454
fn serialize_and_dispatch(
@@ -492,14 +461,20 @@ where
492461
exit_kind: &ExitKind,
493462
) -> Result<(), Error> {
494463
// Now send off the event
495-
let observers_buf = if exec_res.is_corpus()
496-
&& manager.should_send()
497-
&& manager.configuration() != EventConfig::AlwaysUnique
498-
{
499-
// TODO set None for fast targets
500-
Some(postcard::to_allocvec(observers)?)
501-
} else {
502-
None
464+
let observers_buf = match exec_res {
465+
ExecuteInputResult::Corpus => {
466+
if manager.should_send() {
467+
// TODO set None for fast targets
468+
if manager.configuration() == EventConfig::AlwaysUnique {
469+
None
470+
} else {
471+
Some(postcard::to_allocvec(observers)?)
472+
}
473+
} else {
474+
None
475+
}
476+
}
477+
_ => None,
503478
};
504479

505480
self.dispatch_event(state, manager, input, exec_res, observers_buf, exit_kind)?;
@@ -516,38 +491,42 @@ where
516491
exit_kind: &ExitKind,
517492
) -> Result<(), Error> {
518493
// Now send off the event
519-
if manager.should_send() {
520-
if exec_res.is_corpus() {
521-
manager.fire(
522-
state,
523-
EventWithStats::with_current_time(
524-
Event::NewTestcase {
525-
input: input.clone(),
526-
observers_buf,
527-
exit_kind: *exit_kind,
528-
corpus_size: state.corpus().count(),
529-
client_config: manager.configuration(),
530-
forward_id: None,
531-
#[cfg(all(unix, feature = "std", feature = "multi_machine"))]
532-
node_id: None,
533-
},
534-
*state.executions(),
535-
),
536-
)?;
494+
match exec_res {
495+
ExecuteInputResult::Corpus => {
496+
if manager.should_send() {
497+
manager.fire(
498+
state,
499+
EventWithStats::with_current_time(
500+
Event::NewTestcase {
501+
input: input.clone(),
502+
observers_buf,
503+
exit_kind: *exit_kind,
504+
corpus_size: state.corpus().count(),
505+
client_config: manager.configuration(),
506+
forward_id: None,
507+
#[cfg(all(unix, feature = "std", feature = "multi_machine"))]
508+
node_id: None,
509+
},
510+
*state.executions(),
511+
),
512+
)?;
513+
}
537514
}
538-
539-
if exec_res.is_solution() {
540-
manager.fire(
541-
state,
542-
EventWithStats::with_current_time(
543-
Event::Objective {
544-
input: self.share_objectives.then_some(input.clone()),
545-
objective_size: state.solutions().count(),
546-
},
547-
*state.executions(),
548-
),
549-
)?;
515+
ExecuteInputResult::Solution => {
516+
if manager.should_send() {
517+
manager.fire(
518+
state,
519+
EventWithStats::with_current_time(
520+
Event::Objective {
521+
input: self.share_objectives.then_some(input.clone()),
522+
objective_size: state.solutions().count(),
523+
},
524+
*state.executions(),
525+
),
526+
)?;
527+
}
550528
}
529+
ExecuteInputResult::None => (),
551530
}
552531

553532
Ok(())
@@ -568,7 +547,7 @@ where
568547
if send_events {
569548
self.serialize_and_dispatch(state, manager, input, &exec_res, observers, exit_kind)?;
570549
}
571-
if exec_res.is_corpus() || exec_res.is_solution() {
550+
if exec_res != ExecuteInputResult::None {
572551
*state.last_found_time_mut() = current_time();
573552
}
574553
Ok((exec_res, corpus_id))
@@ -687,7 +666,7 @@ where
687666
if self.input_filter.should_execute(input) {
688667
self.evaluate_input(state, executor, manager, input)
689668
} else {
690-
Ok((ExecuteInputResult::default(), None))
669+
Ok((ExecuteInputResult::None, None))
691670
}
692671
}
693672

@@ -712,7 +691,7 @@ where
712691
executor: &mut E,
713692
manager: &mut EM,
714693
input: I,
715-
) -> Result<(CorpusId, ExecuteInputResult), Error> {
694+
) -> Result<CorpusId, Error> {
716695
*state.last_found_time_mut() = current_time();
717696

718697
let exit_kind = self.execute_input(state, executor, manager, &input)?;
@@ -743,7 +722,7 @@ where
743722
self.objective_mut()
744723
.append_metadata(state, manager, &*observers, &mut testcase)?;
745724
// we don't care about solution id
746-
let _ = state.solutions_mut().add(testcase.clone())?;
725+
let id = state.solutions_mut().add(testcase)?;
747726

748727
manager.fire(
749728
state,
@@ -755,17 +734,19 @@ where
755734
*state.executions(),
756735
),
757736
)?;
737+
738+
return Ok(id);
758739
}
759740

760741
// several is_interesting implementations collect some data about the run, later used in
761742
// append_metadata; we *must* invoke is_interesting here to collect it
762743
#[cfg(not(feature = "introspection"))]
763-
let corpus_worthy =
744+
let _corpus_worthy =
764745
self.feedback_mut()
765746
.is_interesting(state, manager, &input, &*observers, &exit_kind)?;
766747

767748
#[cfg(feature = "introspection")]
768-
let corpus_worthy = self.feedback_mut().is_interesting_introspection(
749+
let _corpus_worthy = self.feedback_mut().is_interesting_introspection(
769750
state,
770751
manager,
771752
&input,
@@ -803,7 +784,7 @@ where
803784
*state.executions(),
804785
),
805786
)?;
806-
Ok((id, ExecuteInputResult::new(corpus_worthy, is_solution)))
787+
Ok(id)
807788
}
808789

809790
fn add_disabled_input(&mut self, state: &mut S, input: I) -> Result<CorpusId, Error> {

crates/libafl/src/inputs/encoded.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -320,9 +320,9 @@ mod tests {
320320
fn test_targetbytes_fuzzer_builds() {
321321
const TRUE_VAL: bool = true;
322322

323-
let observer = ValueObserver::new("test_value", OwnedRef::Ref(&TRUE_VAL));
324-
let mut true_feedback = BoolValueFeedback::new(&observer.handle());
325-
let mut true_objective = BoolValueFeedback::new(&observer.handle());
323+
let true_observer = ValueObserver::new("test_value", OwnedRef::Ref(&TRUE_VAL));
324+
let mut feedback = BoolValueFeedback::new(&true_observer.handle());
325+
let mut objective = tuple_list!();
326326

327327
let (bytes_converter, input) = setup_encoder_decoder();
328328
let input_clone = input.clone();
@@ -332,8 +332,8 @@ mod tests {
332332
StdRand::new(),
333333
InMemoryCorpus::new(),
334334
InMemoryCorpus::new(),
335-
&mut true_feedback,
336-
&mut true_objective,
335+
&mut feedback,
336+
&mut objective,
337337
)
338338
.unwrap();
339339

@@ -345,13 +345,13 @@ mod tests {
345345
let mut fuzzer = StdFuzzer::builder()
346346
.target_bytes_converter(bytes_converter)
347347
.scheduler(QueueScheduler::new())
348-
.feedback(true_feedback)
349-
.objective(true_objective)
348+
.feedback(feedback)
349+
.objective(objective)
350350
.build();
351351

352352
let mut executor = InProcessExecutor::new(
353353
&mut harness_fn,
354-
tuple_list!(observer),
354+
tuple_list!(true_observer),
355355
&mut fuzzer,
356356
&mut state,
357357
&mut event_mgr,

0 commit comments

Comments
 (0)