• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 use std::cmp::min;
6 use std::fmt;
7 use std::mem::size_of;
8 use std::result::Result;
9 
10 use rand_core::{Error, ErrorKind, RngCore};
11 
12 /// A random number generator that uses fuzzer input as the source of its
13 /// randomness.  When run on the same input, it provides the same output, as
14 /// long as its methods are called in the same order and with the same
15 /// arguments.
16 pub struct FuzzRng<'a> {
17     buf: &'a [u8],
18 }
19 
20 impl<'a> FuzzRng<'a> {
21     /// Creates a new `FuzzRng` from `buf`, which should be part or all of an
22     /// input buffer provided by a fuzzing library.
new(buf: &'a [u8]) -> FuzzRng<'a>23     pub fn new(buf: &'a [u8]) -> FuzzRng<'a> {
24         FuzzRng { buf }
25     }
26 
27     /// Consumes `self` and returns the inner slice.
into_inner(self) -> &'a [u8]28     pub fn into_inner(self) -> &'a [u8] {
29         let FuzzRng { buf } = self;
30         buf
31     }
32 }
33 
34 impl<'a> RngCore for FuzzRng<'a> {
next_u32(&mut self) -> u3235     fn next_u32(&mut self) -> u32 {
36         let mut buf = [0u8; size_of::<u32>()];
37         self.fill_bytes(&mut buf);
38 
39         u32::from_ne_bytes(buf)
40     }
41 
next_u64(&mut self) -> u6442     fn next_u64(&mut self) -> u64 {
43         let mut buf = [0u8; size_of::<u64>()];
44         self.fill_bytes(&mut buf);
45 
46         u64::from_ne_bytes(buf)
47     }
48 
fill_bytes(&mut self, dest: &mut [u8])49     fn fill_bytes(&mut self, dest: &mut [u8]) {
50         let amt = min(self.buf.len(), dest.len());
51         let (a, b) = self.buf.split_at(amt);
52         dest[..amt].copy_from_slice(a);
53         self.buf = b;
54 
55         if amt < dest.len() {
56             // We didn't have enough data to fill the whole buffer.  Fill the rest
57             // with zeroes.  The compiler is smart enough to turn this into a memset.
58             for b in &mut dest[amt..] {
59                 *b = 0;
60             }
61         }
62     }
63 
try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error>64     fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
65         if self.buf.len() >= dest.len() {
66             self.fill_bytes(dest);
67             Ok(())
68         } else {
69             Err(Error::new(
70                 ErrorKind::Unavailable,
71                 "not enough data in fuzzer input",
72             ))
73         }
74     }
75 }
76 
77 impl<'a> fmt::Debug for FuzzRng<'a> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result78     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
79         write!(f, "FuzzRng {{ {} bytes }}", self.buf.len())
80     }
81 }
82 
83 #[cfg(test)]
84 mod tests {
85     use super::*;
86 
87     #[test]
gen_u32()88     fn gen_u32() {
89         let val = 0xc2a744u32;
90         let buf = val.to_ne_bytes();
91         let mut rng = FuzzRng::new(&buf);
92 
93         assert_eq!(rng.next_u32(), val);
94         assert_eq!(rng.next_u32(), 0);
95     }
96 
97     #[test]
gen_u64()98     fn gen_u64() {
99         let val = 0xac75689deeu64;
100         let buf = val.to_ne_bytes();
101         let mut rng = FuzzRng::new(&buf);
102 
103         assert_eq!(rng.next_u64(), val);
104         assert_eq!(rng.next_u64(), 0);
105     }
106 
107     #[test]
fill_bytes()108     fn fill_bytes() {
109         let buf = &[
110             0xed, 0x90, 0xf3, 0xa4, 0x8f, 0xbf, 0x6e, 0xdb, 0x68, 0xb9, 0x1f, 0x9a, 0x13, 0xfc,
111             0x9f, 0xc8, 0x9e, 0xfa, 0x4a, 0x02, 0x5e, 0xc8, 0xb1, 0xe5, 0x2d, 0x59, 0x22, 0x89,
112             0x10, 0x23, 0xc3, 0x31, 0x6c, 0x42, 0x40, 0xce, 0xfe, 0x6e, 0x5c, 0x3d, 0x10, 0xba,
113             0x0d, 0x11, 0xbc, 0x6a, 0x1f, 0x21, 0xc9, 0x72, 0x37, 0xba, 0xfa, 0x00, 0xb2, 0xa8,
114             0x51, 0x6d, 0xb2, 0x94, 0xf2, 0x34, 0xf8, 0x3c, 0x21, 0xc9, 0x59, 0x24, 0xd8, 0x77,
115             0x51, 0x3f, 0x64, 0xde, 0x19, 0xc8, 0xb3, 0x03, 0x26, 0x81, 0x85, 0x4c, 0xef, 0xb0,
116             0xd5, 0xd8, 0x65, 0xe1, 0x89, 0x8f, 0xb7, 0x14, 0x9b, 0x0d, 0xd9, 0xcb, 0xda, 0x35,
117             0xb2, 0xff, 0xd5, 0xd1, 0xae, 0x38, 0x55, 0xd5, 0x65, 0xba, 0xdc, 0xa1, 0x82, 0x62,
118             0xbf, 0xe6, 0x3d, 0x7a, 0x8f, 0x13, 0x65, 0x2f, 0x4b, 0xdc, 0xcb, 0xee, 0xd8, 0x99,
119             0x2c, 0x21, 0x97, 0xc8, 0x6e, 0x8e, 0x09, 0x0f, 0xf1, 0x4b, 0x85, 0xb5, 0x0f, 0x52,
120             0x82, 0x7f, 0xe0, 0x23, 0xc5, 0x9a, 0x6a, 0x7c, 0xf1, 0x46, 0x7d, 0xbf, 0x3f, 0x14,
121             0x0d, 0x41, 0x09, 0xd5, 0x63, 0x70, 0xa1, 0x0e, 0x04, 0x3c, 0x06, 0x0a, 0x0b, 0x5c,
122             0x95, 0xaf, 0xbd, 0xf5, 0x4b, 0x7f, 0xbe, 0x8d, 0xe2, 0x09, 0xce, 0xa2, 0xf6, 0x1e,
123             0x58, 0xd8, 0xda, 0xd4, 0x56, 0x56, 0xe1, 0x32, 0x30, 0xef, 0x0f, 0x2e, 0xed, 0xb9,
124             0x14, 0x57, 0xa8, 0x8a, 0x9c, 0xd8, 0x58, 0x7f, 0xd9, 0x4f, 0x11, 0xb2, 0x7a, 0xcf,
125             0xc0, 0xef, 0xf3, 0xc7, 0xc1, 0xc5, 0x1e, 0x86, 0x47, 0xc6, 0x42, 0x71, 0x15, 0xc8,
126             0x25, 0x1d, 0x94, 0x00, 0x8d, 0x04, 0x37, 0xe7, 0xfe, 0xf6, 0x10, 0x28, 0xe5, 0xb2,
127             0xef, 0x95, 0xa6, 0x53, 0x20, 0xf8, 0x51, 0xdb, 0x54, 0x99, 0x40, 0x4a, 0x7c, 0xd6,
128             0x90, 0x4a, 0x55, 0xdc, 0x37, 0xb8, 0xbc, 0x0b, 0xc4, 0x54, 0xd1, 0x9b, 0xb3, 0x8c,
129             0x09, 0x55, 0x77, 0xf5, 0x1b, 0xa7, 0x36, 0x06, 0x29, 0x4c, 0xa3, 0x26, 0x35, 0x1b,
130             0x29, 0xa3, 0xa3, 0x45, 0x74, 0xee, 0x0b, 0x78, 0xf8, 0x69, 0x70, 0xa4, 0x1d, 0x11,
131             0x7a, 0x91, 0xca, 0x4c, 0x83, 0xb3, 0xbf, 0xf6, 0x7f, 0x54, 0xca, 0xdb, 0x1f, 0xc4,
132             0xd2, 0xb2, 0x23, 0xfa, 0xc0, 0x24, 0x77, 0x74, 0x61, 0x9e, 0x0b, 0x77, 0x49, 0x29,
133             0xf1, 0xd9, 0xbf, 0xf0, 0x5e, 0x99, 0xa6, 0xf1, 0x00, 0xa4, 0x7f, 0xa0, 0xb1, 0x6b,
134             0xd8, 0xbe, 0xef, 0xa0, 0xa1, 0xa5, 0x33, 0x9c, 0xc3, 0x95, 0xaa, 0x9f,
135         ];
136 
137         let mut rng = FuzzRng::new(&buf[..]);
138         let mut dest = Vec::with_capacity(buf.len());
139         for chunk in buf.chunks(11) {
140             dest.resize(chunk.len(), 0);
141             rng.fill_bytes(&mut dest);
142 
143             assert_eq!(chunk, &*dest);
144         }
145 
146         dest.resize(97, 0x2c);
147         rng.fill_bytes(&mut dest);
148 
149         let zero_buf = vec![0; dest.len()];
150         assert_eq!(zero_buf, dest);
151     }
152 
153     #[test]
try_fill_bytes()154     fn try_fill_bytes() {
155         let buf = &[
156             0xdb, 0x35, 0xad, 0x4e, 0x9d, 0xf5, 0x2d, 0xf6, 0x0d, 0xc5, 0xd2, 0xfc, 0x9f, 0x4c,
157             0xb5, 0x12, 0xe3, 0x78, 0x40, 0x8d, 0x8b, 0xa1, 0x5c, 0xfe, 0x66, 0x49, 0xa9, 0xc0,
158             0x43, 0xa0, 0x95, 0xae, 0x31, 0x99, 0xd2, 0xaa, 0xbc, 0x85, 0x9e, 0x4b, 0x08, 0xca,
159             0x59, 0x21, 0x2b, 0x66, 0x37, 0x6a, 0xb9, 0xb2, 0xd8, 0x71, 0x84, 0xdd, 0xf6, 0x47,
160             0xa5, 0xb9, 0x87, 0x9f, 0x24, 0x97, 0x01, 0x65, 0x15, 0x38, 0x01, 0xd6, 0xb6, 0xf2,
161             0x80,
162         ];
163         let mut rng = FuzzRng::new(&buf[..]);
164         let mut dest = Vec::with_capacity(buf.len());
165         for chunk in buf.chunks(13) {
166             dest.resize(chunk.len(), 0);
167             rng.try_fill_bytes(&mut dest)
168                 .expect("failed to fill bytes while data is remaining");
169 
170             assert_eq!(chunk, &*dest);
171         }
172 
173         dest.resize(buf.len(), 0);
174         rng.try_fill_bytes(&mut dest)
175             .expect_err("successfully filled bytes when no data is remaining");
176     }
177 
178     #[test]
try_fill_bytes_partial()179     fn try_fill_bytes_partial() {
180         let buf = &[
181             0x8b, 0xe3, 0x20, 0x8d, 0xe0, 0x0b, 0xbe, 0x51, 0xa6, 0xec, 0x8a, 0xb5, 0xd6, 0x17,
182             0x04, 0x3f, 0x87, 0xae, 0xc8, 0xe8, 0xf8, 0xe7, 0xd4, 0xbd, 0xf3, 0x4e, 0x74, 0xcf,
183             0xbf, 0x0e, 0x9d, 0xe5, 0x78, 0xc3, 0xe6, 0x44, 0xb8, 0xd1, 0x40, 0xda, 0x63, 0x9f,
184             0x48, 0xf4, 0x09, 0x9c, 0x5c, 0x5f, 0x36, 0x0b, 0x0d, 0x2b, 0xe3, 0xc7, 0xcc, 0x3e,
185             0x9a, 0xb9, 0x0a, 0xca, 0x6d, 0x90, 0x77, 0x3b, 0x7a, 0x50, 0x16, 0x13, 0x5d, 0x20,
186             0x70, 0xc0, 0x88, 0x04, 0x9c, 0xac, 0x2b, 0xd6, 0x61, 0xa0, 0xbe, 0xa4, 0xff, 0xbd,
187             0xac, 0x9c, 0xa1, 0xb2, 0x95, 0x26, 0xeb, 0x99, 0x46, 0x67, 0xe4, 0xcd, 0x88, 0x7b,
188             0x20, 0x4d, 0xb2, 0x92, 0x40, 0x9f, 0x1c, 0xbd, 0xba, 0x22, 0xff, 0xca, 0x89, 0x3c,
189             0x3b,
190         ];
191 
192         let mut rng = FuzzRng::new(&buf[..]);
193         let mut dest = Vec::with_capacity(buf.len());
194         dest.resize((buf.len() / 2) + 1, 0);
195 
196         // The first time should be successful because there is enough data left
197         // in the buffer.
198         rng.try_fill_bytes(&mut dest).expect("failed to fill bytes");
199         assert_eq!(&buf[..dest.len()], &*dest);
200 
201         // The second time should fail because while there is data in the buffer it
202         // is not enough to fill `dest`.
203         rng.try_fill_bytes(&mut dest)
204             .expect_err("filled bytes with insufficient data in buffer");
205 
206         // This should succeed because `dest` is exactly big enough to hold all the remaining
207         // data in the buffer.
208         dest.resize(buf.len() - dest.len(), 0);
209         rng.try_fill_bytes(&mut dest)
210             .expect("failed to fill bytes with exact-sized buffer");
211         assert_eq!(&buf[buf.len() - dest.len()..], &*dest);
212     }
213 }
214