Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
google
GitHub Repository: google/crosvm
Path: blob/main/fuzz/src/rand.rs
5394 views
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
9
use rand_core::RngCore;
10
11
/// A random number generator that uses fuzzer input as the source of its
12
/// randomness. When run on the same input, it provides the same output, as
13
/// long as its methods are called in the same order and with the same
14
/// arguments.
15
pub struct FuzzRng<'a> {
16
buf: &'a [u8],
17
}
18
19
impl<'a> FuzzRng<'a> {
20
/// Creates a new `FuzzRng` from `buf`, which should be part or all of an
21
/// input buffer provided by a fuzzing library.
22
pub fn new(buf: &'a [u8]) -> FuzzRng<'a> {
23
FuzzRng { buf }
24
}
25
26
/// Consumes `self` and returns the inner slice.
27
pub fn into_inner(self) -> &'a [u8] {
28
let FuzzRng { buf } = self;
29
buf
30
}
31
}
32
33
impl RngCore for FuzzRng<'_> {
34
fn next_u32(&mut self) -> u32 {
35
let mut buf = [0u8; size_of::<u32>()];
36
self.fill_bytes(&mut buf);
37
38
u32::from_ne_bytes(buf)
39
}
40
41
fn next_u64(&mut self) -> u64 {
42
let mut buf = [0u8; size_of::<u64>()];
43
self.fill_bytes(&mut buf);
44
45
u64::from_ne_bytes(buf)
46
}
47
48
fn fill_bytes(&mut self, dest: &mut [u8]) {
49
let amt = min(self.buf.len(), dest.len());
50
let (a, b) = self.buf.split_at(amt);
51
dest[..amt].copy_from_slice(a);
52
self.buf = b;
53
54
if amt < dest.len() {
55
// We didn't have enough data to fill the whole buffer. Fill the rest
56
// with zeroes. The compiler is smart enough to turn this into a memset.
57
for b in &mut dest[amt..] {
58
*b = 0;
59
}
60
}
61
}
62
}
63
64
impl fmt::Debug for FuzzRng<'_> {
65
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
66
write!(f, "FuzzRng {{ {} bytes }}", self.buf.len())
67
}
68
}
69
70
#[cfg(test)]
71
mod tests {
72
use super::*;
73
74
#[test]
75
fn gen_u32() {
76
let val = 0xc2a744u32;
77
let buf = val.to_ne_bytes();
78
let mut rng = FuzzRng::new(&buf);
79
80
assert_eq!(rng.next_u32(), val);
81
assert_eq!(rng.next_u32(), 0);
82
}
83
84
#[test]
85
fn gen_u64() {
86
let val = 0xac75689deeu64;
87
let buf = val.to_ne_bytes();
88
let mut rng = FuzzRng::new(&buf);
89
90
assert_eq!(rng.next_u64(), val);
91
assert_eq!(rng.next_u64(), 0);
92
}
93
94
#[test]
95
fn fill_bytes() {
96
let buf = &[
97
0xed, 0x90, 0xf3, 0xa4, 0x8f, 0xbf, 0x6e, 0xdb, 0x68, 0xb9, 0x1f, 0x9a, 0x13, 0xfc,
98
0x9f, 0xc8, 0x9e, 0xfa, 0x4a, 0x02, 0x5e, 0xc8, 0xb1, 0xe5, 0x2d, 0x59, 0x22, 0x89,
99
0x10, 0x23, 0xc3, 0x31, 0x6c, 0x42, 0x40, 0xce, 0xfe, 0x6e, 0x5c, 0x3d, 0x10, 0xba,
100
0x0d, 0x11, 0xbc, 0x6a, 0x1f, 0x21, 0xc9, 0x72, 0x37, 0xba, 0xfa, 0x00, 0xb2, 0xa8,
101
0x51, 0x6d, 0xb2, 0x94, 0xf2, 0x34, 0xf8, 0x3c, 0x21, 0xc9, 0x59, 0x24, 0xd8, 0x77,
102
0x51, 0x3f, 0x64, 0xde, 0x19, 0xc8, 0xb3, 0x03, 0x26, 0x81, 0x85, 0x4c, 0xef, 0xb0,
103
0xd5, 0xd8, 0x65, 0xe1, 0x89, 0x8f, 0xb7, 0x14, 0x9b, 0x0d, 0xd9, 0xcb, 0xda, 0x35,
104
0xb2, 0xff, 0xd5, 0xd1, 0xae, 0x38, 0x55, 0xd5, 0x65, 0xba, 0xdc, 0xa1, 0x82, 0x62,
105
0xbf, 0xe6, 0x3d, 0x7a, 0x8f, 0x13, 0x65, 0x2f, 0x4b, 0xdc, 0xcb, 0xee, 0xd8, 0x99,
106
0x2c, 0x21, 0x97, 0xc8, 0x6e, 0x8e, 0x09, 0x0f, 0xf1, 0x4b, 0x85, 0xb5, 0x0f, 0x52,
107
0x82, 0x7f, 0xe0, 0x23, 0xc5, 0x9a, 0x6a, 0x7c, 0xf1, 0x46, 0x7d, 0xbf, 0x3f, 0x14,
108
0x0d, 0x41, 0x09, 0xd5, 0x63, 0x70, 0xa1, 0x0e, 0x04, 0x3c, 0x06, 0x0a, 0x0b, 0x5c,
109
0x95, 0xaf, 0xbd, 0xf5, 0x4b, 0x7f, 0xbe, 0x8d, 0xe2, 0x09, 0xce, 0xa2, 0xf6, 0x1e,
110
0x58, 0xd8, 0xda, 0xd4, 0x56, 0x56, 0xe1, 0x32, 0x30, 0xef, 0x0f, 0x2e, 0xed, 0xb9,
111
0x14, 0x57, 0xa8, 0x8a, 0x9c, 0xd8, 0x58, 0x7f, 0xd9, 0x4f, 0x11, 0xb2, 0x7a, 0xcf,
112
0xc0, 0xef, 0xf3, 0xc7, 0xc1, 0xc5, 0x1e, 0x86, 0x47, 0xc6, 0x42, 0x71, 0x15, 0xc8,
113
0x25, 0x1d, 0x94, 0x00, 0x8d, 0x04, 0x37, 0xe7, 0xfe, 0xf6, 0x10, 0x28, 0xe5, 0xb2,
114
0xef, 0x95, 0xa6, 0x53, 0x20, 0xf8, 0x51, 0xdb, 0x54, 0x99, 0x40, 0x4a, 0x7c, 0xd6,
115
0x90, 0x4a, 0x55, 0xdc, 0x37, 0xb8, 0xbc, 0x0b, 0xc4, 0x54, 0xd1, 0x9b, 0xb3, 0x8c,
116
0x09, 0x55, 0x77, 0xf5, 0x1b, 0xa7, 0x36, 0x06, 0x29, 0x4c, 0xa3, 0x26, 0x35, 0x1b,
117
0x29, 0xa3, 0xa3, 0x45, 0x74, 0xee, 0x0b, 0x78, 0xf8, 0x69, 0x70, 0xa4, 0x1d, 0x11,
118
0x7a, 0x91, 0xca, 0x4c, 0x83, 0xb3, 0xbf, 0xf6, 0x7f, 0x54, 0xca, 0xdb, 0x1f, 0xc4,
119
0xd2, 0xb2, 0x23, 0xfa, 0xc0, 0x24, 0x77, 0x74, 0x61, 0x9e, 0x0b, 0x77, 0x49, 0x29,
120
0xf1, 0xd9, 0xbf, 0xf0, 0x5e, 0x99, 0xa6, 0xf1, 0x00, 0xa4, 0x7f, 0xa0, 0xb1, 0x6b,
121
0xd8, 0xbe, 0xef, 0xa0, 0xa1, 0xa5, 0x33, 0x9c, 0xc3, 0x95, 0xaa, 0x9f,
122
];
123
124
let mut rng = FuzzRng::new(&buf[..]);
125
let mut dest = Vec::with_capacity(buf.len());
126
for chunk in buf.chunks(11) {
127
dest.resize(chunk.len(), 0);
128
rng.fill_bytes(&mut dest);
129
130
assert_eq!(chunk, &*dest);
131
}
132
133
dest.resize(97, 0x2c);
134
rng.fill_bytes(&mut dest);
135
136
let zero_buf = vec![0; dest.len()];
137
assert_eq!(zero_buf, dest);
138
}
139
}
140
141