@@ -644,6 +644,7 @@ where
644
644
OT : ObserversTuple < S :: Input , S > ,
645
645
S : UsesInput ,
646
646
SP : ShMemProvider ,
647
+ TC : TargetBytesConverter ,
647
648
{
648
649
/// The `target` binary that's going to run.
649
650
pub fn target ( & self ) -> & OsString {
@@ -674,6 +675,112 @@ where
674
675
pub fn coverage_map_size ( & self ) -> Option < usize > {
675
676
self . map_size
676
677
}
678
+
679
+ /// Execute input and increase the execution counter.
680
+ #[ inline]
681
+ fn execute_input ( & mut self , state : & mut S , input : & TC :: Input ) -> Result < ExitKind , Error >
682
+ where
683
+ S : HasExecutions ,
684
+ {
685
+ * state. executions_mut ( ) += 1 ;
686
+
687
+ self . execute_input_uncounted ( input)
688
+ }
689
+
690
+ /// Execute input, but side-step the execution counter.
691
+ #[ inline]
692
+ fn execute_input_uncounted ( & mut self , input : & TC :: Input ) -> Result < ExitKind , Error > {
693
+ let mut exit_kind = ExitKind :: Ok ;
694
+
695
+ let last_run_timed_out = self . forkserver . last_run_timed_out_raw ( ) ;
696
+
697
+ let mut input_bytes = self . target_bytes_converter . to_target_bytes ( input) ;
698
+ let mut input_size = input_bytes. as_slice ( ) . len ( ) ;
699
+ if input_size > self . max_input_size {
700
+ // Truncate like AFL++ does
701
+ input_size = self . max_input_size ;
702
+ } else if input_size < self . min_input_size {
703
+ // Extend like AFL++ does
704
+ input_size = self . min_input_size ;
705
+ let mut input_bytes_copy = Vec :: with_capacity ( input_size) ;
706
+ input_bytes_copy
707
+ . as_slice_mut ( )
708
+ . copy_from_slice ( input_bytes. as_slice ( ) ) ;
709
+ input_bytes = OwnedSlice :: from ( input_bytes_copy) ;
710
+ }
711
+ let input_size_in_bytes = input_size. to_ne_bytes ( ) ;
712
+ if self . uses_shmem_testcase {
713
+ debug_assert ! (
714
+ self . map. is_some( ) ,
715
+ "The uses_shmem_testcase() bool can only exist when a map is set"
716
+ ) ;
717
+ // # Safety
718
+ // Struct can never be created when uses_shmem_testcase is true and map is none.
719
+ let map = unsafe { self . map . as_mut ( ) . unwrap_unchecked ( ) } ;
720
+ // The first four bytes declares the size of the shmem.
721
+ map. as_slice_mut ( ) [ ..SHMEM_FUZZ_HDR_SIZE ]
722
+ . copy_from_slice ( & input_size_in_bytes[ ..SHMEM_FUZZ_HDR_SIZE ] ) ;
723
+ map. as_slice_mut ( ) [ SHMEM_FUZZ_HDR_SIZE ..( SHMEM_FUZZ_HDR_SIZE + input_size) ]
724
+ . copy_from_slice ( & input_bytes. as_slice ( ) [ ..input_size] ) ;
725
+ } else {
726
+ self . input_file
727
+ . write_buf ( & input_bytes. as_slice ( ) [ ..input_size] ) ?;
728
+ }
729
+
730
+ self . forkserver . set_last_run_timed_out ( false ) ;
731
+ if let Err ( err) = self . forkserver . write_ctl ( last_run_timed_out) {
732
+ return Err ( Error :: unknown ( format ! (
733
+ "Unable to request new process from fork server (OOM?): {err:?}"
734
+ ) ) ) ;
735
+ }
736
+
737
+ let pid = self . forkserver . read_st ( ) . map_err ( |err| {
738
+ Error :: unknown ( format ! (
739
+ "Unable to request new process from fork server (OOM?): {err:?}"
740
+ ) )
741
+ } ) ?;
742
+
743
+ if pid <= 0 {
744
+ return Err ( Error :: unknown (
745
+ "Fork server is misbehaving (OOM?)" . to_string ( ) ,
746
+ ) ) ;
747
+ }
748
+
749
+ self . forkserver . set_child_pid ( Pid :: from_raw ( pid) ) ;
750
+
751
+ if let Some ( status) = self . forkserver . read_st_timed ( & self . timeout ) ? {
752
+ self . forkserver . set_status ( status) ;
753
+ let exitcode_is_crash = if let Some ( crash_exitcode) = self . crash_exitcode {
754
+ ( libc:: WEXITSTATUS ( self . forkserver ( ) . status ( ) ) as i8 ) == crash_exitcode
755
+ } else {
756
+ false
757
+ } ;
758
+ if libc:: WIFSIGNALED ( self . forkserver ( ) . status ( ) ) || exitcode_is_crash {
759
+ exit_kind = ExitKind :: Crash ;
760
+ #[ cfg( feature = "regex" ) ]
761
+ if let Some ( asan_observer) = self . observers . get_mut ( & self . asan_obs ) {
762
+ asan_observer. parse_asan_output_from_asan_log_file ( pid) ?;
763
+ }
764
+ }
765
+ } else {
766
+ self . forkserver . set_last_run_timed_out ( true ) ;
767
+
768
+ // We need to kill the child in case he has timed out, or we can't get the correct pid in the next call to self.executor.forkserver_mut().read_st()?
769
+ let _ = kill ( self . forkserver ( ) . child_pid ( ) , self . forkserver . kill_signal ) ;
770
+ if let Err ( err) = self . forkserver . read_st ( ) {
771
+ return Err ( Error :: unknown ( format ! (
772
+ "Could not kill timed-out child: {err:?}"
773
+ ) ) ) ;
774
+ }
775
+ exit_kind = ExitKind :: Timeout ;
776
+ }
777
+
778
+ if !libc:: WIFSTOPPED ( self . forkserver ( ) . status ( ) ) {
779
+ self . forkserver . reset_child_pid ( ) ;
780
+ }
781
+
782
+ Ok ( exit_kind)
783
+ }
677
784
}
678
785
679
786
/// The builder for `ForkserverExecutor`
@@ -1453,98 +1560,7 @@ where
1453
1560
_mgr : & mut EM ,
1454
1561
input : & Self :: Input ,
1455
1562
) -> Result < ExitKind , Error > {
1456
- * state. executions_mut ( ) += 1 ;
1457
-
1458
- let mut exit_kind = ExitKind :: Ok ;
1459
-
1460
- let last_run_timed_out = self . forkserver . last_run_timed_out_raw ( ) ;
1461
-
1462
- let mut input_bytes = self . target_bytes_converter . to_target_bytes ( input) ;
1463
- let mut input_size = input_bytes. as_slice ( ) . len ( ) ;
1464
- if input_size > self . max_input_size {
1465
- // Truncate like AFL++ does
1466
- input_size = self . max_input_size ;
1467
- } else if input_size < self . min_input_size {
1468
- // Extend like AFL++ does
1469
- input_size = self . min_input_size ;
1470
- let mut input_bytes_copy = Vec :: with_capacity ( input_size) ;
1471
- input_bytes_copy
1472
- . as_slice_mut ( )
1473
- . copy_from_slice ( input_bytes. as_slice ( ) ) ;
1474
- input_bytes = OwnedSlice :: from ( input_bytes_copy) ;
1475
- }
1476
- let input_size_in_bytes = input_size. to_ne_bytes ( ) ;
1477
- if self . uses_shmem_testcase {
1478
- debug_assert ! (
1479
- self . map. is_some( ) ,
1480
- "The uses_shmem_testcase() bool can only exist when a map is set"
1481
- ) ;
1482
- // # Safety
1483
- // Struct can never be created when uses_shmem_testcase is true and map is none.
1484
- let map = unsafe { self . map . as_mut ( ) . unwrap_unchecked ( ) } ;
1485
- // The first four bytes declares the size of the shmem.
1486
- map. as_slice_mut ( ) [ ..SHMEM_FUZZ_HDR_SIZE ]
1487
- . copy_from_slice ( & input_size_in_bytes[ ..SHMEM_FUZZ_HDR_SIZE ] ) ;
1488
- map. as_slice_mut ( ) [ SHMEM_FUZZ_HDR_SIZE ..( SHMEM_FUZZ_HDR_SIZE + input_size) ]
1489
- . copy_from_slice ( & input_bytes. as_slice ( ) [ ..input_size] ) ;
1490
- } else {
1491
- self . input_file
1492
- . write_buf ( & input_bytes. as_slice ( ) [ ..input_size] ) ?;
1493
- }
1494
-
1495
- self . forkserver . set_last_run_timed_out ( false ) ;
1496
- if let Err ( err) = self . forkserver . write_ctl ( last_run_timed_out) {
1497
- return Err ( Error :: unknown ( format ! (
1498
- "Unable to request new process from fork server (OOM?): {err:?}"
1499
- ) ) ) ;
1500
- }
1501
-
1502
- let pid = self . forkserver . read_st ( ) . map_err ( |err| {
1503
- Error :: unknown ( format ! (
1504
- "Unable to request new process from fork server (OOM?): {err:?}"
1505
- ) )
1506
- } ) ?;
1507
-
1508
- if pid <= 0 {
1509
- return Err ( Error :: unknown (
1510
- "Fork server is misbehaving (OOM?)" . to_string ( ) ,
1511
- ) ) ;
1512
- }
1513
-
1514
- self . forkserver . set_child_pid ( Pid :: from_raw ( pid) ) ;
1515
-
1516
- if let Some ( status) = self . forkserver . read_st_timed ( & self . timeout ) ? {
1517
- self . forkserver . set_status ( status) ;
1518
- let exitcode_is_crash = if let Some ( crash_exitcode) = self . crash_exitcode {
1519
- ( libc:: WEXITSTATUS ( self . forkserver ( ) . status ( ) ) as i8 ) == crash_exitcode
1520
- } else {
1521
- false
1522
- } ;
1523
- if libc:: WIFSIGNALED ( self . forkserver ( ) . status ( ) ) || exitcode_is_crash {
1524
- exit_kind = ExitKind :: Crash ;
1525
- #[ cfg( feature = "regex" ) ]
1526
- if let Some ( asan_observer) = self . observers . get_mut ( & self . asan_obs ) {
1527
- asan_observer. parse_asan_output_from_asan_log_file ( pid) ?;
1528
- }
1529
- }
1530
- } else {
1531
- self . forkserver . set_last_run_timed_out ( true ) ;
1532
-
1533
- // We need to kill the child in case he has timed out, or we can't get the correct pid in the next call to self.executor.forkserver_mut().read_st()?
1534
- let _ = kill ( self . forkserver ( ) . child_pid ( ) , self . forkserver . kill_signal ) ;
1535
- if let Err ( err) = self . forkserver . read_st ( ) {
1536
- return Err ( Error :: unknown ( format ! (
1537
- "Could not kill timed-out child: {err:?}"
1538
- ) ) ) ;
1539
- }
1540
- exit_kind = ExitKind :: Timeout ;
1541
- }
1542
-
1543
- if !libc:: WIFSTOPPED ( self . forkserver ( ) . status ( ) ) {
1544
- self . forkserver . reset_child_pid ( ) ;
1545
- }
1546
-
1547
- Ok ( exit_kind)
1563
+ self . execute_input ( state, input)
1548
1564
}
1549
1565
}
1550
1566
0 commit comments