@@ -11,10 +11,13 @@ enum RawOption<'a> {
11
11
}
12
12
13
13
fn parse_option ( arg : & str ) -> Option < RawOption > {
14
- if arg. starts_with ( '-' ) {
14
+ if arg. starts_with ( "--" ) {
15
+ None
16
+ } else if arg. starts_with ( '-' ) {
15
17
if let Some ( ( name, value) ) = arg. split_at ( 1 ) . 1 . split_once ( '=' ) {
16
18
Some ( Flag { name, value } )
17
19
} else {
20
+ eprintln ! ( "warning: flag {arg} provided without a value; did you mean `{arg}=1'?" ) ;
18
21
None
19
22
}
20
23
} else {
@@ -100,6 +103,7 @@ pub struct LibfuzzerOptions {
100
103
ignore_ooms : bool ,
101
104
rss_limit : usize ,
102
105
unknown : Vec < String > ,
106
+ pub malloc_limit : usize ,
103
107
}
104
108
105
109
impl LibfuzzerOptions {
@@ -185,7 +189,9 @@ struct LibfuzzerOptionsBuilder<'a> {
185
189
ignore_crashes : bool ,
186
190
ignore_timeouts : bool ,
187
191
ignore_ooms : bool ,
188
- rss_limit : usize ,
192
+ rss_limit : Option < usize > ,
193
+ malloc_limit : Option < usize > ,
194
+ ignore_remaining : bool ,
189
195
unknown : Vec < & ' a str > ,
190
196
}
191
197
@@ -201,52 +207,68 @@ macro_rules! parse_or_bail {
201
207
202
208
impl < ' a > LibfuzzerOptionsBuilder < ' a > {
203
209
fn consume ( mut self , arg : & ' a str ) -> Result < Self , OptionsParseError < ' a > > {
204
- if let Some ( option) = parse_option ( arg) {
205
- match option {
206
- Directory ( dir) => {
207
- self . dirs . push ( dir) ;
208
- }
209
- Flag { name, value } => match name {
210
- "merge" => {
211
- if parse_or_bail ! ( name, value, u64 ) > 0
212
- && * self . mode . get_or_insert ( LibfuzzerMode :: Merge )
213
- != LibfuzzerMode :: Merge
214
- {
215
- return Err ( OptionsParseError :: MultipleModesSelected ) ;
216
- }
210
+ if !self . ignore_remaining {
211
+ if let Some ( option) = parse_option ( arg) {
212
+ match option {
213
+ Directory ( dir) => {
214
+ self . dirs . push ( dir) ;
217
215
}
218
- "minimize_crash" => {
219
- if parse_or_bail ! ( name, value, u64 ) > 0
220
- && * self . mode . get_or_insert ( LibfuzzerMode :: Cmin ) != LibfuzzerMode :: Cmin
221
- {
222
- return Err ( OptionsParseError :: MultipleModesSelected ) ;
216
+ Flag { name, value } => match name {
217
+ "merge" => {
218
+ if parse_or_bail ! ( name, value, u64 ) > 0
219
+ && * self . mode . get_or_insert ( LibfuzzerMode :: Merge )
220
+ != LibfuzzerMode :: Merge
221
+ {
222
+ return Err ( OptionsParseError :: MultipleModesSelected ) ;
223
+ }
223
224
}
224
- }
225
- "grimoire" => self . grimoire = Some ( parse_or_bail ! ( name, value, u64 ) > 0 ) ,
226
- "artifact_prefix" => {
227
- self . artifact_prefix = Some ( value) ;
228
- }
229
- "timeout" => {
230
- self . timeout =
231
- Some ( value. parse ( ) . map ( Duration :: from_secs_f64) . map_err ( |_| {
232
- OptionsParseError :: OptionValueParseFailed ( name, value)
233
- } ) ?) ;
234
- }
235
- "dict" => self . dict = Some ( value) ,
236
- "fork" | "jobs" => {
237
- self . forks = Some ( parse_or_bail ! ( name, value, usize ) ) ;
238
- }
239
- "ignore_crashes" => self . ignore_crashes = parse_or_bail ! ( name, value, u64 ) > 0 ,
240
- "ignore_timeouts" => {
241
- self . ignore_timeouts = parse_or_bail ! ( name, value, u64 ) > 0
242
- }
243
- "ignore_ooms" => self . ignore_ooms = parse_or_bail ! ( name, value, u64 ) > 0 ,
244
- "rss_limit_mb" => self . rss_limit = parse_or_bail ! ( name, value, usize ) << 20 ,
245
- _ => self . unknown . push ( arg) ,
246
- } ,
225
+ "minimize_crash" => {
226
+ if parse_or_bail ! ( name, value, u64 ) > 0
227
+ && * self . mode . get_or_insert ( LibfuzzerMode :: Cmin )
228
+ != LibfuzzerMode :: Cmin
229
+ {
230
+ return Err ( OptionsParseError :: MultipleModesSelected ) ;
231
+ }
232
+ }
233
+ "grimoire" => self . grimoire = Some ( parse_or_bail ! ( name, value, u64 ) > 0 ) ,
234
+ "artifact_prefix" => {
235
+ self . artifact_prefix = Some ( value) ;
236
+ }
237
+ "timeout" => {
238
+ self . timeout =
239
+ Some ( value. parse ( ) . map ( Duration :: from_secs_f64) . map_err ( |_| {
240
+ OptionsParseError :: OptionValueParseFailed ( name, value)
241
+ } ) ?) ;
242
+ }
243
+ "dict" => self . dict = Some ( value) ,
244
+ "fork" | "jobs" => {
245
+ self . forks = Some ( parse_or_bail ! ( name, value, usize ) ) ;
246
+ }
247
+ "ignore_crashes" => {
248
+ self . ignore_crashes = parse_or_bail ! ( name, value, u64 ) > 0
249
+ }
250
+ "ignore_timeouts" => {
251
+ self . ignore_timeouts = parse_or_bail ! ( name, value, u64 ) > 0
252
+ }
253
+ "ignore_ooms" => self . ignore_ooms = parse_or_bail ! ( name, value, u64 ) > 0 ,
254
+ "rss_limit_mb" => {
255
+ self . rss_limit = Some ( parse_or_bail ! ( name, value, usize ) << 20 )
256
+ }
257
+ "malloc_limit_mb" => {
258
+ self . malloc_limit = Some ( parse_or_bail ! ( name, value, usize ) << 20 )
259
+ }
260
+ "ignore_remaining_args" => {
261
+ self . ignore_remaining = parse_or_bail ! ( name, value, u64 ) > 0
262
+ }
263
+ _ => {
264
+ eprintln ! ( "warning: unrecognised flag {name}" ) ;
265
+ self . unknown . push ( arg)
266
+ }
267
+ } ,
268
+ }
269
+ } else {
270
+ self . unknown . push ( arg)
247
271
}
248
- } else {
249
- self . unknown . push ( arg) ;
250
272
}
251
273
Ok ( self )
252
274
}
@@ -266,7 +288,14 @@ impl<'a> LibfuzzerOptionsBuilder<'a> {
266
288
ignore_crashes : self . ignore_crashes ,
267
289
ignore_timeouts : self . ignore_timeouts ,
268
290
ignore_ooms : self . ignore_ooms ,
269
- rss_limit : self . rss_limit ,
291
+ rss_limit : match self . rss_limit . unwrap_or ( 2 << 30 ) {
292
+ 0 => usize:: MAX ,
293
+ value => value,
294
+ } ,
295
+ malloc_limit : match self . malloc_limit . or ( self . rss_limit ) . unwrap_or ( 2 << 30 ) {
296
+ 0 => usize:: MAX ,
297
+ value => value,
298
+ } ,
270
299
unknown : self . unknown . into_iter ( ) . map ( |s| s. to_string ( ) ) . collect ( ) ,
271
300
} )
272
301
}
0 commit comments