@@ -8,6 +8,7 @@ use std::fs;
88use std:: io:: IsTerminal ;
99use std:: path:: PathBuf ;
1010use std:: rc:: Rc ;
11+ use std:: slice;
1112use std:: time:: { Duration , Instant } ;
1213
1314use libafl:: {
@@ -26,7 +27,9 @@ use libafl::{
2627 havoc_mutations:: havoc_mutations, scheduled:: HavocScheduledMutator , tokens_mutations,
2728 I2SRandReplace , Tokens ,
2829 } ,
29- observers:: { CanTrack , HitcountsMapObserver , StdMapObserver } ,
30+ observers:: {
31+ CanTrack , HitcountsMapObserver , StdMapObserver , VariableMapObserver ,
32+ } ,
3033 schedulers:: {
3134 powersched:: PowerSchedule , IndexesLenTimeMinimizerScheduler , PowerQueueScheduler ,
3235 } ,
@@ -82,7 +85,8 @@ pub struct JazzerLibAflRuntimeOptions {
8285#[ repr( C ) ]
8386pub struct JazzerLibAflRuntimeSharedMaps {
8487 pub edges : * mut u8 ,
85- pub edges_len : usize ,
88+ pub edges_capacity : usize ,
89+ pub edges_size : * mut usize ,
8690 pub cmp : * mut u8 ,
8791 pub cmp_len : usize ,
8892 pub compare_log : * mut JazzerLibAflCompareLog ,
@@ -619,23 +623,40 @@ fn clear_finding_info(ptr: *mut JazzerLibAflFindingInfo) {
619623 }
620624}
621625
626+ fn edge_map_len ( maps : & JazzerLibAflRuntimeSharedMaps ) -> usize {
627+ if maps. edges_size . is_null ( ) {
628+ 0
629+ } else {
630+ unsafe { ( * maps. edges_size ) . min ( maps. edges_capacity ) }
631+ }
632+ }
633+
634+ fn has_non_zero_coverage ( ptr : * mut u8 , len : usize ) -> bool {
635+ if ptr. is_null ( ) || len == 0 {
636+ return false ;
637+ }
638+
639+ unsafe { slice:: from_raw_parts ( ptr, len) . iter ( ) . any ( |slot| * slot != 0 ) }
640+ }
641+
622642fn ensure_non_empty_edge_map ( ptr : * mut u8 , len : usize ) -> bool {
643+ if has_non_zero_coverage ( ptr, len) {
644+ return false ;
645+ }
646+
623647 if ptr. is_null ( ) || len == 0 {
624648 return false ;
625649 }
626650
627651 unsafe {
628- let map = std:: slice:: from_raw_parts_mut ( ptr, len) ;
629- if map. iter ( ) . all ( |slot| * slot == 0 ) {
630- // Power scheduling rejects corpus entries that never hit any edge.
631- // Preserve the old behavior for uninstrumented callbacks by marking
632- // one synthetic edge only when the target left the map untouched.
633- map[ 0 ] = 1 ;
634- return true ;
635- }
652+ let map = slice:: from_raw_parts_mut ( ptr, len) ;
653+ // Power scheduling rejects corpus entries that never hit any edge.
654+ // Preserve the old behavior for uninstrumented callbacks by marking
655+ // one synthetic edge only when the target left every coverage region untouched.
656+ map[ 0 ] = 1 ;
636657 }
637658
638- false
659+ true
639660}
640661
641662unsafe fn parse_corpus_directories ( options : & JazzerLibAflRuntimeOptions ) -> Option < Vec < PathBuf > > {
@@ -713,7 +734,8 @@ pub unsafe extern "C" fn jazzer_libafl_runtime_run(
713734 let options = & * options;
714735 let maps = & * maps;
715736 if maps. edges . is_null ( )
716- || maps. edges_len == 0
737+ || maps. edges_capacity == 0
738+ || maps. edges_size . is_null ( )
717739 || maps. cmp . is_null ( )
718740 || maps. cmp_len == 0
719741 || maps. compare_log . is_null ( )
@@ -749,11 +771,14 @@ pub unsafe extern "C" fn jazzer_libafl_runtime_run(
749771 let ( monitor, monitor_state) = LibAflMonitor :: new ( maps. finding_info ) ;
750772 let mut mgr = SimpleEventManager :: new ( monitor) ;
751773
752- let edges_observer = HitcountsMapObserver :: new ( StdMapObserver :: from_mut_ptr (
753- "edges" ,
754- maps. edges ,
755- maps. edges_len ,
756- ) )
774+ let edges_observer = HitcountsMapObserver :: new (
775+ VariableMapObserver :: from_mut_ptr (
776+ "edges" ,
777+ maps. edges ,
778+ maps. edges_capacity ,
779+ maps. edges_size ,
780+ ) ,
781+ )
757782 . track_indices ( ) ;
758783 let cmp_observer =
759784 HitcountsMapObserver :: new ( StdMapObserver :: from_mut_ptr ( "cmp" , maps. cmp , maps. cmp_len ) ) ;
@@ -814,7 +839,7 @@ pub unsafe extern "C" fn jazzer_libafl_runtime_run(
814839 let timeout_found = Cell :: new ( false ) ;
815840
816841 let mut harness = |input : & BytesInput | {
817- clear_shared_map ( maps. edges , maps. edges_len ) ;
842+ clear_shared_map ( maps. edges , edge_map_len ( maps) ) ;
818843 clear_shared_map ( maps. cmp , maps. cmp_len ) ;
819844 clear_compare_log ( maps. compare_log ) ;
820845 clear_finding_info ( maps. finding_info ) ;
@@ -823,7 +848,10 @@ pub unsafe extern "C" fn jazzer_libafl_runtime_run(
823848 let bytes = bytes. as_slice ( ) ;
824849 let size = bytes. len ( ) . min ( options. max_len ) ;
825850 let status = unsafe { execute_one ( user_data, bytes. as_ptr ( ) , size) } ;
826- let synthetic_edges = ensure_non_empty_edge_map ( maps. edges , maps. edges_len ) ;
851+ let synthetic_edges = ensure_non_empty_edge_map (
852+ maps. edges ,
853+ edge_map_len ( maps) ,
854+ ) ;
827855 monitor_state. borrow_mut ( ) . last_edges_are_synthetic = synthetic_edges;
828856 match status {
829857 EXECUTION_CONTINUE => ExitKind :: Ok ,
0 commit comments