Skip to content

Commit 212a0c4

Browse files
committed
infra: Report dry run seed crashes
1 parent 1eb2e62 commit 212a0c4

1 file changed

Lines changed: 60 additions & 10 deletions

File tree

infra/ensemble-fuzz/src/fuzzer/aflpp.rs

Lines changed: 60 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,51 @@ impl AflppFuzzer {
4747
pull_corpus: PathBuf::new(),
4848
}
4949
}
50+
51+
fn fuzzer_stats_path(&self) -> PathBuf {
52+
self.out_dir.join(self.id.to_string()).join("fuzzer_stats")
53+
}
54+
55+
fn queue_dir(&self) -> PathBuf {
56+
self.out_dir.join(self.id.to_string()).join("queue")
57+
}
58+
59+
fn stderr_log_path(&self) -> PathBuf {
60+
self.workspace.join(format!("aflpp_instance_{}.log", self.id))
61+
}
62+
63+
fn queue_seed_count(&self) -> Option<u64> {
64+
let seed_count = std::fs::read_dir(self.queue_dir())
65+
.ok()?
66+
.filter_map(Result::ok)
67+
.filter(|entry| entry.path().is_file())
68+
.count() as u64;
69+
70+
(seed_count > 0).then_some(seed_count)
71+
}
72+
73+
fn dry_run_crash_seed_count(&self) -> Option<u64> {
74+
if self.fuzzer_stats_path().exists() {
75+
return None;
76+
}
77+
78+
let log = std::fs::read_to_string(self.stderr_log_path()).ok()?;
79+
if !log.contains("We need at least one valid input seed that does not crash") {
80+
return None;
81+
}
82+
83+
self.queue_seed_count()
84+
}
85+
86+
fn maybe_cleanup_stderr_log(&self) {
87+
if std::env::var("FUZZOR_AFL_DEBUG").is_ok() {
88+
return;
89+
}
90+
91+
if self.fuzzer_stats_path().exists() {
92+
let _ = std::fs::remove_file(self.stderr_log_path());
93+
}
94+
}
5095
}
5196

5297
#[async_trait]
@@ -62,9 +107,9 @@ impl Fuzzer for AflppFuzzer {
62107
async fn get_stats(&self) -> FuzzerStats {
63108
let mut stats = FuzzerStats::default();
64109

65-
if let Ok(stat_file) =
66-
std::fs::read_to_string(self.out_dir.join(self.id.to_string()).join("fuzzer_stats"))
67-
{
110+
if let Ok(stat_file) = std::fs::read_to_string(self.fuzzer_stats_path()) {
111+
self.maybe_cleanup_stderr_log();
112+
68113
let mut afl_fuzzer_stats = HashMap::new();
69114
stat_file
70115
.lines()
@@ -107,14 +152,18 @@ impl Fuzzer for AflppFuzzer {
107152
.unwrap_or(0.0),
108153
);
109154
}
155+
} else if let Some(seed_count) = self.dry_run_crash_seed_count() {
156+
// Report dry run seed crashes as solution candidates.
157+
stats.corpus_count = seed_count;
158+
stats.saved_crashes = seed_count;
110159
}
111160

112161
stats
113162
}
114163

115164
fn get_push_corpus(&self) -> Option<PathBuf> {
116165
if self.id == 0 {
117-
Some(self.out_dir.join(self.id.to_string()).join("queue"))
166+
Some(self.queue_dir())
118167
} else {
119168
None
120169
}
@@ -135,6 +184,9 @@ impl Fuzzer for AflppFuzzer {
135184
if !ignore_hangs {
136185
solution_dirs.push(self.out_dir.join(self.id.to_string()).join("hangs"));
137186
}
187+
if self.dry_run_crash_seed_count().is_some() {
188+
solution_dirs.push(self.queue_dir());
189+
}
138190
solution_dirs
139191
}
140192

@@ -199,14 +251,12 @@ impl Fuzzer for AflppFuzzer {
199251
command.envs(&self.env);
200252

201253
command.stdout(Stdio::null());
254+
let log_path = self.stderr_log_path();
255+
let log_file = std::fs::File::create(&log_path).expect("Could not create AFL++ log file");
202256
if std::env::var("FUZZOR_AFL_DEBUG").is_ok() {
203-
let log_path = self.workspace.join(format!("aflpp_instance_{}.log", self.id));
204-
let log_file =
205-
std::fs::File::create(&log_path).expect("Could not create AFL++ log file");
206-
command.stderr(Stdio::from(log_file));
207-
} else {
208-
command.stderr(Stdio::null());
257+
log::info!("AFL++ instance {} stderr is logged to {:?}", self.id, log_path);
209258
}
259+
command.stderr(Stdio::from(log_file));
210260

211261
let host_env: HashMap<String, String> = std::env::vars().collect();
212262
command.envs(host_env);

0 commit comments

Comments
 (0)