Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,7 @@ target/
# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb

core
core

# Profiler files generated during coverage
*.profraw
64 changes: 32 additions & 32 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ cli = [
"cargo_metadata",
"twox-hash",
]
coverage = ["fork", "libc"]
coverage = []

[dependencies]
afl = { version = "0.17.0", default-features = false, optional = true }
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ ziggy = { version = "1.4.0", default-features = false }

Then use the `fuzz!` macro inside your `main` to create a harness.

```rust
```rust ignore
fn main() {
ziggy::fuzz!(|data: &[u8]| {
println!("{data:?}");
Expand Down
32 changes: 20 additions & 12 deletions src/bin/cargo-ziggy/coverage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,12 @@ impl Cover {
Cover::clean_old_cov()?;
}

let mut shared_corpus = PathBuf::new();

shared_corpus.push(
let input_path = PathBuf::from(
self.input
.display()
.to_string()
.replace("{ziggy_output}", &self.ziggy_output.display().to_string())
.replace("{target_name}", &self.target)
.as_str(),
.replace("{target_name}", &self.target),
);

// Get the absolute path for the coverage directory to ensure .profraw files
Expand All @@ -49,13 +46,24 @@ impl Cover {
.join("target/coverage/debug/deps");
let profile_file = coverage_target_dir.join("coverage-%p-%m.profraw");

let _ = process::Command::new(format!("./target/coverage/debug/{}", &self.target))
.arg(format!("{}", shared_corpus.display()))
.env("LLVM_PROFILE_FILE", profile_file.display().to_string())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
let coverage_corpus = match input_path.is_dir() {
true => fs::read_dir(input_path)
.unwrap()
.flatten()
.map(|e| e.path())
.collect(),
false => vec![input_path],
};

for file in coverage_corpus {
let _ = process::Command::new(format!("./target/coverage/debug/{}", &self.target))
.arg(file.display().to_string())
.env("LLVM_PROFILE_FILE", profile_file.display().to_string())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
}

let source_or_workspace_root = match &self.source {
Some(s) => s.display().to_string(),
Expand Down
8 changes: 4 additions & 4 deletions src/bin/cargo-ziggy/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,10 +200,6 @@ pub struct Run {
#[clap(value_name = "TARGET", default_value = DEFAULT_UNMODIFIED_TARGET)]
target: String,

/// Maximum length of input
#[clap(short = 'G', long = "maxlength", default_value_t = 1048576)]
max_length: u64,

/// Input directories and/or files to run
#[clap(short, long, value_name = "DIR", default_value = DEFAULT_CORPUS_DIR)]
inputs: Vec<PathBuf>,
Expand All @@ -225,6 +221,10 @@ pub struct Run {
/// Activate these features on the target
#[clap(short = 'F', long, num_args = 0..)]
features: Vec<String>,

/// Stop the run after the first crash is encountered
#[clap(short = 'x', long)]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why -x? 'S' or 'C' might be more intuitive maybe? also what about timeouts?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-x kind of looks like a line crashing 😄 I'm open to changing it to -C.

ziggy run reacting to timeouts is a good idea, I'll create an issue 👍

stop_on_crash: bool,
}

#[derive(Args, Clone)]
Expand Down
53 changes: 35 additions & 18 deletions src/bin/cargo-ziggy/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,26 @@ impl Run {
}
}

let run_args: Vec<String> = self
let input_files: Vec<PathBuf> = self
.inputs
.iter()
.map(|x| {
x.display()
.flat_map(|x| {
let canonical_name = x
.display()
.to_string()
.replace("{ziggy_output}", &self.ziggy_output.display().to_string())
.replace("{target_name}", &target)
.replace("{target_name}", &target);
// For each directory we read, we get all files in that directory
let path = PathBuf::from(canonical_name);
match path.is_dir() {
true => fs::read_dir(path)
.expect("could not read directory")
.filter_map(|entry| entry.ok())
.map(|entry| entry.path())
.filter(|path| path.is_file())
.collect::<Vec<_>>(),
false => vec![path],
}
})
.collect();

Expand All @@ -83,21 +95,26 @@ impl Run {
false => format!("./target/runner/debug/{}", target),
};

let res = process::Command::new(runner_path)
.args(run_args)
.env("RUST_BACKTRACE", "full")
.spawn()
.context("⚠️ couldn't spawn the runner process")?
.wait()
.context("⚠️ couldn't wait for the runner process")?;
for file in input_files {
let res = process::Command::new(&runner_path)
.arg(file)
.env("RUST_BACKTRACE", "full")
.spawn()
.context("⚠️ couldn't spawn the runner process")?
.wait()
.context("⚠️ couldn't wait for the runner process")?;

if !res.success() {
if let Some(signal) = res.signal() {
println!("⚠️ input terminated with signal {:?}!", signal);
} else if let Some(exit_code) = res.code() {
println!("⚠️ input terminated with code {:?}!", exit_code);
} else {
println!("⚠️ input terminated but we do not know why!");
if !res.success() {
if let Some(signal) = res.signal() {
println!("⚠️ input terminated with signal {:?}!", signal);
} else if let Some(exit_code) = res.code() {
println!("⚠️ input terminated with code {:?}!", exit_code);
} else {
println!("⚠️ input terminated but we do not know why!");
}
if self.stop_on_crash {
return Ok(());
}
}
}

Expand Down
Loading