1
1
#![ no_main]
2
2
3
3
use anyhow:: Result ;
4
- use arbitrary:: Arbitrary ;
5
- use bstr:: BStr ;
4
+
5
+ use bstr:: { BStr , BString } ;
6
+
6
7
use gix_config:: {
7
8
file:: { init:: Options , Metadata } ,
8
9
File ,
9
10
} ;
10
11
use libfuzzer_sys:: fuzz_target;
11
12
use std:: hint:: black_box;
12
-
13
- #[ derive( Arbitrary , Debug ) ]
14
- struct Ctx < ' a > {
15
- input : & ' a [ u8 ] ,
16
- sections_by_name : & ' a str ,
17
- section_subsection_key_triples : Vec < ( & ' a str , Option < & ' a [ u8 ] > , & ' a str ) > ,
13
+ use std:: str;
14
+
15
+ fn fuzz_immutable ( file : & File , section_name : & str , subsection_name : & Option < BString > , key : & str ) {
16
+ // Can't use the map here is the borrow checker chucks a flip converting between
17
+ // &Option<BString> and Option<&BStr>.
18
+ let subsection_name: Option < & BStr > = if let Some ( n) = subsection_name {
19
+ Some ( n. as_ref ( ) )
20
+ } else {
21
+ None
22
+ } ;
23
+ // Singular strings.
24
+ _ = black_box ( file. string ( section_name, subsection_name, key) ) ;
25
+ _ = black_box ( file. string_by_key ( key) ) ;
26
+ _ = black_box ( file. string_filter ( section_name, subsection_name, key, & mut |_| false ) ) ;
27
+ _ = black_box ( file. string_filter_by_key ( key, & mut |_| false ) ) ;
28
+
29
+ // Plural strings.
30
+ _ = black_box ( file. strings ( section_name, subsection_name, key) ) ;
31
+ _ = black_box ( file. strings_by_key ( key) ) ;
32
+ _ = black_box ( file. strings_filter ( section_name, subsection_name, key, & mut |_| false ) ) ;
33
+ _ = black_box ( file. strings_filter_by_key ( key, & mut |_| false ) ) ;
34
+
35
+ // Singular path.
36
+ _ = black_box ( file. path ( section_name, subsection_name, key) ) ;
37
+ _ = black_box ( file. path_by_key ( key) ) ;
38
+ _ = black_box ( file. path_filter ( section_name, subsection_name, key, & mut |_| false ) ) ;
39
+ _ = black_box ( file. path_filter_by_key ( key, & mut |_| false ) ) ;
40
+
41
+ // Singular bool.
42
+ _ = black_box ( file. boolean ( section_name, subsection_name, key) ) ;
43
+ _ = black_box ( file. boolean_by_key ( key) ) ;
44
+ _ = black_box ( file. boolean_filter ( section_name, subsection_name, key, & mut |_| false ) ) ;
45
+ _ = black_box ( file. boolean_filter_by_key ( key, & mut |_| false ) ) ;
46
+ // NOTE: no plural bool.
47
+
48
+ // Singular integer.
49
+ _ = black_box ( file. integer ( section_name, subsection_name, key) ) ;
50
+ _ = black_box ( file. integer_by_key ( key) ) ;
51
+ _ = black_box ( file. integer_filter ( section_name, subsection_name, key, & mut |_| false ) ) ;
52
+ _ = black_box ( file. integer_filter_by_key ( key, & mut |_| false ) ) ;
53
+
54
+ // Plural integers.
55
+ _ = black_box ( file. integers ( section_name, subsection_name, key) ) ;
56
+ _ = black_box ( file. integers_by_key ( key) ) ;
57
+ _ = black_box ( file. integers_filter ( section_name, subsection_name, key, & mut |_| false ) ) ;
58
+ _ = black_box ( file. integers_filter_by_key ( key, & mut |_| false ) ) ;
18
59
}
19
60
20
- const DEFAULT_TRIPLE : ( & str , Option < & ' static [ u8 ] > , & str ) = ( "section" , Some ( b"subsection" ) , "key" ) ;
61
+ fn fuzz_mutable ( file : & mut File , section_name : & str , subsection_name : & Option < BString > , key : & str ) -> Result < ( ) > {
62
+ // TODO: It might make sense to make fuzzed modifications.
63
+
64
+ // Can't use the map here is the borrow checker chucks a flip converting between
65
+ // &Option<BString> and Option<&BStr>.
66
+ let subsection_name: Option < & BStr > = if let Some ( n) = subsection_name {
67
+ Some ( n. as_ref ( ) )
68
+ } else {
69
+ None
70
+ } ;
71
+
72
+ // Mutate section.
73
+ {
74
+ let mut section = file. section_mut ( section_name, subsection_name) ?;
75
+ section. push_newline ( ) ;
76
+ section. set ( key. to_string ( ) . try_into ( ) ?, BStr :: new ( "Set value" ) ) ;
77
+ section. push_newline ( ) ;
78
+ let kv_pair = section. pop ( ) . map ( |( key, value) | ( key. to_owned ( ) , value. to_owned ( ) ) ) ;
79
+ if let Some ( ( key, value) ) = kv_pair {
80
+ section. push_with_comment ( key, Some ( & value) , "Popped" ) ;
81
+ }
82
+ }
83
+
84
+ // Singular raw.
85
+ _ = black_box (
86
+ file. raw_value_mut ( section_name, subsection_name, key) ?
87
+ . set_string ( "raw_values" ) ,
88
+ ) ;
89
+
90
+ // Plural raw.
91
+ _ = black_box ( file. raw_values_mut ( section_name, subsection_name, key) ?. len ( ) ) ;
92
+ Ok ( ( ) )
93
+ }
21
94
22
- fn fuzz ( ctx : Ctx ) -> Result < ( ) > {
95
+ fn fuzz ( input : & [ u8 ] ) -> Result < ( ) > {
23
96
let meta = Metadata :: default ( ) ;
24
97
let options = Options :: default ( ) ;
25
- let file = File :: from_bytes_no_includes ( & ctx. input , meta. clone ( ) , options. clone ( ) ) ?;
26
-
27
- let mut triples = ctx. section_subsection_key_triples . iter ( ) ;
28
-
29
- let ( section_name, subsection_name, key) = triples. next ( ) . unwrap_or ( & DEFAULT_TRIPLE ) ;
30
- _ = black_box ( file. string ( section_name, subsection_name. map ( |x| BStr :: new ( x) ) , key) ) ;
31
- _ = black_box ( file. string_by_key ( BStr :: new ( key) ) ) ;
32
- _ = black_box ( file. string_filter ( section_name, subsection_name. map ( |x| BStr :: new ( x) ) , key, & mut |_| false ) ) ;
33
- _ = black_box ( file. string_filter_by_key ( BStr :: new ( key) , & mut |_| false ) ) ;
34
-
35
- let ( section_name, subsection_name, key) = triples. next ( ) . unwrap_or ( & DEFAULT_TRIPLE ) ;
36
- _ = black_box ( file. path ( section_name, subsection_name. map ( |x| BStr :: new ( x) ) , key) ) ;
37
- _ = black_box ( file. path_by_key ( BStr :: new ( key) ) ) ;
38
- _ = black_box ( file. path_filter ( section_name, subsection_name. map ( |x| BStr :: new ( x) ) , key, & mut |_| false ) ) ;
39
- _ = black_box ( file. path_filter_by_key ( BStr :: new ( key) , & mut |_| false ) ) ;
40
-
41
- let ( section_name, subsection_name, key) = triples. next ( ) . unwrap_or ( & DEFAULT_TRIPLE ) ;
42
- _ = black_box ( file. boolean ( section_name, subsection_name. map ( |x| BStr :: new ( x) ) , key) ) ;
43
- _ = black_box ( file. boolean_by_key ( BStr :: new ( key) ) ) ;
44
- _ = black_box ( file. boolean_filter ( section_name, subsection_name. map ( |x| BStr :: new ( x) ) , key, & mut |_| false ) ) ;
45
- _ = black_box ( file. boolean_filter_by_key ( BStr :: new ( key) , & mut |_| false ) ) ;
46
-
47
- let ( section_name, subsection_name, key) = triples. next ( ) . unwrap_or ( & DEFAULT_TRIPLE ) ;
48
- _ = black_box ( file. integer ( section_name, subsection_name. map ( |x| BStr :: new ( x) ) , key) ) ;
49
- _ = black_box ( file. integer_by_key ( BStr :: new ( key) ) ) ;
50
- _ = black_box ( file. integer_filter ( section_name, subsection_name. map ( |x| BStr :: new ( x) ) , key, & mut |_| false ) ) ;
51
- _ = black_box ( file. integer_filter_by_key ( BStr :: new ( key) , & mut |_| false ) ) ;
52
-
53
- let ( section_name, subsection_name, key) = triples. next ( ) . unwrap_or ( & DEFAULT_TRIPLE ) ;
54
- _ = black_box ( file. strings ( section_name, subsection_name. map ( |x| BStr :: new ( x) ) , key) ) ;
55
- _ = black_box ( file. strings_by_key ( BStr :: new ( key) ) ) ;
56
- _ = black_box ( file. strings_filter ( section_name, subsection_name. map ( |x| BStr :: new ( x) ) , key, & mut |_| false ) ) ;
57
- _ = black_box ( file. strings_filter_by_key ( BStr :: new ( key) , & mut |_| false ) ) ;
58
-
59
- let ( section_name, subsection_name, key) = triples. next ( ) . unwrap_or ( & DEFAULT_TRIPLE ) ;
60
- _ = black_box ( file. integers ( section_name, subsection_name. map ( |x| BStr :: new ( x) ) , key) ) ;
61
- _ = black_box ( file. integers_by_key ( BStr :: new ( key) ) ) ;
62
- _ = black_box ( file. integers_filter ( section_name, subsection_name. map ( |x| BStr :: new ( x) ) , key, & mut |_| false ) ) ;
63
- _ = black_box ( file. integers_filter_by_key ( BStr :: new ( key) , & mut |_| false ) ) ;
64
-
65
- let ( section_name, subsection_name, key) = triples. next ( ) . unwrap_or ( & DEFAULT_TRIPLE ) ;
66
- _ = black_box ( file. integers ( section_name, subsection_name. map ( |x| BStr :: new ( x) ) , key) ) ;
67
- _ = black_box ( file. integers_by_key ( BStr :: new ( key) ) ) ;
68
- _ = black_box ( file. integers_filter ( section_name, subsection_name. map ( |x| BStr :: new ( x) ) , key, & mut |_| false ) ) ;
69
- _ = black_box ( file. integers_filter_by_key ( BStr :: new ( key) , & mut |_| false ) ) ;
70
-
71
- _ = black_box ( file. sections ( ) . count ( ) ) ;
98
+ let mut file = File :: from_bytes_no_includes ( input, meta. clone ( ) , options. clone ( ) ) ?;
99
+
100
+ let section_triples: Vec < _ > = file
101
+ . sections ( )
102
+ . flat_map ( |sec| {
103
+ sec. keys ( ) . map ( |key| {
104
+ let section_name = str:: from_utf8 ( sec. header ( ) . name ( ) ) . unwrap ( ) ;
105
+ let subsection_name = sec. header ( ) . subsection_name ( ) ;
106
+ let key = str:: from_utf8 ( & key) . unwrap ( ) ;
107
+ return (
108
+ section_name. to_owned ( ) ,
109
+ subsection_name. map ( |x| x. to_owned ( ) ) ,
110
+ key. to_owned ( ) ,
111
+ ) ;
112
+ } )
113
+ } )
114
+ . collect ( ) ;
115
+
116
+ for section_triple in section_triples. iter ( ) {
117
+ let ( section_name, subsection_name, key) = section_triple;
118
+ black_box ( fuzz_immutable ( & file, & section_name, & subsection_name, & key) ) ;
119
+ }
120
+
121
+ for section_triple in section_triples. iter ( ) {
122
+ let ( section_name, subsection_name, key) = section_triple;
123
+ _ = black_box ( fuzz_mutable ( & mut file, & section_name, & subsection_name, & key) ) ;
124
+ }
125
+
72
126
_ = black_box ( file. sections_and_ids ( ) . count ( ) ) ;
73
127
_ = black_box ( file. sections_and_postmatter ( ) . count ( ) ) ;
74
- _ = black_box ( file. sections_by_name ( ctx . sections_by_name ) . map ( |x| x. count ( ) ) ) ;
128
+ _ = black_box ( file. sections_by_name ( "section" ) . map ( |x| x. count ( ) ) ) ;
75
129
_ = black_box ( file. frontmatter ( ) ) ;
76
130
77
- for section in file. sections ( ) {
78
- for key in section. keys ( ) {
79
- _ = black_box (
80
- section
81
- . value_implicit ( key. as_ref ( ) )
82
- . expect ( "The key exists, so should the value." ) ,
83
- ) ;
84
- }
85
- }
86
-
87
131
let roundtrip_as_string: Vec < u8 > = file. to_bstring ( ) . into ( ) ;
88
132
_ = black_box ( File :: from_bytes_no_includes (
89
133
& roundtrip_as_string,
@@ -93,6 +137,6 @@ fn fuzz(ctx: Ctx) -> Result<()> {
93
137
Ok ( ( ) )
94
138
}
95
139
96
- fuzz_target ! ( |ctx : Ctx | {
97
- _ = black_box( fuzz( ctx ) ) ;
140
+ fuzz_target ! ( |input : & [ u8 ] | {
141
+ _ = black_box( fuzz( input ) ) ;
98
142
} ) ;
0 commit comments