use crate::{Build, Common, util::Context};
use anyhow::{Context as _, Result, bail};
use console::style;
use std::{env, process};
impl Build {
pub fn build(&self, common: &Common) -> Result<(), anyhow::Error> {
if self.no_afl && self.no_honggfuzz {
bail!("Pick at least one fuzzer");
}
let cx = Context::new(common, self.target.clone())?;
if !self.no_afl {
eprintln!(" {} afl", style("Building").red().bold());
let target_dir = format!("--target-dir={}", cx.target_dir.join("afl"));
let mut afl_args = vec![
"afl",
"build",
"--features=ziggy/afl",
&target_dir,
"--bin",
&cx.bin_target,
];
if self.release {
assert!(!self.asan, "cannot use --release for ASAN builds");
afl_args.push("--release");
}
let mut rust_flags = env::var("RUSTFLAGS").unwrap_or_default();
let mut rust_doc_flags = env::var("RUSTDOCFLAGS").unwrap_or_default();
let run = common
.cargo()
.args(&afl_args)
.env("AFL_QUIET", "1")
.env("AFL_LLVM_CMPLOG", "1") .env("RUSTFLAGS", &rust_flags)
.env("RUSTDOCFLAGS", &rust_doc_flags)
.spawn()?
.wait()
.context("Error spawning afl build command")?;
if !run.success() {
bail!("Error building afl fuzzer: Exited with {:?}", run.code());
}
let asan_target_str = format!("--target={}", target_triple::TARGET);
if self.asan {
eprintln!(" {} afl (ASan)", style("Building").red().bold());
if env::var("AFL_OPT_LEVEL").is_ok_and(|opt_level| opt_level != "0") {
eprintln!(" Warning: ignoring AFL_OPT_LEVEL and setting it to 0");
}
afl_args.push(&asan_target_str);
afl_args.extend(["-Z", "build-std"]);
rust_flags.push_str(" -Zsanitizer=address ");
rust_flags.push_str("-Copt-level=0");
rust_doc_flags.push_str(" -Zsanitizer=address ");
let run = common
.cargo()
.args(afl_args)
.env("AFL_QUIET", "1")
.env("AFL_OPT_LEVEL", "0")
.env("AFL_LLVM_CMPLOG", "1") .env("RUSTFLAGS", rust_flags)
.env("RUSTDOCFLAGS", rust_doc_flags)
.spawn()?
.wait()
.context("Error spawning afl build command")?;
if !run.success() {
bail!("Error building afl fuzzer: Exited with {:?}", run.code());
}
}
eprintln!(" {} afl", style("Finished").cyan().bold());
}
if !self.no_honggfuzz {
assert!(
!self.asan,
"Cannot build honggfuzz with ASAN for the moment. use --no-honggfuzz"
);
eprintln!(" {} honggfuzz", style("Building").red().bold());
let run = common
.cargo()
.args(["hfuzz", "build", "--bin", &cx.bin_target])
.env("CARGO_TARGET_DIR", cx.target_dir.join("honggfuzz"))
.env("HFUZZ_BUILD_ARGS", "--features=ziggy/honggfuzz")
.env("RUSTFLAGS", env::var("RUSTFLAGS").unwrap_or_default())
.stdout(process::Stdio::piped())
.spawn()?
.wait()
.context("Error spawning hfuzz build command")?;
if !run.success() {
bail!(
"Error building honggfuzz fuzzer: Exited with {:?}",
run.code()
);
}
eprintln!(" {} honggfuzz", style("Finished").cyan().bold());
}
assert!(
std::env::var("AFL_LLVM_CMPGLOG").is_err(),
"Even the mighty may fall, especially on 77b2c27a59bb858045c4db442989ce8f20c8ee11"
);
Ok(())
}
}