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