forked from MystenLabs/sui
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfuzz_mutations.rs
146 lines (126 loc) · 4.42 KB
/
fuzz_mutations.rs
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0
use rand::{seq::SliceRandom, SeedableRng};
use sui_types::transaction::TransactionKind;
use crate::fuzz::TransactionKindMutator;
pub mod drop_random_command_suffix;
pub mod drop_random_commands;
pub mod shuffle_command_inputs;
pub mod shuffle_commands;
pub mod shuffle_transaction_inputs;
pub mod shuffle_types;
// The number of times that we will try to select a different mutator if the selected one is unable
// to be applied for some reason.
const NUM_TRIES: u64 = 5;
// Combiners for `TransactionKindMutator`s:
// * `RandomMutator` will select a random mutator from a list of mutators
// * `ChainedMutator` will apply a list of mutators in sequence. If a given mutator doesn't apply
// it will be skipped but other mutations both before and after the failed mutator may still be applied.
pub struct RandomMutator {
pub rng: rand::rngs::StdRng,
pub mutators: Vec<Box<dyn TransactionKindMutator + Send + Sync>>,
pub num_tries: u64,
}
pub struct ChainedMutator {
pub mutators: Vec<Box<dyn TransactionKindMutator>>,
}
impl RandomMutator {
pub fn new() -> Self {
Self {
rng: rand::rngs::StdRng::from_seed([0u8; 32]),
mutators: vec![],
num_tries: NUM_TRIES,
}
}
pub fn add_mutator(&mut self, mutator: Box<dyn TransactionKindMutator + Send + Sync>) {
self.mutators.push(mutator);
}
pub fn select_mutator(&mut self) -> Option<&mut Box<dyn TransactionKindMutator + Send + Sync>> {
self.mutators.choose_mut(&mut self.rng)
}
}
impl Default for RandomMutator {
fn default() -> Self {
Self::new()
}
}
impl TransactionKindMutator for RandomMutator {
fn mutate(&mut self, transaction_kind: &TransactionKind) -> Option<TransactionKind> {
for _ in 0..self.num_tries {
if let Some(mutator) = self.select_mutator() {
return mutator.mutate(transaction_kind);
}
}
None
}
fn reset(&mut self, mutations_per_base: u64) {
for mutator in self.mutators.iter_mut() {
mutator.reset(mutations_per_base);
}
}
}
impl ChainedMutator {
pub fn new() -> Self {
Self { mutators: vec![] }
}
pub fn add_mutator(&mut self, mutator: Box<dyn TransactionKindMutator>) {
self.mutators.push(mutator);
}
}
impl Default for ChainedMutator {
fn default() -> Self {
Self::new()
}
}
impl TransactionKindMutator for ChainedMutator {
fn mutate(&mut self, transaction_kind: &TransactionKind) -> Option<TransactionKind> {
let mut mutated = transaction_kind.clone();
let mut num_mutations = 0;
for mutator in self.mutators.iter_mut() {
if let Some(new_mutated) = mutator.mutate(&mutated) {
num_mutations += 1;
mutated = new_mutated;
}
}
if num_mutations == 0 {
None
} else {
Some(mutated)
}
}
fn reset(&mut self, mutations_per_base: u64) {
for mutator in self.mutators.iter_mut() {
mutator.reset(mutations_per_base);
}
}
}
pub fn base_fuzzers(num_mutations: u64) -> RandomMutator {
let mut mutator = RandomMutator::new();
mutator.add_mutator(Box::new(shuffle_commands::ShuffleCommands {
rng: rand::rngs::StdRng::from_seed([0u8; 32]),
num_mutations_per_base_left: num_mutations,
}));
mutator.add_mutator(Box::new(shuffle_types::ShuffleTypes {
rng: rand::rngs::StdRng::from_seed([0u8; 32]),
num_mutations_per_base_left: num_mutations,
}));
mutator.add_mutator(Box::new(shuffle_command_inputs::ShuffleCommandInputs {
rng: rand::rngs::StdRng::from_seed([0u8; 32]),
num_mutations_per_base_left: num_mutations,
}));
mutator.add_mutator(Box::new(
shuffle_transaction_inputs::ShuffleTransactionInputs {
rng: rand::rngs::StdRng::from_seed([0u8; 32]),
num_mutations_per_base_left: num_mutations,
},
));
mutator.add_mutator(Box::new(drop_random_commands::DropRandomCommands {
rng: rand::rngs::StdRng::from_seed([0u8; 32]),
num_mutations_per_base_left: num_mutations,
}));
mutator.add_mutator(Box::new(drop_random_command_suffix::DropCommandSuffix {
rng: rand::rngs::StdRng::from_seed([0u8; 32]),
num_mutations_per_base_left: num_mutations,
}));
mutator
}