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
pub use arbitrary::{Arbitrary, Error as ArbitraryError, Unstructured};
use canonical::{Canon, Id, Sink};
const FUZZ_ITERATIONS: usize = 128;
fn raw_data<'a>() -> Unstructured<'a> {
Unstructured::new(include_bytes!("noise.bin"))
}
pub fn fuzz_canon<'a, C>()
where
C: Canon + Arbitrary<'a> + PartialEq + std::fmt::Debug,
{
fuzz_canon_iterations::<C>(FUZZ_ITERATIONS)
}
pub fn fuzz_canon_iterations<'a, C>(iterations: usize)
where
C: Canon + Arbitrary<'a> + PartialEq + std::fmt::Debug,
{
let data = &mut raw_data::<'a>();
for _ in 0..iterations {
let canon: C = Arbitrary::arbitrary(data).unwrap();
let claimed_len = canon.encoded_len();
let mut buffer_a = vec![];
buffer_a.resize_with(claimed_len + 1, || 0xff);
let mut buffer_b = vec![];
buffer_b.resize_with(claimed_len + 1, || 0x00);
let mut sink_a = Sink::new(&mut buffer_a[..]);
let mut sink_b = Sink::new(&mut buffer_b[..]);
canon.encode(&mut sink_a);
canon.encode(&mut sink_b);
let mut valid = true;
if buffer_a[claimed_len] != 0xff
|| buffer_b[claimed_len] != 0x00
|| (claimed_len > 0
&& buffer_a[claimed_len - 1] != buffer_b[claimed_len - 1])
{
valid = false
}
if !valid {
for i in 0..claimed_len {
if buffer_a[i] != buffer_b[i] {
panic!(
"{:?}\n\nclaimed {}, wrote {}",
canon,
claimed_len,
i - 1
);
}
}
}
let id = Id::new(&canon);
let restored = id.reify().unwrap();
assert!(canon == restored);
}
}