def get_file_features(self, input_file_path, showmap_args): """Get the features (edge hit counts) of |input_file_path| using afl-showmap.""" # TODO(metzman): Figure out if we should worry about CPU affinity errors # here. showmap_result = self.run_and_wait( additional_args=showmap_args, input_data=engine_common.read_data_from_file(input_file_path), # TODO(metzman): Set a more reasonable per-file timeout. This is a must # to make timeouts smarter for afl-fuzz. timeout=self.merge_timeout) self.merge_timeout -= showmap_result.time_executed # TODO(metzman): Figure out why negative values are accepted by # self.run_and_wait. if showmap_result.timed_out or self.merge_timeout <= 0: return None, True showmap_output = engine_common.read_data_from_file( self.showmap_output_path) # Log an error if showmap didn't write any coverage. if showmap_output is None: if not self.showmap_no_output_logged: self.showmap_no_output_logged = True logs.log_error( ('afl-showmap didn\'t output any coverage. Command: {0}\n' 'Return code: {1}\n' 'Time executed: {2}\n' 'Output: {3}').format(showmap_result.command, showmap_result.return_code, showmap_result.time_executed, showmap_result.output)) return None, True features = set() for match in re.finditer(self.SHOWMAP_REGEX, showmap_output): d = match.groupdict() features.add((int(d['guard']), int(d['hit_count']))) return frozenset(features), False
def set_afl_stats(self): """Read statistics from afl-fuzz's "fuzzer_stats" file and save them as self.afl_stats. """ # fuzzer_stats will not exist if there was a crashing input in the corpus or # if afl was unable to fuzz for some other reason. if not os.path.exists(self.afl_stats_path): return afl_stats_string = engine_common.read_data_from_file(self.afl_stats_path) matches_iterator = re.finditer(self.STATS_REGEX, afl_stats_string) self.afl_stats = dict(match.groups() for match in matches_iterator)