From e0fbb0ca0c1192542e1c07a84f35a7dd4800a557 Mon Sep 17 00:00:00 2001 From: Samuel Moelius Date: Thu, 11 Jul 2024 04:52:53 -0400 Subject: [PATCH] Display AFL++ version and whether plugins are in use --- cargo-afl/Cargo.toml | 2 +- cargo-afl/src/main.rs | 45 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/cargo-afl/Cargo.toml b/cargo-afl/Cargo.toml index 5735db609..ad4ef4804 100644 --- a/cargo-afl/Cargo.toml +++ b/cargo-afl/Cargo.toml @@ -23,7 +23,7 @@ tempfile = "3.10" xdg = "2.5" [dependencies] -clap = { version = "4.5", features = ["cargo", "derive"] } +clap = { version = "4.5", features = ["cargo", "derive", "string"] } fs_extra = "1.3" home = "0.5" libc = "0.2" diff --git a/cargo-afl/src/main.rs b/cargo-afl/src/main.rs index 7cac84e8e..b1e9bc082 100644 --- a/cargo-afl/src/main.rs +++ b/cargo-afl/src/main.rs @@ -1,4 +1,4 @@ -use clap::{crate_version, Parser}; +use clap::{crate_version, CommandFactory, FromArgMatches, Parser}; use std::collections::HashMap; use std::env; use std::ffi::{OsStr, OsString}; @@ -115,7 +115,9 @@ declare_afl_subcommand_enum! { } fn main() { - let afl_args = match Args::parse() { + let command = command_with_afl_version(); + + let afl_args = match Args::from_arg_matches(&command.get_matches()).unwrap() { Args { subcmd: CargoSubcommand::Afl(afl_args), } => afl_args, @@ -175,6 +177,42 @@ fn main() { } } +fn command_with_afl_version() -> clap::Command { + let mut command = Args::command(); + + (|| -> Option<()> { + let afl_version = afl_version()?; + let with_plugins = common::plugins_available().ok()?; + + let subcmd = command.find_subcommand_mut("afl").unwrap(); + let ver = format!( + "{} (AFL++ version {}{})", + subcmd.get_version().unwrap(), + afl_version, + if with_plugins { " with plugins" } else { "" } + ); + *subcmd = subcmd.clone().version(ver); + Some(()) + })() + .unwrap_or_default(); + + command +} + +fn afl_version() -> Option { + const PREFIX: &str = "afl-fuzz++"; + let afl_fuzz_path = common::afl_dir().unwrap().join("bin/afl-fuzz"); + let output = Command::new(afl_fuzz_path).output().ok()?; + let stdout = String::from_utf8(output.stdout).ok()?; + let index = stdout.find(PREFIX)?; + Some( + stdout[index + PREFIX.len()..] + .chars() + .take_while(|c| !c.is_ascii_whitespace()) + .collect(), + ) +} + fn run_afl(tool: &str, args: I) where I: IntoIterator, @@ -334,13 +372,12 @@ fn is_nightly() -> bool { mod tests { use super::*; use assert_cmd::Command; - use clap::CommandFactory; use std::os::unix::ffi::OsStringExt; use std::process::Output; #[test] fn test_app() { - Args::command().debug_assert(); + command_with_afl_version().debug_assert(); } #[test]