/src/fontations/fuzz/fuzz_targets/fuzz_range_set.rs
Line | Count | Source |
1 | | #![no_main] |
2 | | //! Fuzzes the incremental_font_transfer patch_group.rs API |
3 | | |
4 | | use std::ops::RangeInclusive; |
5 | | |
6 | | use libfuzzer_sys::{arbitrary, fuzz_target}; |
7 | | use read_fonts::collections::{IntSet, RangeSet}; |
8 | | |
9 | 372k | #[derive(Debug, arbitrary::Arbitrary)] Unexecuted instantiation: <fuzz_range_set::Operation as arbitrary::Arbitrary>::arbitrary_take_rest::{closure#0} Unexecuted instantiation: <fuzz_range_set::Operation as arbitrary::Arbitrary>::arbitrary_take_rest::{closure#1} Unexecuted instantiation: <fuzz_range_set::Operation as arbitrary::Arbitrary>::arbitrary_take_rest::{closure#2} Unexecuted instantiation: <fuzz_range_set::Operation as arbitrary::Arbitrary>::try_size_hint::{closure#0} <fuzz_range_set::Operation as arbitrary::Arbitrary>::arbitrary::{closure#0} Line | Count | Source | 9 | 86 | #[derive(Debug, arbitrary::Arbitrary)] |
<fuzz_range_set::Operation as arbitrary::Arbitrary>::arbitrary::{closure#1} Line | Count | Source | 9 | 372k | #[derive(Debug, arbitrary::Arbitrary)] |
<fuzz_range_set::Operation as arbitrary::Arbitrary>::arbitrary::{closure#2} Line | Count | Source | 9 | 86 | #[derive(Debug, arbitrary::Arbitrary)] |
|
10 | | enum Operation { |
11 | | Insert(RangeInclusive<u16>), |
12 | | Extend(Vec<RangeInclusive<u16>>), |
13 | | Intersection, |
14 | | Iter, |
15 | | } |
16 | | |
17 | 373k | #[derive(Debug, arbitrary::Arbitrary)] Unexecuted instantiation: <fuzz_range_set::SetIndex as arbitrary::Arbitrary>::arbitrary_take_rest::{closure#0} Unexecuted instantiation: <fuzz_range_set::SetIndex as arbitrary::Arbitrary>::arbitrary_take_rest::{closure#1} Unexecuted instantiation: <fuzz_range_set::SetIndex as arbitrary::Arbitrary>::arbitrary_take_rest::{closure#2} Unexecuted instantiation: <fuzz_range_set::SetIndex as arbitrary::Arbitrary>::try_size_hint::{closure#0} <fuzz_range_set::SetIndex as arbitrary::Arbitrary>::arbitrary::{closure#0} Line | Count | Source | 17 | 1.31k | #[derive(Debug, arbitrary::Arbitrary)] |
<fuzz_range_set::SetIndex as arbitrary::Arbitrary>::arbitrary::{closure#1} Line | Count | Source | 17 | 372k | #[derive(Debug, arbitrary::Arbitrary)] |
<fuzz_range_set::SetIndex as arbitrary::Arbitrary>::arbitrary::{closure#2} Line | Count | Source | 17 | 1.31k | #[derive(Debug, arbitrary::Arbitrary)] |
|
18 | | enum SetIndex { |
19 | | One, |
20 | | Two, |
21 | | } |
22 | | |
23 | | #[derive(Default)] |
24 | | struct State { |
25 | | range_set: RangeSet<u16>, |
26 | | int_set: IntSet<u16>, |
27 | | } |
28 | | |
29 | | const OP_COUNT_LIMIT: u64 = 1000; |
30 | | |
31 | 22.1k | fn range_len(range: &RangeInclusive<u16>) -> u64 { |
32 | 22.1k | if range.end() > range.start() { |
33 | 12.0k | let count = *range.end() as u64 - *range.start() as u64; |
34 | 12.0k | count.saturating_mul(count.ilog2() as u64) |
35 | | } else { |
36 | 10.0k | 0 |
37 | | } |
38 | 22.1k | } |
39 | | |
40 | | fuzz_target!(|operations: Vec<(Operation, SetIndex)>| { |
41 | | let mut state1: State = Default::default(); |
42 | | let mut state2: State = Default::default(); |
43 | | let mut op_count = 0u64; |
44 | | for (op, index) in operations { |
45 | | let (state, state_other) = match index { |
46 | | SetIndex::One => (&mut state1, &mut state2), |
47 | | SetIndex::Two => (&mut state2, &mut state1), |
48 | | }; |
49 | | |
50 | | match op { |
51 | | Operation::Insert(range) => { |
52 | | op_count = op_count.saturating_add(range_len(&range)); |
53 | | if op_count > OP_COUNT_LIMIT { |
54 | | return; |
55 | | } |
56 | | |
57 | | state.range_set.insert(range.clone()); |
58 | | state.int_set.insert_range(range.clone()); |
59 | | } |
60 | | Operation::Extend(ranges) => { |
61 | | for range in ranges.iter() { |
62 | | op_count = op_count.saturating_add(range_len(range)); |
63 | | if op_count > OP_COUNT_LIMIT { |
64 | | return; |
65 | | } |
66 | | state.int_set.insert_range(range.clone()); |
67 | | } |
68 | | state.range_set.extend(ranges.into_iter()); |
69 | | } |
70 | | Operation::Iter => { |
71 | | op_count = op_count.saturating_add(state.int_set.iter_ranges().count() as u64); |
72 | | if op_count > OP_COUNT_LIMIT { |
73 | | return; |
74 | | } |
75 | | |
76 | | assert!(state.range_set.iter().eq(state.int_set.iter_ranges())); |
77 | | } |
78 | | Operation::Intersection => { |
79 | | op_count = op_count.saturating_add(state.int_set.len()); |
80 | | op_count = op_count.saturating_add(state_other.int_set.len()); |
81 | | if op_count > OP_COUNT_LIMIT { |
82 | | return; |
83 | | } |
84 | | |
85 | | let mut tmp = state.int_set.clone(); |
86 | | tmp.intersect(&state_other.int_set); |
87 | | assert!(state |
88 | | .range_set |
89 | | .intersection(&state_other.range_set) |
90 | | .eq(tmp.iter_ranges())); |
91 | | } |
92 | | } |
93 | | } |
94 | | }); |