The Fuzzing Book 之 樣本突變Fuzzing(二)

class ProgramCoverage:
??def __init__(self, source_path: str) -> None:
????self._coverage = set()
????self.reports = []
????self.rest(source_path)
??def rest(self, source_path):
????self.source_path = source_path
????self._sources = []
????for filepath, dirnames, filenames in os.walk(source_path):
??????for filename in filenames:
????????if filename.endswith('.c'):
??????????fullname = os.path.join(filepath, filename)
??????????self._sources.append(fullname)
??def sources(self) -> List:
????return self._sources
??def trace(self):
????old_work_dir = os.getcwd()
????os.chdir(self.source_path)
????for source in self._sources:
??????gcov_come = subprocess.run(
????????["gcov", source],
????????stdin=subprocess.PIPE,
????????stderr=subprocess.PIPE,
????????stdout=subprocess.PIPE,
????????universal_newlines=True
??????)
??????if gcov_come.stdout != '':
????????self.reports.append((source, gcov_come.stdout))
????????gcov_file = source + ".gcov"
????????with open(gcov_file, 'r') as f:
??????????for line in f.readlines():
????????????if line.startswith('??#####:?'):
??????????????self._coverage.add((source, int(line.strip('??#####:?').split(':')[0])))
????os.chdir(old_work_dir)
??def coverage(self) -> any:
????return self._coverage
??def __repr__(self):
????out = ""
????for report in self.reports:
??????source, gcov_info = report
??????out += source + "\n"
??????out += gcov_info
??????out += '#' * 60 + '\n'
????return out
class ProgramCoverageRunner(ProgramRunner):
??def __init__(self, program: str, sources_path):
????self.program = program
????self.sources_path = sources_path
????basename = "input.txt"
????tmpdir = tempfile.mkdtemp()
????self.input_file = os.path.join(tmpdir, basename)
??def run_process(self, inp) -> subprocess.CompletedProcess:
????print(inp)
????with open(self.input_file, 'w') as f:
??????f.write(inp + '\n')
????result = subprocess.run(
??????[self.program, self.input_file],
??????stdin=subprocess.PIPE,
??????stdout=subprocess.PIPE,
??????stderr=subprocess.PIPE,
??????universal_newlines=True
????)
????cov = ProgramCoverage(self.sources_path)
????cov.trace()
????self._coverage = cov.coverage()
????return result
??def coverage(self):
????return self._coverage