puffin/fuzzer/
config.rs

1use std::num::NonZeroUsize;
2use std::path::PathBuf;
3use std::time::Duration;
4
5use log::LevelFilter;
6
7use crate::fuzzer::mutations::MutationConfig;
8use crate::put::{PutDescriptor, PutOptions};
9
10/// Minimum of executions before starting to run bit-level mutations
11pub const MIN_BIT_EXECS: u64 = 5_000; // one 1 core
12/// Minimum of test cases in corpus before starting to run bit-level mutations
13pub const MIN_BIT_CORPUS: usize = 200; // on 1 core
14
15#[derive(Clone, Debug)]
16pub struct FuzzerConfig {
17    pub initial_corpus_dir: PathBuf,
18    pub initial_corpus: Option<Vec<String>>,
19    pub static_seed: Option<u64>,
20    pub max_iters: Option<u64>,
21    pub core_definition: String,
22    pub stats_file: PathBuf,
23    pub stats_interval: Duration,
24    pub corpus_dir: PathBuf,
25    pub objective_dir: PathBuf,
26    pub broker_port: u16,
27    pub minimizer: bool, // FIXME: support this property
28    pub mutation_stage_config: MutationStageConfig,
29    pub mutation_config: MutationConfig,
30    pub tui: bool,
31    pub no_launcher: bool,
32    pub log_folder: PathBuf,
33    pub is_experiment: bool,
34    pub put_options: PutOptions,
35    pub verbosity: LevelFilter, // level for the client logging
36    pub target: FuzzingTarget,
37}
38
39impl Default for FuzzerConfig {
40    fn default() -> Self {
41        let current = std::env::current_dir().unwrap();
42        Self {
43            initial_corpus_dir: current.join("./seeds"),
44            initial_corpus: None,
45            static_seed: None,
46            max_iters: None,
47            core_definition: "1".to_string(),
48            stats_file: current.join("log/stats.json"),
49            stats_interval: Duration::from_millis(250),
50            corpus_dir: current.join("corpus"),
51            objective_dir: current.join("objective"),
52            broker_port: 1337,
53            minimizer: false,
54            tui: false,
55            no_launcher: false,
56            log_folder: current.join("log"),
57            is_experiment: false,
58            verbosity: LevelFilter::Info, // default verbosity
59            mutation_stage_config: Default::default(),
60            mutation_config: Default::default(),
61            put_options: Default::default(),
62            target: Default::default(),
63        }
64    }
65}
66
67#[derive(Clone, Debug)]
68pub enum FuzzingTarget {
69    Single(Option<PutDescriptor>),
70    Differential(PutDescriptor, PutDescriptor),
71}
72
73impl Default for FuzzingTarget {
74    fn default() -> Self {
75        Self::Single(None)
76    }
77}
78
79#[derive(Clone, Copy, Debug)]
80pub struct MutationStageConfig {
81    /// How many iterations each stage gets, as an upper bound
82    /// It may randomly continue earlier. Each iteration works on a different Input from the corpus
83    pub max_iterations_per_stage: NonZeroUsize,
84    pub max_mutations_pow_per_iteration: u64,
85    // Whether to truncate the input after mutations, prior to adding it to the corpus
86    pub with_truncation: bool,
87    /// When true, all mutations stacked within one mutational stage confine their anchor selection
88    /// to a single randomly-chosen step (see [`crate::fuzzer::stages::StepLockedStackMutator`]).
89    /// Disabled by default; enable with the `--step-lock` CLI flag. Evaluation (OPC UA N=3 +
90    /// TLS cross-check) found it coverage/throughput-neutral with no measurable reachability or
91    /// corpus-executability benefit over geometric stacking + scope weights alone, so it is
92    /// opt-in rather than on by default.
93    pub step_locked_stacking: bool,
94}
95
96impl Default for MutationStageConfig {
97    //  TODO:EVAL: evaluate modifications of this config
98    fn default() -> Self {
99        Self {
100            max_iterations_per_stage: NonZeroUsize::new(128).unwrap(),
101            max_mutations_pow_per_iteration: 7,
102            with_truncation: false,
103            step_locked_stacking: false,
104            // Default for StdMutationalStage and StdMutationalStage (=HavocScheduledMutator)
105        }
106    }
107}