• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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