1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
//! Fuzzing target for edge cases and boundary conditions
#![no_main]
use libfuzzer_sys::fuzz_target;
use clock_rand::*;
fuzz_target!(|data: &[u8]| {
if data.len() < 4 {
return;
}
let test_case = data[0];
let param = data[1];
match test_case % 8 {
0 => {
// Edge case: Very small buffer sizes
let mut rng = Xoshiro256Plus::new(42);
let sizes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 15, 16, 31, 32, 63, 64, 127, 128];
for &size in &sizes {
let mut buf = vec![0u8; size];
rng.fill_bytes(&mut buf);
// Ensure buffer was filled
assert!(buf.len() == size);
}
}
1 => {
// Edge case: Large buffer allocations (limited for fuzzing)
let mut rng = Xoshiro256Plus::new(42);
let size = (param as usize).min(1024 * 10); // Limit to 10KB for fuzzing
let mut buf = vec![0u8; size];
rng.fill_bytes(&mut buf);
assert!(buf.len() == size);
}
2 => {
// Edge case: Seed generation boundary conditions
let seed_size = (param as usize).max(1).min(1024);
let mut seed_data = vec![0u8; seed_size];
// Fill with fuzzer data
let copy_len = seed_data.len().min(data.len().saturating_sub(2));
seed_data[..copy_len].copy_from_slice(&data[2..2 + copy_len]);
// Try to create seed - should not panic
let _ = Seed::from_bytes(seed_data);
}
3 => {
// Edge case: Distribution boundary values
#[cfg(feature = "distributions")]
{
let mut rng = Xoshiro256Plus::new(42);
let uniform = Uniform::new(0u32, u32::MAX);
// Generate many values to test distribution
for _ in 0..100 {
let _ = uniform.sample(&mut rng);
}
}
}
4 => {
// Edge case: State save/restore with corrupted data
#[cfg(feature = "fast_rng")]
{
let mut rng = Xoshiro256Plus::new(42);
let original_value = rng.next_u64();
// Save state
let state = rng.save_state();
// Corrupt state with fuzzer data (limited corruption for safety)
let mut corrupted_state = state;
if corrupted_state.len() > 2 {
let corrupt_index = (param as usize) % corrupted_state.len();
corrupted_state[corrupt_index] = data[2].wrapping_add(corrupted_state[corrupt_index]);
}
// Try to restore - should not panic even with corrupted data
let _ = rng.restore_state(corrupted_state);
// RNG should still be usable
let _ = rng.next_u64();
}
}
5 => {
// Edge case: Utility functions with boundary inputs
let mut rng = Xoshiro256Plus::new(42);
// Test sample with various sizes
let sample_size = (param as usize).min(100);
let data: Vec<i32> = (0..200).collect();
if sample_size <= data.len() {
let _ = sample(&mut rng, &data, sample_size);
}
}
6 => {
// Edge case: Range generation boundary conditions
let mut rng = Xoshiro256Plus::new(42);
// Test various range combinations
let ranges = [
(0u32, 1u32),
(0u32, u32::MAX),
(u32::MAX - 1, u32::MAX),
(param as u32, (param as u32).wrapping_add(100)),
];
for (low, high) in &ranges {
if *low < *high {
let _ = gen_range_u32(&mut rng, *low, *high);
}
}
}
7 => {
// Edge case: ChaCha20Rng with various seed sizes
#[cfg(feature = "crypto_rng")]
{
let seed_size = (param as usize).max(1).min(256);
let mut seed_data = vec![0u8; seed_size];
let copy_len = seed_data.len().min(data.len().saturating_sub(2));
seed_data[..copy_len].copy_from_slice(&data[2..2 + copy_len]);
if let Ok(seed) = Seed::from_bytes(seed_data) {
let mut rng = ChaCha20Rng::from_seed(seed);
// Test various operations
let _ = rng.next_u64();
let _ = rng.next_u32();
// Test buffer filling with various sizes
let buf_sizes = [1, 4, 8, 16, 32, 64, 128];
for &size in &buf_sizes {
let mut buf = vec![0u8; size];
rng.fill_bytes(&mut buf);
assert!(buf.len() == size);
}
}
}
}
_ => unreachable!(),
}
});