aha_misc/common/cli.rs
1//! Some CLI Definitions
2
3use std::path::PathBuf;
4
5use clap::Args;
6
7/// Base options for the fuzzer configuration.
8///
9/// This struct defines the common parameters needed for fuzzing operations,
10/// including input/output directories and token file configuration.
11#[derive(Args, Debug)]
12pub struct BaseFuzzerOptions {
13 /// Input corpus directory
14 #[arg(
15 help = "The directory to read initial inputs from ('seeds')",
16 long = "in",
17 required = true
18 )]
19 pub in_dir: PathBuf,
20
21 /// Output corpus directory
22 #[arg(long = "out", default_value = "./out")]
23 pub find_corpus_dir: PathBuf,
24
25 /// Directory to store crashes
26 #[arg(long = "crashes", default_value = "./crashes")]
27 pub find_crash_dir: PathBuf,
28
29 /// Optional directory to store crash inputs
30 #[arg(long = "crash_inputs")]
31 pub executor_crash_dir: Option<PathBuf>,
32
33 /// File has tokens
34 #[arg(long = "token_file", default_value = "")]
35 pub token_file: String,
36}
37
38/// Options for replaying test cases.
39///
40/// This struct defines the parameters for replaying previously generated
41/// test cases, including paths to corpus files, start/end indices,
42/// and debug settings.
43#[derive(Args, Debug)]
44pub struct ReplayOptions {
45 /// Replay corpus dir, could be dirs
46 #[arg(long = "replay-dir", action = clap::ArgAction::Append)]
47 pub replay_dirs: Option<Vec<String>>,
48
49 /// Replay corpus file, could be files
50 #[arg(long = "replay-file", action = clap::ArgAction::Append)]
51 pub replay_files: Option<Vec<String>>,
52
53 /// Start replaying from this index (0-based, inclusive)
54 #[arg(long, default_value = "0")]
55 pub start: usize,
56
57 /// End replaying at this index (0-based, exclusive), defaults to all files if not specified
58 #[arg(long)]
59 pub end: Option<usize>,
60
61 /// Enable debug mode
62 #[arg(long, action = clap::ArgAction::SetTrue)]
63 pub debug: bool,
64}
65
66impl ReplayOptions {
67 /// Get the list of files to replay.
68 ///
69 /// # Returns
70 /// A vector of PathBuf objects pointing to the files that should be replayed.
71 ///
72 /// # Description
73 /// This method processes both directories and individual files specified in the options.
74 /// For directories, it includes all files within those directories. It skips any paths
75 /// that don't exist or are not of the expected type.
76 pub fn get_replay_files(&self) -> Vec<PathBuf> {
77 let mut to_replay_files: Vec<PathBuf> = vec![];
78
79 // Process directories
80 if let Some(dirs) = &self.replay_dirs {
81 for dir_str in dirs {
82 let dir = PathBuf::from(dir_str);
83 if dir.is_dir() {
84 for entry in std::fs::read_dir(&dir).unwrap() {
85 let entry = entry.unwrap();
86 let path = entry.path();
87 if path.is_file() {
88 to_replay_files.push(path);
89 }
90 }
91 } else {
92 eprintln!("Warning: Skipping non-directory path: {:?}", dir);
93 }
94 }
95 }
96
97 // Process individual files
98 if let Some(files) = &self.replay_files {
99 for file_str in files {
100 let file = PathBuf::from(file_str);
101 if file.is_file() {
102 to_replay_files.push(file);
103 } else {
104 eprintln!("Warning: Skipping non-file path: {:?}", file);
105 }
106 }
107 }
108
109 to_replay_files
110 }
111
112 /// Get the end index for replay.
113 ///
114 /// # Returns
115 /// The end index if specified, or usize::MAX to indicate no limit.
116 pub fn get_end(&self) -> usize {
117 self.end.unwrap_or(usize::MAX)
118 }
119}