11#![ no_main]
22
33use anyhow:: Result ;
4- use arbitrary:: Arbitrary ;
5- use bstr:: BStr ;
4+
5+ use bstr:: { BStr , BString } ;
6+
67use gix_config:: {
78 file:: { init:: Options , Metadata } ,
89 File ,
910} ;
1011use libfuzzer_sys:: fuzz_target;
1112use 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 ) ) ;
1859}
1960
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+ }
2194
22- fn fuzz ( ctx : Ctx ) -> Result < ( ) > {
95+ fn fuzz ( input : & [ u8 ] ) -> Result < ( ) > {
2396 let meta = Metadata :: default ( ) ;
2497 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+
72126 _ = black_box ( file. sections_and_ids ( ) . count ( ) ) ;
73127 _ = 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 ( ) ) ) ;
75129 _ = black_box ( file. frontmatter ( ) ) ;
76130
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-
87131 let roundtrip_as_string: Vec < u8 > = file. to_bstring ( ) . into ( ) ;
88132 _ = black_box ( File :: from_bytes_no_includes (
89133 & roundtrip_as_string,
@@ -93,6 +137,6 @@ fn fuzz(ctx: Ctx) -> Result<()> {
93137 Ok ( ( ) )
94138}
95139
96- fuzz_target ! ( |ctx : Ctx | {
97- _ = black_box( fuzz( ctx ) ) ;
140+ fuzz_target ! ( |input : & [ u8 ] | {
141+ _ = black_box( fuzz( input ) ) ;
98142} ) ;
0 commit comments