From c89b6cceff8fb93e7187ea6e899f1ee3979a01ba Mon Sep 17 00:00:00 2001 From: mephi42 Date: Fri, 22 Oct 2021 03:44:56 +0200 Subject: [PATCH] Support AFL++ coverage maps AFL++ generates coverage maps with different sizes. --- util/symcc_fuzzing_helper/src/main.rs | 2 +- util/symcc_fuzzing_helper/src/symcc.rs | 44 ++++++++++++++++---------- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/util/symcc_fuzzing_helper/src/main.rs b/util/symcc_fuzzing_helper/src/main.rs index 378e79d1..9af01363 100644 --- a/util/symcc_fuzzing_helper/src/main.rs +++ b/util/symcc_fuzzing_helper/src/main.rs @@ -353,7 +353,7 @@ fn process_new_testcase( ) })? { AflShowmapResult::Success(testcase_bitmap) => { - let interesting = state.current_bitmap.merge(&testcase_bitmap); + let interesting = state.current_bitmap.merge(*testcase_bitmap)?; if interesting { symcc::copy_testcase(&testcase, &mut state.queue, parent).with_context(|| { format!( diff --git a/util/symcc_fuzzing_helper/src/symcc.rs b/util/symcc_fuzzing_helper/src/symcc.rs index 69066039..745ce9e7 100644 --- a/util/symcc_fuzzing_helper/src/symcc.rs +++ b/util/symcc_fuzzing_helper/src/symcc.rs @@ -42,13 +42,13 @@ fn insert_input_file, P: AsRef>( /// A coverage map as used by AFL. pub struct AflMap { - data: [u8; 65536], + data: Option>, } impl AflMap { /// Create an empty map. pub fn new() -> AflMap { - AflMap { data: [0; 65536] } + AflMap { data: None } } /// Load a map from disk. @@ -60,31 +60,41 @@ impl AflMap { path.as_ref().display() ) })?; + Ok(AflMap { data: Some(data) }) + } + + /// Merge two coverage maps in place. + fn merge_vec(data: &mut Vec, new_data: Vec) -> Result { + let mut interesting = false; ensure!( - data.len() == 65536, - "The file to load the coverage map from has the wrong size ({})", - data.len() + data.len() == new_data.len(), + "Coverage maps must have the same size ({} and {})", + data.len(), + new_data.len(), ); - - let mut result = AflMap::new(); - result.data.copy_from_slice(&data); - Ok(result) + for (known, new) in data.iter_mut().zip(new_data.iter()) { + if *known != (*known | new) { + *known |= new; + interesting = true; + } + } + Ok(interesting) } /// Merge with another coverage map in place. /// /// Return true if the map has changed, i.e., if the other map yielded new /// coverage. - pub fn merge(&mut self, other: &AflMap) -> bool { - let mut interesting = false; - for (known, new) in self.data.iter_mut().zip(other.data.iter()) { - if *known != (*known | new) { - *known |= new; - interesting = true; + pub fn merge(&mut self, other: AflMap) -> Result { + match (&mut self.data, other.data) { + (Some(data), Some(new_data)) => AflMap::merge_vec(data, new_data), + (Some(_), None) => Ok(false), + (None, Some(new_data)) => { + self.data = Some(new_data); + Ok(true) } + (None, None) => Ok(false), } - - interesting } }