|
1 | 1 | //! Map feedback, maximizing or minimizing maps, for example the afl-style map observer.
|
2 | 2 |
|
3 | 3 | use alloc::{borrow::Cow, vec::Vec};
|
4 |
| -#[rustversion::nightly] |
5 |
| -use core::simd::prelude::SimdOrd; |
6 | 4 | use core::{
|
7 | 5 | fmt::Debug,
|
8 | 6 | marker::PhantomData,
|
9 | 7 | ops::{BitAnd, BitOr, Deref, DerefMut},
|
10 | 8 | };
|
11 | 9 |
|
12 | 10 | #[rustversion::nightly]
|
13 |
| -use libafl_bolts::AsSlice; |
| 11 | +use libafl_bolts::simd::std_covmap_is_interesting; |
14 | 12 | use libafl_bolts::{
|
15 |
| - AsIter, HasRefCnt, Named, |
| 13 | + AsIter, AsSlice, HasRefCnt, Named, |
16 | 14 | tuples::{Handle, Handled, MatchName, MatchNameRef},
|
17 | 15 | };
|
18 | 16 | use num_traits::PrimInt;
|
@@ -548,7 +546,7 @@ where
|
548 | 546 | observers: &OT,
|
549 | 547 | _exit_kind: &ExitKind,
|
550 | 548 | ) -> Result<bool, Error> {
|
551 |
| - Ok(self.is_interesting_u8_simd_optimized(state, observers)) |
| 549 | + Ok(self.is_interesting_u8_simd_optimized(state, observers, std_covmap_is_interesting)) |
552 | 550 | }
|
553 | 551 | }
|
554 | 552 |
|
@@ -604,117 +602,6 @@ where
|
604 | 602 | }
|
605 | 603 | }
|
606 | 604 |
|
607 |
| -/// Specialize for the common coverage map size, maximization of u8s |
608 |
| -#[rustversion::nightly] |
609 |
| -impl<C, O> MapFeedback<C, DifferentIsNovel, O, MaxReducer> |
610 |
| -where |
611 |
| - O: MapObserver<Entry = u8> + for<'a> AsSlice<'a, Entry = u8> + for<'a> AsIter<'a, Item = u8>, |
612 |
| - C: CanTrack + AsRef<O>, |
613 |
| -{ |
614 |
| - fn is_interesting_u8_simd_optimized<S, OT>(&mut self, state: &mut S, observers: &OT) -> bool |
615 |
| - where |
616 |
| - S: HasNamedMetadata, |
617 |
| - OT: MatchName, |
618 |
| - { |
619 |
| - // 128 bits vectors |
620 |
| - type VectorType = core::simd::u8x16; |
621 |
| - |
622 |
| - let mut interesting = false; |
623 |
| - // TODO Replace with match_name_type when stable |
624 |
| - let observer = observers.get(&self.map_ref).expect("MapObserver not found. This is likely because you entered the crash handler with the wrong executor/observer").as_ref(); |
625 |
| - |
626 |
| - let map_state = state |
627 |
| - .named_metadata_map_mut() |
628 |
| - .get_mut::<MapFeedbackMetadata<u8>>(&self.name) |
629 |
| - .unwrap(); |
630 |
| - let size = observer.usable_count(); |
631 |
| - let len = observer.len(); |
632 |
| - if map_state.history_map.len() < len { |
633 |
| - map_state.history_map.resize(len, u8::default()); |
634 |
| - } |
635 |
| - |
636 |
| - let map = observer.as_slice(); |
637 |
| - debug_assert!(map.len() >= size); |
638 |
| - |
639 |
| - let history_map = map_state.history_map.as_slice(); |
640 |
| - |
641 |
| - // Non vector implementation for reference |
642 |
| - /*for (i, history) in history_map.iter_mut().enumerate() { |
643 |
| - let item = map[i]; |
644 |
| - let reduced = MaxReducer::reduce(*history, item); |
645 |
| - if DifferentIsNovel::is_novel(*history, reduced) { |
646 |
| - *history = reduced; |
647 |
| - interesting = true; |
648 |
| - if self.novelties.is_some() { |
649 |
| - self.novelties.as_mut().unwrap().push(i); |
650 |
| - } |
651 |
| - } |
652 |
| - }*/ |
653 |
| - |
654 |
| - let steps = size / VectorType::LEN; |
655 |
| - let left = size % VectorType::LEN; |
656 |
| - |
657 |
| - if let Some(novelties) = self.novelties.as_mut() { |
658 |
| - novelties.clear(); |
659 |
| - for step in 0..steps { |
660 |
| - let i = step * VectorType::LEN; |
661 |
| - let history = VectorType::from_slice(&history_map[i..]); |
662 |
| - let items = VectorType::from_slice(&map[i..]); |
663 |
| - |
664 |
| - if items.simd_max(history) != history { |
665 |
| - interesting = true; |
666 |
| - unsafe { |
667 |
| - for j in i..(i + VectorType::LEN) { |
668 |
| - let item = *map.get_unchecked(j); |
669 |
| - if item > *history_map.get_unchecked(j) { |
670 |
| - novelties.push(j); |
671 |
| - } |
672 |
| - } |
673 |
| - } |
674 |
| - } |
675 |
| - } |
676 |
| - |
677 |
| - for j in (size - left)..size { |
678 |
| - unsafe { |
679 |
| - let item = *map.get_unchecked(j); |
680 |
| - if item > *history_map.get_unchecked(j) { |
681 |
| - interesting = true; |
682 |
| - novelties.push(j); |
683 |
| - } |
684 |
| - } |
685 |
| - } |
686 |
| - } else { |
687 |
| - for step in 0..steps { |
688 |
| - let i = step * VectorType::LEN; |
689 |
| - let history = VectorType::from_slice(&history_map[i..]); |
690 |
| - let items = VectorType::from_slice(&map[i..]); |
691 |
| - |
692 |
| - if items.simd_max(history) != history { |
693 |
| - interesting = true; |
694 |
| - break; |
695 |
| - } |
696 |
| - } |
697 |
| - |
698 |
| - if !interesting { |
699 |
| - for j in (size - left)..size { |
700 |
| - unsafe { |
701 |
| - let item = *map.get_unchecked(j); |
702 |
| - if item > *history_map.get_unchecked(j) { |
703 |
| - interesting = true; |
704 |
| - break; |
705 |
| - } |
706 |
| - } |
707 |
| - } |
708 |
| - } |
709 |
| - } |
710 |
| - #[cfg(feature = "track_hit_feedbacks")] |
711 |
| - { |
712 |
| - self.last_result = Some(interesting); |
713 |
| - } |
714 |
| - interesting |
715 |
| - } |
716 |
| -} |
717 |
| - |
718 | 605 | impl<C, N, O, R> HasObserverHandle for MapFeedback<C, N, O, R> {
|
719 | 606 | type Observer = C;
|
720 | 607 |
|
@@ -789,6 +676,67 @@ where
|
789 | 676 | }
|
790 | 677 | }
|
791 | 678 |
|
| 679 | +/// Specialize for the common coverage map size, maximization of u8s |
| 680 | +impl<C, O> MapFeedback<C, DifferentIsNovel, O, MaxReducer> |
| 681 | +where |
| 682 | + O: MapObserver<Entry = u8> + for<'a> AsSlice<'a, Entry = u8> + for<'a> AsIter<'a, Item = u8>, |
| 683 | + C: CanTrack + AsRef<O>, |
| 684 | +{ |
| 685 | + #[allow(dead_code)] // this is true on stable wihout "stable_simd" |
| 686 | + pub(crate) fn is_interesting_u8_simd_optimized<S, OT, F>( |
| 687 | + &mut self, |
| 688 | + state: &mut S, |
| 689 | + observers: &OT, |
| 690 | + simd: F, |
| 691 | + ) -> bool |
| 692 | + where |
| 693 | + S: HasNamedMetadata, |
| 694 | + OT: MatchName, |
| 695 | + F: FnOnce(&[u8], &[u8], bool) -> (bool, Vec<usize>), |
| 696 | + { |
| 697 | + // TODO Replace with match_name_type when stable |
| 698 | + let observer = observers.get(&self.map_ref).expect("MapObserver not found. This is likely because you entered the crash handler with the wrong executor/observer").as_ref(); |
| 699 | + |
| 700 | + let map_state = state |
| 701 | + .named_metadata_map_mut() |
| 702 | + .get_mut::<MapFeedbackMetadata<u8>>(&self.name) |
| 703 | + .unwrap(); |
| 704 | + let size = observer.usable_count(); |
| 705 | + let len = observer.len(); |
| 706 | + if map_state.history_map.len() < len { |
| 707 | + map_state.history_map.resize(len, u8::default()); |
| 708 | + } |
| 709 | + |
| 710 | + let map = observer.as_slice(); |
| 711 | + debug_assert!(map.len() >= size); |
| 712 | + |
| 713 | + let history_map = map_state.history_map.as_slice(); |
| 714 | + |
| 715 | + // Non vector implementation for reference |
| 716 | + /*for (i, history) in history_map.iter_mut().enumerate() { |
| 717 | + let item = map[i]; |
| 718 | + let reduced = MaxReducer::reduce(*history, item); |
| 719 | + if DifferentIsNovel::is_novel(*history, reduced) { |
| 720 | + *history = reduced; |
| 721 | + interesting = true; |
| 722 | + if self.novelties.is_some() { |
| 723 | + self.novelties.as_mut().unwrap().push(i); |
| 724 | + } |
| 725 | + } |
| 726 | + }*/ |
| 727 | + |
| 728 | + let (interesting, novelties) = simd(history_map, &map, self.novelties.is_some()); |
| 729 | + if let Some(nov) = self.novelties.as_mut() { |
| 730 | + *nov = novelties; |
| 731 | + } |
| 732 | + #[cfg(feature = "track_hit_feedbacks")] |
| 733 | + { |
| 734 | + self.last_result = Some(interesting); |
| 735 | + } |
| 736 | + interesting |
| 737 | + } |
| 738 | +} |
| 739 | + |
792 | 740 | #[cfg(test)]
|
793 | 741 | mod tests {
|
794 | 742 | use crate::feedbacks::{AllIsNovel, IsNovel, NextPow2IsNovel};
|
|
0 commit comments