use anyhow::Result;
use clap::Parser;
#[macro_use]
mod templates;
mod options;
mod project;
mod rustc_version;
mod utils;
static FUZZ_TARGETS_DIR_OLD: &str = "fuzzers";
static FUZZ_TARGETS_DIR: &str = "fuzz_targets";
const LONG_ABOUT_TEMPLATE: &str = "\
{bin} {version}
{about}
USAGE:
{usage}
{before-help}
{all-args}
{after-help}";
const RUN_BEFORE_HELP: &str = "\
The fuzz target name is the same as the name of the fuzz target script in
fuzz/fuzz_targets/, i.e. the name picked when running `cargo fuzz add`.
This will run the script inside the fuzz target with varying inputs until it
finds a crash, at which point it will save the crash input to the artifact
directory, print some output, and exit. Unless you configure it otherwise (see
libFuzzer options below), this will run indefinitely.
By default fuzz targets are built with optimizations equivalent to
`cargo build --release`, but with debug assertions and overflow checks enabled.
Address Sanitizer is also enabled by default.";
const RUN_AFTER_HELP: &str = "\
A full list of libFuzzer options can be found at
http://llvm.org/docs/LibFuzzer.html#options
You can also get this by running `cargo fuzz run fuzz_target -- -help=1`
Some useful options (to be used as `cargo fuzz run fuzz_target -- <options>`)
include:
* `-max_len=<len>`: Will limit the length of the input string to `<len>`
* `-runs=<number>`: Will limit the number of tries (runs) before it gives up
* `-max_total_time=<time>`: Will limit the amount of time (seconds) to
fuzz before it gives up
* `-timeout=<time>`: Will limit the amount of time (seconds) for a single
run before it considers that run a failure
* `-only_ascii`: Only provide ASCII input
* `-dict=<file>`: Use a keyword dictionary from specified file. See
http://llvm.org/docs/LibFuzzer.html#dictionaries\
";
const BUILD_BEFORE_HELP: &str = "\
By default fuzz targets are built with optimizations equivalent to
`cargo build --release`, but with debug assertions and overflow checks enabled.
Address Sanitizer is also enabled by default.";
const BUILD_AFTER_HELP: &str = "\
Sanitizers perform checks necessary for detecting bugs in unsafe code
at the cost of some performance. For more information on sanitizers see
https://doc.rust-lang.org/unstable-book/compiler-flags/sanitizer.html\
";
trait RunCommand {
fn run_command(&mut self) -> Result<()>;
}
#[derive(Clone, Debug, Parser)]
#[command(version, about)]
#[command(subcommand_required = true)]
#[command(arg_required_else_help = true)]
#[command(propagate_version = true)]
#[command(
arg(clap::Arg::new("dummy")
.value_parser(["fuzz"])
.required(false)
.hide(true))
)]
enum Command {
Init(options::Init),
Add(options::Add),
#[command(
help_template(LONG_ABOUT_TEMPLATE),
before_help(BUILD_BEFORE_HELP),
after_help(BUILD_AFTER_HELP),
visible_alias("b")
)]
Build(options::Build),
#[command(help_template(LONG_ABOUT_TEMPLATE), visible_alias("c"))]
Check(options::Check),
Fmt(options::Fmt),
#[command(visible_alias("ls"))]
List(options::List),
#[command(
help_template(LONG_ABOUT_TEMPLATE),
before_help(RUN_BEFORE_HELP),
after_help(RUN_AFTER_HELP),
visible_alias("r")
)]
Run(options::Run),
Cmin(options::Cmin),
Tmin(options::Tmin),
#[command(visible_alias("cov"))]
Coverage(options::Coverage),
}
impl RunCommand for Command {
fn run_command(&mut self) -> Result<()> {
match self {
Command::Init(x) => x.run_command(),
Command::Add(x) => x.run_command(),
Command::Build(x) => x.run_command(),
Command::Check(x) => x.run_command(),
Command::List(x) => x.run_command(),
Command::Fmt(x) => x.run_command(),
Command::Run(x) => x.run_command(),
Command::Cmin(x) => x.run_command(),
Command::Tmin(x) => x.run_command(),
Command::Coverage(x) => x.run_command(),
}
}
}
fn main() -> Result<()> {
Command::parse().run_command()
}