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