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
//! represents an action that should be performed, typically in response to some event
#![allow(clippy::use_self)] // clippy false-positive on Action, doesn't want to apply directly to the enums that derive Serialize
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use crate::corpora::CorpusItemType;
/// all possible actions
#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[non_exhaustive]
pub enum Action {
/// when used in a pre-send context, retain the current [`Request`], if
/// used in a post-send context, retain the current [`Response`]
///
/// [`Request`]: crate::requests::Request
/// [`Response`]: crate::responses::Response
Keep,
/// when used in a pre-send context, ignore the current [`Request`], if
/// used in a post-send context, ignore the current [`Response`]
///
/// [`Request`]: crate::requests::Request
/// [`Response`]: crate::responses::Response
Discard,
/// add the current mutated field(s) to the [`Corpus`] associated
/// with the given `name`.
///
/// the [`FlowControl`] passed to the `AddToCorpus` action is used to
/// embed a `Keep` or `Discard` action that will dictate whether the
/// mutated request or response should be allowed to be processed
/// any further, after being added to the corpus.
///
/// said another way: when the action is `AddToCorpus`, the current
/// request's fuzzable fields will (unconditionally) be added to the
/// named corpus. If the `FlowControl` is `Keep`, the request will continue
/// in the fuzz loop, and if the `FlowControl` is `Discard`, the request
/// won't progress beyond being added to the corpus. In either case, the
/// resulting `Action` will still be passed to any configured
/// [`Processor`]s.
///
/// [`Corpus`]: crate::corpora::Corpus
/// [`Processor`]: crate::processors::Processor
AddToCorpus(String, CorpusItemType, FlowControl),
/// break out of the current fuzz loop; no more iterations other than
/// what's already in flight will be performed
StopFuzzing,
}
impl Action {
/// returns `true` if the action is [`Action::Discard`] or has a flow control
/// directive of [`FlowControl::Discard`]; false otherwise
#[must_use]
pub const fn should_discard(&self) -> bool {
matches!(self, Self::Discard)
|| matches!(self, Action::AddToCorpus(_, _, FlowControl::Discard))
}
}
/// analogous to the [`Action::Keep`], [`Action::Discard`], and [`Action::StopFuzzing`] variants
///
/// used when the [`Action`] isn't a flow control directive itself
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[non_exhaustive]
pub enum FlowControl {
/// when used in a pre-send context, retain the current [`Request`], if
/// used in a post-send context, retain the current [`Response`]
///
/// [`Request`]: crate::requests::Request
/// [`Response`]: crate::responses::Response
Keep,
/// when used in a pre-send context, ignore the current [`Request`], if
/// used in a post-send context, ignore the current [`Response`]
///
/// [`Request`]: crate::requests::Request
/// [`Response`]: crate::responses::Response
Discard,
/// break out of the current fuzz loop; no more iterations other than
/// what's already in flight will be performed
StopFuzzing,
}