1pub mod afl;
2pub mod argument;
3pub mod constants;
4pub mod fuzz;
5pub mod honggfuzz;
6
7use afl::*;
8use constants::*;
9use fuzz::*;
10use honggfuzz::*;
11
12pub mod utils;
13
14use serde::Deserialize;
15use std::{fs, io};
16use thiserror::Error;
17use utils::{discover_root, resolve_path};
18
19#[derive(Error, Debug)]
20pub enum Error {
21 #[error("invalid workspace")]
22 BadWorkspace,
23 #[error("{0:?}")]
24 Anyhow(#[from] anyhow::Error),
25 #[error("{0:?}")]
26 Io(#[from] io::Error),
27 #[error("{0:?}")]
28 Toml(#[from] toml::de::Error),
29}
30
31#[derive(Debug, Deserialize, Clone)]
32pub struct TridentConfig {
33 pub honggfuzz: Option<HonggFuzz>,
34 pub afl: Option<Afl>,
35 pub fuzz: Option<Fuzz>,
36}
37
38impl Default for TridentConfig {
39 fn default() -> Self {
40 Self::new()
41 }
42}
43
44impl TridentConfig {
45 pub fn new() -> Self {
46 let root = discover_root().expect("failed to find the root folder");
47 let s = fs::read_to_string(root.join(TRIDENT_TOML).as_path())
48 .expect("failed to read the Trident config file");
49 let _config: TridentConfig =
50 toml::from_str(&s).expect("failed to parse the Trident config file");
51 _config
52 }
53
54 pub fn get_honggfuzz_args(&self, cli_input: String) -> String {
57 if let Some(honggfuzz) = &self.honggfuzz {
58 let mut args = honggfuzz.get_collect_fuzz_args();
59 args.push(cli_input);
60 args.join(" ")
61 } else {
62 String::default()
63 }
64 }
65 pub fn get_honggfuzz_workspace(&self) -> String {
66 let path = self
67 .honggfuzz
68 .as_ref()
69 .map(|honggfuzz| honggfuzz.get_hfuzz_workspace().value)
70 .unwrap_or_else(|| HFUZZ_WORKSPACE_DEFAULT_HFUZZ.to_string());
71 let full_path = resolve_path(&path);
72 full_path.to_str().unwrap().to_string()
73 }
74 pub fn get_honggfuzz_target_dir(&self) -> String {
75 let path = self
76 .honggfuzz
77 .as_ref()
78 .map(|honggfuzz| honggfuzz.get_cargo_target_dir().value)
79 .unwrap_or_else(|| CARGO_TARGET_DIR_DEFAULT_HFUZZ.to_string());
80 let full_path = resolve_path(&path);
81 full_path.to_str().unwrap().to_string()
82 }
83 pub fn get_afl_target_dir(&self) -> String {
86 let path = self
87 .afl
88 .as_ref()
89 .map(|afl| afl.get_cargo_target_dir().value.unwrap())
90 .unwrap_or_else(|| CARGO_TARGET_DIR_DEFAULT_AFL.to_string());
91 let full_path = resolve_path(&path);
92 full_path.to_str().unwrap().to_string()
93 }
94 pub fn get_afl_target_path(&self, target: &str) -> String {
95 let mut afl_target_dir = self.get_afl_target_dir();
96 afl_target_dir.push_str("/debug/");
97 afl_target_dir.push_str(target);
98 afl_target_dir
99 }
100 pub fn get_afl_workspace_in(&self) -> String {
101 let path = self
102 .afl
103 .as_ref()
104 .map(|afl| afl.get_workspace_in().value.unwrap())
105 .unwrap_or_else(|| AFL_WORKSPACE_DEFAULT_IN.to_string());
106 let full_path = resolve_path(&path);
107 full_path.to_str().unwrap().to_string()
108 }
109 pub fn get_afl_workspace_out(&self) -> String {
110 let path = self
111 .afl
112 .as_ref()
113 .map(|afl| afl.get_workspace_out().value.unwrap())
114 .unwrap_or_else(|| AFL_WORKSPACE_DEFAULT_OUT.to_string());
115 let full_path = resolve_path(&path);
116 full_path.to_str().unwrap().to_string()
117 }
118 pub fn get_afl_build_args(&self) -> Vec<String> {
119 self.afl
120 .as_ref()
121 .map(|afl| afl.get_collect_build_args())
122 .unwrap_or_default()
123 }
124 pub fn get_afl_fuzz_args(&self) -> Vec<String> {
125 self.afl
126 .as_ref()
127 .map(|afl| afl.get_collect_fuzz_args())
128 .unwrap_or_default()
129 }
130
131 pub fn get_initial_seed(&self) -> Vec<AflSeed> {
132 self.afl
133 .as_ref()
134 .map(|afl| afl.get_seeds())
135 .unwrap_or_else(|| vec![AflSeed::default()])
136 }
137 pub fn get_fuzzing_with_stats(&self) -> bool {
140 self.fuzz
141 .as_ref()
142 .map(|fuzz| fuzz.get_fuzzing_with_stats())
143 .unwrap_or_default()
144 }
145 pub fn get_allow_duplicate_txs(&self) -> bool {
146 self.fuzz
147 .as_ref()
148 .map(|fuzz| fuzz.get_allow_duplicate_txs())
149 .unwrap_or_default()
150 }
151
152 pub fn programs(&self) -> Vec<FuzzProgram> {
153 self.fuzz
154 .as_ref()
155 .map(|fuzz| {
156 if let Some(programs) = &fuzz.programs {
157 programs.iter().map(FuzzProgram::from).collect()
158 } else {
159 Vec::default()
160 }
161 })
162 .unwrap_or_default()
163 }
164 pub fn accounts(&self) -> Vec<FuzzAccount> {
165 self.fuzz
166 .as_ref()
167 .map(|fuzz| {
168 if let Some(accounts) = &fuzz.accounts {
169 accounts.iter().map(FuzzAccount::from).collect()
170 } else {
171 Vec::default()
172 }
173 })
174 .unwrap_or_default()
175 }
176}