@@ -79,7 +79,6 @@ pub fn rust_libfuzzer_debug_path() -> &'static Option<String> {
7979}
8080
8181#[ doc( hidden) ]
82- #[ export_name = "LLVMFuzzerInitialize" ]
8382pub fn initialize ( _argc : * const isize , _argv : * const * const * const u8 ) -> isize {
8483 // Registers a panic hook that aborts the process before unwinding.
8584 // It is useful to abort before unwinding so that the fuzzer will then be
@@ -89,10 +88,10 @@ pub fn initialize(_argc: *const isize, _argv: *const *const *const u8) -> isize
8988 // impossible to build code using compiler plugins with this flag.
9089 // We will be able to remove this code when
9190 // https://github.com/rust-lang/cargo/issues/5423 is fixed.
92- let default_hook = :: std:: panic:: take_hook ( ) ;
93- :: std:: panic:: set_hook ( Box :: new ( move |panic_info| {
91+ let default_hook = std:: panic:: take_hook ( ) ;
92+ std:: panic:: set_hook ( Box :: new ( move |panic_info| {
9493 default_hook ( panic_info) ;
95- :: std:: process:: abort ( ) ;
94+ std:: process:: abort ( ) ;
9695 } ) ) ;
9796 0
9897}
@@ -196,11 +195,48 @@ pub fn initialize(_argc: *const isize, _argv: *const *const *const u8) -> isize
196195///
197196/// You can also enable the `arbitrary` crate's custom derive via this crate's
198197/// `"arbitrary-derive"` cargo feature.
198+ ///
199+ /// ## Init Code
200+ ///
201+ /// Init code to the fuzz target by using the `init` keyword. This is called once before the fuzzer starts.
202+ /// Supports short |input| or |input: <type>| syntax.
203+ ///
204+ /// ```no_run
205+ /// #![no_main]
206+ ///
207+ /// use libfuzzer_sys::fuzz_target;
208+ /// use std::collections::HashSet;
209+ /// use std::sync::OnceLock;
210+ ///
211+ /// static DICTIONARY: OnceLock<HashSet<String>> = OnceLock::new();
212+ ///
213+ /// fuzz_target!(
214+ /// init: {
215+ /// let read_dictionary = |_| unimplemented!();
216+ /// let dictionary = read_dictionary("/usr/share/dict/words");
217+ /// DICTIONARY.set(dictionary).unwrap();
218+ /// },
219+ /// |input| {
220+ /// // Use the initialized `DICTIONARY` here...
221+ /// }
222+ /// );
223+ /// ```
224+ ///
199225#[ macro_export]
200226macro_rules! fuzz_target {
201- ( |$bytes: ident| $body: expr) => {
227+ ( init : $init : expr , |$bytes: ident| $body: expr) => {
202228 const _: ( ) = {
203- /// Auto-generated function
229+ /// Auto-generated functions
230+ /// LLVMFuzzerInitialize is called once before the fuzzer starts.
231+ #[ no_mangle]
232+ pub extern "C" fn LLVMFuzzerInitialize ( _argc: * const isize , _argv: * const * const * const u8 ) -> isize {
233+ $crate:: initialize( _argc, _argv) ;
234+
235+ // Supplied init code
236+ $init;
237+ 0
238+ }
239+
204240 #[ no_mangle]
205241 pub extern "C" fn rust_fuzzer_test_input( bytes: & [ u8 ] ) -> i32 {
206242 // When `RUST_LIBFUZZER_DEBUG_PATH` is set, write the debug
@@ -240,17 +276,47 @@ macro_rules! fuzz_target {
240276 } ;
241277 } ;
242278
279+ ( |$bytes: ident| $body: expr) => {
280+ $crate:: fuzz_target!( |$bytes: & [ u8 ] | $body) ;
281+ } ;
282+
243283 ( |$data: ident: & [ u8 ] | $body: expr) => {
244- $crate:: fuzz_target!( |$data| $body) ;
284+ $crate:: fuzz_target!( init : ( ) , |$data| $body) ;
245285 } ;
246286
247287 ( |$data: ident: $dty: ty| $body: expr) => {
248- $crate:: fuzz_target!( |$data: $dty| -> ( ) { $body } ) ;
288+ $crate:: fuzz_target!( init : ( ) , |$data: $dty| -> ( ) { $body } ) ;
249289 } ;
250290
251291 ( |$data: ident: $dty: ty| -> $rty: ty $body: block) => {
292+ $crate:: fuzz_target!( init: ( ) , |$data: $dty| -> $rty { $body } ) ;
293+ } ;
294+
295+ ( init: $init: expr, |$data: ident: & [ u8 ] | $body: expr) => {
296+ $crate:: fuzz_target!( init: $init, |$data| $body) ;
297+ } ;
298+
299+ ( init: $init: expr, |$bytes: ident| $body: expr) => {
300+ $crate:: fuzz_target!( init: $init, |$bytes: & [ u8 ] | $body) ;
301+ } ;
302+
303+ ( init: $init: expr, |$data: ident: $dty: ty| $body: expr) => {
304+ $crate:: fuzz_target!( init: $init, |$data: $dty| -> ( ) { $body } ) ;
305+ } ;
306+
307+ ( init: $init: expr, |$data: ident: $dty: ty| -> $rty: ty $body: block) => {
252308 const _: ( ) = {
253- /// Auto-generated function
309+ /// Auto-generated functions
310+ /// LLVMFuzzerInitialize is called once before the fuzzer starts.
311+ #[ no_mangle]
312+ pub extern "C" fn LLVMFuzzerInitialize ( _argc: * const isize , _argv: * const * const * const u8 ) -> isize {
313+ $crate:: initialize( _argc, _argv) ;
314+
315+ // Supplied init code
316+ $init;
317+ 0
318+ }
319+
254320 #[ no_mangle]
255321 pub extern "C" fn rust_fuzzer_test_input( bytes: & [ u8 ] ) -> i32 {
256322 use $crate:: arbitrary:: { Arbitrary , Unstructured } ;
@@ -293,7 +359,6 @@ macro_rules! fuzz_target {
293359 let result = :: libfuzzer_sys:: Corpus :: from( __libfuzzer_sys_run( data) ) ;
294360 result. to_libfuzzer_code( )
295361 }
296-
297362 // See above for why this is split to a separate function.
298363 #[ inline( never) ]
299364 fn __libfuzzer_sys_run( $data: $dty) -> $rty {
0 commit comments