diff --git a/src/options/init.rs b/src/options/init.rs index 565ac53..ae86c6b 100644 --- a/src/options/init.rs +++ b/src/options/init.rs @@ -12,6 +12,10 @@ pub struct Init { /// Whether to create a separate workspace for fuzz targets crate pub fuzzing_workspace: Option, + #[arg(long, value_parser = clap::builder::BoolishValueParser::new(), default_value = "false")] + /// Whether to use libafl's libfuzzer_sys-compatible API for improved fuzzing performance + pub use_libafl: Option, + #[command(flatten)] pub fuzz_dir_wrapper: FuzzDirWrapper, } diff --git a/src/project.rs b/src/project.rs index ed8c5c7..6b53823 100644 --- a/src/project.rs +++ b/src/project.rs @@ -70,6 +70,7 @@ impl FuzzProject { .write_fmt(toml_template!( manifest.crate_name, manifest.edition, + init.use_libafl, init.fuzzing_workspace )) .with_context(|| format!("failed to write to {}", cargo_toml.display()))?; @@ -353,7 +354,7 @@ impl FuzzProject { // Use the user-provided target directory, if provided. Otherwise if building for coverage, // use the coverage directory if let Some(target_dir) = build.target_dir.as_ref() { - return Ok(Some(PathBuf::from(target_dir))); + Ok(Some(PathBuf::from(target_dir))) } else if build.coverage { // To ensure that fuzzing and coverage-output generation can run in parallel, we // produce a separate binary for the coverage command. @@ -387,7 +388,7 @@ impl FuzzProject { cmd.arg("--bins"); } - if let Some(target_dir) = self.target_dir(&build)? { + if let Some(target_dir) = self.target_dir(build)? { cmd.arg("--target-dir").arg(target_dir); } @@ -756,7 +757,7 @@ impl FuzzProject { for corpus in corpora.iter() { // _tmp_dir is deleted when it goes of of scope. let (mut cmd, _tmp_dir) = - self.create_coverage_cmd(coverage, &coverage_out_raw_dir, &corpus.as_path())?; + self.create_coverage_cmd(coverage, &coverage_out_raw_dir, corpus.as_path())?; eprintln!("Generating coverage data for corpus {:?}", corpus); let status = cmd .status() diff --git a/src/rustc_version.rs b/src/rustc_version.rs index c92863d..d688672 100644 --- a/src/rustc_version.rs +++ b/src/rustc_version.rs @@ -22,7 +22,7 @@ fn rust_version_string() -> anyhow::Result { String::from_utf8(raw_output).context("`rustc --version` returned non-text output somehow") } -#[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd)] +#[derive(Debug, Copy, Clone, Eq, PartialEq)] pub struct RustVersion { pub major: u32, pub minor: u32, @@ -39,6 +39,12 @@ impl Ord for RustVersion { } } +impl PartialOrd for RustVersion { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + impl RustVersion { pub fn discover() -> anyhow::Result { let version_string = rust_version_string()?; diff --git a/src/templates.rs b/src/templates.rs index 5f09e33..0f1b6e9 100644 --- a/src/templates.rs +++ b/src/templates.rs @@ -1,5 +1,5 @@ macro_rules! toml_template { - ($name:expr, $edition:expr, $fuzzing_workspace:expr) => { + ($name:expr, $edition:expr, $use_libafl:expr, $fuzzing_workspace:expr) => { format_args!( r##"[package] name = "{name}-fuzz" @@ -10,7 +10,7 @@ publish = false cargo-fuzz = true [dependencies] -libfuzzer-sys = "0.4" +{libfuzzer_sys_dep} [dependencies.{name}] path = ".." @@ -21,6 +21,11 @@ path = ".." } else { String::new() }, + libfuzzer_sys_dep = if let Some(true) = $use_libafl { + r##"libfuzzer-sys = { version = "0.15.3", package = "libafl_libfuzzer" }"## + } else { + r##"libfuzzer-sys = "0.4""## + }, workspace = if let Some(true) = $fuzzing_workspace { r##" # Use independent workspace for fuzzers diff --git a/tests/tests/main.rs b/tests/tests/main.rs index 1b98bad..e501183 100644 --- a/tests/tests/main.rs +++ b/tests/tests/main.rs @@ -159,6 +159,22 @@ fn init_defines_correct_dependency() { let expected_dependency_attrs = &format!("[dependencies.{name}]\npath = \"..\"", name = project_name); assert!(cargo_toml.contains(expected_dependency_attrs)); + assert!(cargo_toml.contains(r#"libfuzzer-sys = "0.4""#)) +} + +#[test] +fn init_with_libafl() { + let project = project("init_with_libafl").build(); + project + .cargo_fuzz() + .arg("init") + .arg("--use-libafl=true") + .assert() + .success(); + + let cargo_toml = fs::read_to_string(project.fuzz_cargo_toml()).unwrap(); + assert!(cargo_toml + .contains(r#"libfuzzer-sys = { version = "0.15.3", package = "libafl_libfuzzer" }"#)); } #[test]