@@ -245,14 +245,64 @@ macro_rules! fuzz_target {
245
245
} ;
246
246
} ;
247
247
248
+ ( |mut $bytes: ident| $body: expr) => {
249
+ const _: ( ) = {
250
+ /// Auto-generated function
251
+ #[ no_mangle]
252
+ pub extern "C" fn rust_fuzzer_test_input( bytes: & [ u8 ] ) -> i32 {
253
+ // When `RUST_LIBFUZZER_DEBUG_PATH` is set, write the debug
254
+ // formatting of the input to that file. This is only intended for
255
+ // `cargo fuzz`'s use!
256
+
257
+ // `RUST_LIBFUZZER_DEBUG_PATH` is set in initialization.
258
+ if let Some ( path) = $crate:: RUST_LIBFUZZER_DEBUG_PATH . get( ) {
259
+ use std:: io:: Write ;
260
+ let mut file = std:: fs:: File :: create( path)
261
+ . expect( "failed to create `RUST_LIBFUZZER_DEBUG_PATH` file" ) ;
262
+ writeln!( & mut file, "{:?}" , bytes)
263
+ . expect( "failed to write to `RUST_LIBFUZZER_DEBUG_PATH` file" ) ;
264
+ return 0 ;
265
+ }
266
+
267
+ __libfuzzer_sys_run( bytes) ;
268
+ 0
269
+ }
270
+
271
+ // Split out the actual fuzzer into a separate function which is
272
+ // tagged as never being inlined. This ensures that if the fuzzer
273
+ // panics there's at least one stack frame which is named uniquely
274
+ // according to this specific fuzzer that this is embedded within.
275
+ //
276
+ // Systems like oss-fuzz try to deduplicate crashes and without this
277
+ // panics in separate fuzzers can accidentally appear the same
278
+ // because each fuzzer will have a function called
279
+ // `rust_fuzzer_test_input`. By using a normal Rust function here
280
+ // it's named something like `the_fuzzer_name::_::__libfuzzer_sys_run` which should
281
+ // ideally help prevent oss-fuzz from deduplicate fuzz bugs across
282
+ // distinct targets accidentally.
283
+ #[ inline( never) ]
284
+ fn __libfuzzer_sys_run( mut $bytes: & [ u8 ] ) {
285
+ $body
286
+ }
287
+ } ;
288
+ } ;
289
+
248
290
( |$data: ident: & [ u8 ] | $body: expr) => {
249
291
$crate:: fuzz_target!( |$data| $body) ;
250
292
} ;
251
293
294
+ ( |mut $data: ident: & [ u8 ] | $body: expr) => {
295
+ $crate:: fuzz_target!( |mut $data| $body) ;
296
+ } ;
297
+
252
298
( |$data: ident: $dty: ty| $body: expr) => {
253
299
$crate:: fuzz_target!( |$data: $dty| -> ( ) { $body } ) ;
254
300
} ;
255
301
302
+ ( |mut $data: ident: $dty: ty| $body: expr) => {
303
+ $crate:: fuzz_target!( |mut $data: $dty| -> ( ) { $body } ) ;
304
+ } ;
305
+
256
306
( |$data: ident: $dty: ty| -> $rty: ty $body: block) => {
257
307
const _: ( ) = {
258
308
/// Auto-generated function
@@ -306,6 +356,60 @@ macro_rules! fuzz_target {
306
356
}
307
357
} ;
308
358
} ;
359
+
360
+ ( |mut $data: ident: $dty: ty| -> $rty: ty $body: block) => {
361
+ const _: ( ) = {
362
+ /// Auto-generated function
363
+ #[ no_mangle]
364
+ pub extern "C" fn rust_fuzzer_test_input( bytes: & [ u8 ] ) -> i32 {
365
+ use $crate:: arbitrary:: { Arbitrary , Unstructured } ;
366
+
367
+ // Early exit if we don't have enough bytes for the `Arbitrary`
368
+ // implementation. This helps the fuzzer avoid exploring all the
369
+ // different not-enough-input-bytes paths inside the `Arbitrary`
370
+ // implementation. Additionally, it exits faster, letting the fuzzer
371
+ // get to longer inputs that actually lead to interesting executions
372
+ // quicker.
373
+ if bytes. len( ) < <$dty as Arbitrary >:: size_hint( 0 ) . 0 {
374
+ return -1 ;
375
+ }
376
+
377
+ let mut u = Unstructured :: new( bytes) ;
378
+ let data = <$dty as Arbitrary >:: arbitrary_take_rest( u) ;
379
+
380
+ // When `RUST_LIBFUZZER_DEBUG_PATH` is set, write the debug
381
+ // formatting of the input to that file. This is only intended for
382
+ // `cargo fuzz`'s use!
383
+
384
+ // `RUST_LIBFUZZER_DEBUG_PATH` is set in initialization.
385
+ if let Some ( path) = $crate:: RUST_LIBFUZZER_DEBUG_PATH . get( ) {
386
+ use std:: io:: Write ;
387
+ let mut file = std:: fs:: File :: create( path)
388
+ . expect( "failed to create `RUST_LIBFUZZER_DEBUG_PATH` file" ) ;
389
+ ( match data {
390
+ Ok ( data) => writeln!( & mut file, "{:#?}" , data) ,
391
+ Err ( err) => writeln!( & mut file, "Arbitrary Error: {}" , err) ,
392
+ } )
393
+ . expect( "failed to write to `RUST_LIBFUZZER_DEBUG_PATH` file" ) ;
394
+ return -1 ;
395
+ }
396
+
397
+ let data = match data {
398
+ Ok ( d) => d,
399
+ Err ( _) => return -1 ,
400
+ } ;
401
+
402
+ let result = :: libfuzzer_sys:: Corpus :: from( __libfuzzer_sys_run( data) ) ;
403
+ result. to_libfuzzer_code( )
404
+ }
405
+
406
+ // See above for why this is split to a separate function.
407
+ #[ inline( never) ]
408
+ fn __libfuzzer_sys_run( mut $data: $dty) -> $rty {
409
+ $body
410
+ }
411
+ } ;
412
+ } ;
309
413
}
310
414
311
415
/// Define a custom mutator.
0 commit comments