1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
use crate::FuzzTarget;
use anyhow::{bail, format_err, Context, Result};
use diem_proptest_helpers::ValueGenerator;
use sha1::{Digest, Sha1};
use std::{
env,
ffi::OsString,
fs,
io::Write,
path::{Path, PathBuf},
process::Command,
};
pub fn make_corpus(
target: FuzzTarget,
num_items: usize,
corpus_dir: &Path,
debug: bool,
) -> Result<usize> {
let mut gen = ValueGenerator::new();
let mut sha1 = Sha1::new();
let mut idx = 0;
while idx < num_items {
let result = match target.generate(idx, &mut gen) {
Some(bytes) => bytes,
None => {
break;
}
};
sha1.update(&result);
let hash = sha1.finalize_reset();
let name = hex::encode(hash.as_slice());
let path = corpus_dir.join(name);
let mut f = fs::File::create(&path)
.with_context(|| format!("Failed to create file: {:?}", path))?;
if debug {
println!("Writing {} bytes to file: {:?}", result.len(), path);
}
f.write_all(&result)
.with_context(|| format!("Failed to write to file: {:?}", path))?;
idx += 1;
}
Ok(idx)
}
pub fn fuzz_target(
target: FuzzTarget,
corpus_dir: PathBuf,
artifact_dir: PathBuf,
mut args: Vec<OsString>,
) -> Result<()> {
static FUZZ_RUNNER: &str = "fuzz_runner";
let dash_dash_pos = args.iter().position(|x| x == "--");
let splice_pos = dash_dash_pos.unwrap_or(args.len());
args.splice(
splice_pos..splice_pos,
vec![FUZZ_RUNNER.into(), corpus_dir.into()],
);
if dash_dash_pos.is_none() {
args.push("--".into());
}
let mut artifact_arg: OsString = "-artifact_prefix=".into();
artifact_arg.push(&artifact_dir);
artifact_arg.push("/");
args.push(artifact_arg);
let manifest_dir = env::var_os("CARGO_MANIFEST_DIR").ok_or_else(|| {
format_err!("Fuzzing requires CARGO_MANIFEST_DIR to be set (are you using `cargo run`?)")
})?;
let status = Command::new("cargo")
.arg("fuzz")
.arg("run")
.args(args)
.current_dir(manifest_dir)
.env(FuzzTarget::ENV_VAR, target.name())
.env("RUSTC_BOOTSTRAP", "1")
.status()
.context("cargo fuzz run errored")?;
if !status.success() {
bail!("cargo fuzz run failed with status {}", status);
}
Ok(())
}
pub fn list_targets(no_desc: bool) {
for target in FuzzTarget::all_targets() {
if no_desc {
println!("{}", target.name())
} else {
println!(" * {0: <24} {1}", target.name(), target.description())
}
}
}