11use core:: ffi:: c_int;
22#[ cfg( unix) ]
3- use std:: io:: { Write , stderr, stdout} ;
4- use std:: { fmt:: Debug , fs:: File , net:: TcpListener , os:: fd:: AsRawFd , str:: FromStr } ;
3+ use std:: {
4+ fmt:: Debug ,
5+ fs:: File ,
6+ io:: { Write , stderr, stdout} ,
7+ net:: TcpListener ,
8+ os:: fd:: AsRawFd ,
9+ str:: FromStr ,
10+ } ;
511
12+ #[ cfg( feature = "tui_monitor" ) ]
13+ use libafl:: monitors:: tui:: TuiMonitor ;
614use libafl:: {
715 Error , Fuzzer , HasMetadata ,
816 corpus:: Corpus ,
9- events:: {
10- EventConfig , EventReceiver , ProgressReporter , SimpleEventManager ,
11- SimpleRestartingEventManager , launcher:: Launcher ,
12- } ,
17+ events:: { EventReceiver , ProgressReporter , SimpleEventManager } ,
1318 executors:: ExitKind ,
14- monitors:: { Monitor , MultiMonitor , tui :: TuiMonitor } ,
19+ monitors:: MultiMonitor ,
1520 stages:: StagesTuple ,
1621 state:: { HasCurrentStageId , HasExecutions , HasLastReportTime , HasSolutions , Stoppable } ,
1722} ;
23+ #[ cfg( unix) ]
24+ use libafl:: {
25+ events:: { EventConfig , SimpleRestartingEventManager , launcher:: Launcher } ,
26+ monitors:: Monitor ,
27+ } ;
28+ #[ cfg( unix) ]
1829use libafl_bolts:: {
1930 core_affinity:: Cores ,
2031 shmem:: { ShMemProvider , StdShMemProvider } ,
2132} ;
2233
2334use crate :: { feedbacks:: LibfuzzerCrashCauseMetadata , fuzz_with, options:: LibfuzzerOptions } ;
2435
36+ #[ cfg( unix) ]
2537fn destroy_output_fds ( options : & LibfuzzerOptions ) {
26- #[ cfg( unix) ]
27- {
28- use libafl_bolts:: os:: { dup2, null_fd} ;
38+ use libafl_bolts:: os:: { dup2, null_fd} ;
2939
30- let null_fd = null_fd ( ) . unwrap ( ) ;
31- let stdout_fd = stdout ( ) . as_raw_fd ( ) ;
32- let stderr_fd = stderr ( ) . as_raw_fd ( ) ;
40+ let null_fd = null_fd ( ) . unwrap ( ) ;
41+ let stdout_fd = stdout ( ) . as_raw_fd ( ) ;
42+ let stderr_fd = stderr ( ) . as_raw_fd ( ) ;
3343
34- if options. tui ( ) {
44+ #[ cfg( feature = "tui_monitor" ) ]
45+ if options. tui ( ) {
46+ dup2 ( null_fd, stdout_fd) . unwrap ( ) ;
47+ dup2 ( null_fd, stderr_fd) . unwrap ( ) ;
48+ return ;
49+ }
50+
51+ if options. close_fd_mask ( ) != 0 {
52+ if options. close_fd_mask ( ) & u8:: try_from ( stderr_fd) . unwrap ( ) != 0 {
3553 dup2 ( null_fd, stdout_fd) . unwrap ( ) ;
54+ }
55+ if options. close_fd_mask ( ) & u8:: try_from ( stderr_fd) . unwrap ( ) != 0 {
3656 dup2 ( null_fd, stderr_fd) . unwrap ( ) ;
37- } else if options. close_fd_mask ( ) != 0 {
38- if options. close_fd_mask ( ) & u8:: try_from ( stderr_fd) . unwrap ( ) != 0 {
39- dup2 ( null_fd, stdout_fd) . unwrap ( ) ;
40- }
41- if options. close_fd_mask ( ) & u8:: try_from ( stderr_fd) . unwrap ( ) != 0 {
42- dup2 ( null_fd, stderr_fd) . unwrap ( ) ;
43- }
4457 }
4558 }
4659}
@@ -87,10 +100,17 @@ where
87100 return Err ( Error :: shutting_down ( ) ) ;
88101 }
89102 }
90- fuzzer. fuzz_loop ( stages, executor, state, mgr) ?;
103+ if options. runs ( ) == 0 {
104+ fuzzer. fuzz_loop ( stages, executor, state, mgr) ?;
105+ } else {
106+ for _ in 0 ..options. runs ( ) {
107+ fuzzer. fuzz_one ( stages, executor, state, mgr) ?;
108+ }
109+ }
91110 Ok ( ( ) )
92111}
93112
113+ #[ cfg( unix) ]
94114fn fuzz_single_forking < M > (
95115 options : & LibfuzzerOptions ,
96116 harness : & extern "C" fn ( * const u8 , usize ) -> c_int ,
@@ -121,9 +141,7 @@ where
121141 } )
122142}
123143
124- /// Communicate the selected port to subprocesses
125- const PORT_PROVIDER_VAR : & str = "_LIBAFL_LIBFUZZER_FORK_PORT" ;
126-
144+ #[ cfg( unix) ]
127145fn fuzz_many_forking < M > (
128146 options : & LibfuzzerOptions ,
129147 harness : & extern "C" fn ( * const u8 , usize ) -> c_int ,
@@ -134,6 +152,9 @@ fn fuzz_many_forking<M>(
134152where
135153 M : Monitor + Clone + Debug + ' static ,
136154{
155+ // Communicate the selected port to subprocesses
156+ const PORT_PROVIDER_VAR : & str = "_LIBAFL_LIBFUZZER_FORK_PORT" ;
157+
137158 destroy_output_fds ( options) ;
138159 let broker_port = std:: env:: var ( PORT_PROVIDER_VAR )
139160 . map_err ( Error :: from)
@@ -194,35 +215,47 @@ pub fn fuzz(
194215 options : & LibfuzzerOptions ,
195216 harness : & extern "C" fn ( * const u8 , usize ) -> c_int ,
196217) -> Result < ( ) , Error > {
218+ #[ cfg( unix) ]
197219 if let Some ( forks) = options. forks ( ) {
198220 let shmem_provider = StdShMemProvider :: new ( ) . expect ( "Failed to init shared memory" ) ;
221+
222+ #[ cfg( feature = "tui_monitor" ) ]
199223 if options. tui ( ) {
200224 let monitor = TuiMonitor :: builder ( )
201225 . title ( options. fuzzer_name ( ) )
202226 . enhanced_graphics ( true )
203227 . build ( ) ;
204- fuzz_many_forking ( options, harness, shmem_provider, forks, monitor)
205- } else if forks == 1 {
206- let monitor = MultiMonitor :: new ( create_monitor_closure ( ) ) ;
207- fuzz_single_forking ( options, harness, shmem_provider, monitor)
208- } else {
209- let monitor = MultiMonitor :: new ( create_monitor_closure ( ) ) ;
210- fuzz_many_forking ( options, harness, shmem_provider, forks, monitor)
228+ return fuzz_many_forking ( options, harness, shmem_provider, forks, monitor) ;
211229 }
212- } else if options. tui ( ) {
230+
231+ // Non-TUI path or when tui_monitor feature is disabled
232+ let monitor = MultiMonitor :: new ( create_monitor_closure ( ) ) ;
233+
234+ if forks == 1 {
235+ return fuzz_single_forking ( options, harness, shmem_provider, monitor) ;
236+ }
237+
238+ return fuzz_many_forking ( options, harness, shmem_provider, forks, monitor) ;
239+ }
240+
241+ #[ cfg( feature = "tui_monitor" ) ]
242+ if options. tui ( ) {
213243 // if the user specifies TUI, we assume they want to fork; it would not be possible to use
214244 // TUI safely otherwise
215245 let shmem_provider = StdShMemProvider :: new ( ) . expect ( "Failed to init shared memory" ) ;
216246 let monitor = TuiMonitor :: builder ( )
217247 . title ( options. fuzzer_name ( ) )
218248 . enhanced_graphics ( true )
219249 . build ( ) ;
220- fuzz_many_forking ( options, harness, shmem_provider, 1 , monitor)
221- } else {
222- destroy_output_fds ( options) ;
223- fuzz_with ! ( options, harness, do_fuzz, |fuzz_single| {
224- let mgr = SimpleEventManager :: new( MultiMonitor :: new( create_monitor_closure( ) ) ) ;
225- crate :: start_fuzzing_single( fuzz_single, None , mgr)
226- } )
250+ return fuzz_many_forking ( options, harness, shmem_provider, 1 , monitor) ;
227251 }
252+
253+ // Default path when no forks or TUI are specified, or when tui_monitor feature is disabled
254+ #[ cfg( unix) ]
255+ destroy_output_fds ( options) ;
256+
257+ fuzz_with ! ( options, harness, do_fuzz, |fuzz_single| {
258+ let mgr = SimpleEventManager :: new( MultiMonitor :: new( create_monitor_closure( ) ) ) ;
259+ crate :: start_fuzzing_single( fuzz_single, None , mgr)
260+ } )
228261}
0 commit comments