1 // Copyright 2021, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #![allow(missing_docs)]
16 #![no_main]
17
18 use libfuzzer_sys::arbitrary::Arbitrary;
19 use libfuzzer_sys::fuzz_target;
20 use smallvec::{Array, SmallVec};
21
22 // Avoid allocating too much memory and crashing the fuzzer.
23 const MAX_SIZE_MODIFIER: usize = 1024;
24
25 #[derive(Arbitrary, Clone, Debug, PartialEq)]
26 enum Data {
27 A,
28 B,
29 Int { val: u8 },
30 Str { s: String },
31 }
32
33 #[derive(Arbitrary, Debug)]
34 struct FuzzInfo {
35 inline_size: Size,
36 commands: Vec<Command>,
37 }
38
39 #[derive(Arbitrary, Debug)]
40 enum Size {
41 One,
42 Two,
43 Three,
44 Four,
45 Five,
46 }
47
48 #[derive(Arbitrary, Debug)]
49 enum Command {
50 Push { value: Data },
51 Pop,
52 Insert { index: usize, element: Data },
53 Remove { index: usize },
54 SwapRemove { index: usize },
55 Drain,
56 Clear,
57 Reserve { additional: usize },
58 ReserveExact { additional: usize },
59 ShrinkToFit,
60 Truncate { len: usize },
61 Grow { new_cap: usize },
62 Dedup,
63 Resize { len: usize, value: Data },
64 }
65
66 fuzz_target!(|info: FuzzInfo| {
67 match info.inline_size {
68 Size::One => do_fuzz::<[Data; 1]>(info.commands),
69 Size::Two => do_fuzz::<[Data; 2]>(info.commands),
70 Size::Three => do_fuzz::<[Data; 3]>(info.commands),
71 Size::Four => do_fuzz::<[Data; 4]>(info.commands),
72 Size::Five => do_fuzz::<[Data; 5]>(info.commands),
73 }
74 });
75
do_fuzz<T: Array<Item = Data>>(commands: Vec<Command>)76 fn do_fuzz<T: Array<Item = Data>>(commands: Vec<Command>) {
77 let mut vec = SmallVec::<T>::new();
78 for command in commands {
79 match command {
80 Command::Push { value } => {
81 vec.push(value);
82 }
83 Command::Pop => {
84 vec.pop();
85 }
86 Command::Insert { index, element } => {
87 if index < vec.len() {
88 vec.insert(index, element);
89 }
90 }
91 Command::Remove { index } => {
92 if index < vec.len() {
93 vec.remove(index);
94 }
95 }
96 Command::SwapRemove { index } => {
97 if index < vec.len() {
98 vec.remove(index);
99 }
100 }
101 Command::Drain => {
102 std::hint::black_box(vec.drain(..).count());
103 }
104 Command::Clear => {
105 vec.clear();
106 }
107 Command::Reserve { additional } => {
108 vec.reserve(additional % MAX_SIZE_MODIFIER);
109 }
110 Command::ReserveExact { additional } => {
111 vec.reserve_exact(additional % MAX_SIZE_MODIFIER);
112 }
113 Command::ShrinkToFit => {
114 vec.shrink_to_fit();
115 }
116 Command::Truncate { len } => {
117 vec.truncate(len);
118 }
119 Command::Grow { new_cap } => {
120 let new_cap = new_cap % MAX_SIZE_MODIFIER;
121 if new_cap >= vec.len() {
122 vec.grow(new_cap);
123 }
124 }
125 Command::Dedup => {
126 vec.dedup();
127 }
128 Command::Resize { len, value } => {
129 vec.resize(len % MAX_SIZE_MODIFIER, value);
130 }
131 }
132 }
133 }
134