Skip to main content

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}