From 2ea81325eb81c4bb0c03161b3d6cd83d112420f3 Mon Sep 17 00:00:00 2001 From: Valentin Huber Date: Thu, 12 Dec 2024 16:12:06 +0100 Subject: [PATCH] Fixes according to code review --- libafl/src/inputs/bytes.rs | 4 +- libafl/src/inputs/mod.rs | 6 +- libafl/src/inputs/{wrapping.rs => value.rs} | 158 ++++++++------------ libafl/src/mutators/numeric.rs | 39 +++-- 4 files changed, 87 insertions(+), 120 deletions(-) rename libafl/src/inputs/{wrapping.rs => value.rs} (62%) diff --git a/libafl/src/inputs/bytes.rs b/libafl/src/inputs/bytes.rs index dd7eeaee37..d71bc7c22e 100644 --- a/libafl/src/inputs/bytes.rs +++ b/libafl/src/inputs/bytes.rs @@ -10,11 +10,11 @@ use core::cell::RefCell; use libafl_bolts::{ownedref::OwnedSlice, HasLen}; -use super::WrappingInput; +use super::ValueInput; use crate::inputs::{HasMutatorBytes, HasTargetBytes}; /// A bytes input is the basic input -pub type BytesInput = WrappingInput>; +pub type BytesInput = ValueInput>; /// Rc Ref-cell from Input impl From for Rc> { diff --git a/libafl/src/inputs/mod.rs b/libafl/src/inputs/mod.rs index 46099dc404..b38b18856f 100644 --- a/libafl/src/inputs/mod.rs +++ b/libafl/src/inputs/mod.rs @@ -3,8 +3,8 @@ pub mod bytes; pub use bytes::BytesInput; -pub mod wrapping; -pub use wrapping::WrappingInput; +pub mod value; +pub use value::ValueInput; pub mod encoded; pub use encoded::*; @@ -213,7 +213,7 @@ where } /// A wrapper type that allows us to use mutators for Mutators for `&mut `[`Vec`]. -pub type MutVecInput<'a> = WrappingInput<&'a mut Vec>; +pub type MutVecInput<'a> = ValueInput<&'a mut Vec>; impl HasLen for MutVecInput<'_> { fn len(&self) -> usize { diff --git a/libafl/src/inputs/wrapping.rs b/libafl/src/inputs/value.rs similarity index 62% rename from libafl/src/inputs/wrapping.rs rename to libafl/src/inputs/value.rs index cf413d8f00..b1af47414d 100644 --- a/libafl/src/inputs/wrapping.rs +++ b/libafl/src/inputs/value.rs @@ -7,7 +7,7 @@ use core::{ }; use ahash::RandomState; -use num_traits::{One, WrappingAdd, WrappingSub, Zero}; +use num_traits::{One, WrappingAdd, WrappingSub}; use serde::{Deserialize, Serialize}; #[cfg(feature = "std")] use { @@ -22,16 +22,16 @@ use crate::corpus::CorpusId; /// /// This does not blanket implement [`super::Input`], because for certain inputs, writing them to disk does not make sense, because they don't own their data (like [`super::MutVecInput`]) #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Default)] -pub struct WrappingInput(I); +pub struct ValueInput(I); -impl From for WrappingInput { +impl From for ValueInput { fn from(value: I) -> Self { Self(value) } } -impl WrappingInput { - /// Create a new [`WrappingInput`] +impl ValueInput { + /// Create a new [`ValueInput`] pub const fn new(value: I) -> Self { Self(value) } @@ -42,30 +42,30 @@ impl WrappingInput { } } -impl AsRef for WrappingInput { +impl AsRef for ValueInput { fn as_ref(&self) -> &I { &self.0 } } -impl AsMut for WrappingInput { +impl AsMut for ValueInput { fn as_mut(&mut self) -> &mut I { &mut self.0 } } -impl MappedInput for WrappingInput<&mut I> { +impl MappedInput for ValueInput<&mut I> { type Type<'a> - = WrappingInput<&'a mut I> + = ValueInput<&'a mut I> where Self: 'a; } // Macro to implement the `Input` trait and create type aliases for `WrappingInput` -macro_rules! impl_input_for_wrapping_input { +macro_rules! impl_input_for_value_input { ($($t:ty => $name:ident),+ $(,)?) => { $( - impl Input for WrappingInput<$t> { + impl Input for ValueInput<$t> { fn generate_name(&self, _id: Option) -> String { format!( "{:016x}", @@ -75,13 +75,13 @@ macro_rules! impl_input_for_wrapping_input { } /// Input wrapping a <$t> - pub type $name = WrappingInput<$t>; + pub type $name = ValueInput<$t>; )* }; } // Invoke the macro with type-name pairs -impl_input_for_wrapping_input!( +impl_input_for_value_input!( u8 => U8Input, u16 => U16Input, u32 => U32Input, @@ -97,7 +97,7 @@ impl_input_for_wrapping_input!( ); /// manually implemented because files can be written more efficiently -impl Input for WrappingInput> { +impl Input for ValueInput> { fn generate_name(&self, _id: Option) -> String { format!( "{:016x}", @@ -128,31 +128,7 @@ impl Input for WrappingInput> { } } -/// Constants for numeric types -pub trait NumericConsts { - /// The number of bits, used for limiting shift operations - const BITS: u32; - /// The min value - const MIN: Self; - /// The max value - const MAX: Self; -} - -macro_rules! impl_numeric_consts { - ( $( $t:ty ),* $(,)? ) => { - $( - impl NumericConsts for $t { - const BITS: u32 = <$t>::BITS; - const MIN: Self = <$t>::MIN; - const MAX: Self = <$t>::MAX; - } - )* - }; -} - -impl_numeric_consts!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize); - -impl Shl for WrappingInput +impl Shl for ValueInput where I: Shl, I::Output: Into, @@ -164,7 +140,7 @@ where } } -impl BitXorAssign for WrappingInput +impl BitXorAssign for ValueInput where I: BitXorAssign, { @@ -172,7 +148,7 @@ where self.as_mut().bitxor_assign(rhs.inner()); } } -impl BitOrAssign for WrappingInput +impl BitOrAssign for ValueInput where I: BitOrAssign, { @@ -181,16 +157,7 @@ where } } -impl NumericConsts for WrappingInput -where - I: NumericConsts, -{ - const BITS: u32 = I::BITS; - const MIN: Self = WrappingInput::new(I::MIN); - const MAX: Self = WrappingInput::new(I::MAX); -} - -impl One for WrappingInput +impl One for ValueInput where I: One + Mul, { @@ -199,7 +166,7 @@ where } } -impl Mul for WrappingInput +impl Mul for ValueInput where I: Mul, I::Output: Into, @@ -211,20 +178,20 @@ where } } -impl Zero for WrappingInput -where - I: Zero + Into, -{ - fn zero() -> Self { - I::zero().into() - } +// impl Zero for ValueInput +// where +// I: Zero + Into, +// { +// fn zero() -> Self { +// I::zero().into() +// } - fn is_zero(&self) -> bool { - self.as_ref().is_zero() - } -} +// fn is_zero(&self) -> bool { +// self.as_ref().is_zero() +// } +// } -impl WrappingAdd for WrappingInput +impl WrappingAdd for ValueInput where I: WrappingAdd, I::Output: Into, @@ -234,7 +201,7 @@ where } } -impl Add for WrappingInput +impl Add for ValueInput where I: Add, I::Output: Into, @@ -245,7 +212,7 @@ where self.inner().add(rhs.inner()).into() } } -impl WrappingSub for WrappingInput +impl WrappingSub for ValueInput where I: WrappingSub, I::Output: Into, @@ -255,7 +222,7 @@ where } } -impl Sub for WrappingInput +impl Sub for ValueInput where I: Sub, I::Output: Into, @@ -267,7 +234,7 @@ where } } -impl Not for WrappingInput +impl Not for ValueInput where I: Not, I::Output: Into, @@ -279,20 +246,20 @@ where } } -impl Copy for WrappingInput where I: Copy {} +impl Copy for ValueInput where I: Copy {} #[cfg(test)] mod tests { use core::ops::{Add as _, Mul as _, Not as _, Sub as _}; - use num_traits::{One, WrappingAdd as _, WrappingSub as _, Zero}; + use num_traits::{One, WrappingAdd as _, WrappingSub as _}; - use crate::inputs::{wrapping::NumericConsts as _, WrappingInput}; + use crate::inputs::ValueInput; #[test] fn shl() { let unwrapped = 0x10_u64; - let wrapped: WrappingInput<_> = unwrapped.into(); + let wrapped: ValueInput<_> = unwrapped.into(); let offset = 1_u32; assert_eq!(unwrapped << offset, *(wrapped << offset).as_ref()); } @@ -300,80 +267,73 @@ mod tests { #[test] fn bit_xor_assign() { let mut unwrapped = 0x10_u64; - let mut wrapped: WrappingInput<_> = unwrapped.into(); + let mut wrapped: ValueInput<_> = unwrapped.into(); unwrapped ^= u64::one(); - wrapped ^= WrappingInput::one(); + wrapped ^= ValueInput::one(); assert_eq!(unwrapped, *wrapped.as_ref()); } #[test] fn bit_or_assign() { let mut unwrapped = 0x10_u64; - let mut wrapped: WrappingInput<_> = unwrapped.into(); + let mut wrapped: ValueInput<_> = unwrapped.into(); unwrapped |= u64::one(); - wrapped |= WrappingInput::one(); + wrapped |= ValueInput::one(); assert_eq!(unwrapped, *wrapped.as_ref()); } #[test] fn one() { let unwrapped = u64::one(); - let wrapped: WrappingInput = WrappingInput::one(); - assert_eq!(unwrapped, *wrapped.as_ref()); - } - - #[test] - fn zero() { - let unwrapped = u64::zero(); - let wrapped: WrappingInput = WrappingInput::zero(); + let wrapped: ValueInput = ValueInput::one(); assert_eq!(unwrapped, *wrapped.as_ref()); } #[test] fn mul() { - let lhs: WrappingInput = 7.into(); - let rhs: WrappingInput = 3.into(); + let lhs: ValueInput = 7.into(); + let rhs: ValueInput = 3.into(); assert_eq!(21, *lhs.mul(rhs).as_ref()); } #[test] fn add() { - let lhs: WrappingInput = 7.into(); - let rhs: WrappingInput = 3.into(); + let lhs: ValueInput = 7.into(); + let rhs: ValueInput = 3.into(); assert_eq!(10, *lhs.add(rhs).as_ref()); } #[test] fn wrapping_add() { - let lhs: WrappingInput = 7.into(); - let rhs: WrappingInput = 3.into(); + let lhs: ValueInput = 7.into(); + let rhs: ValueInput = 3.into(); assert_eq!(10, *lhs.wrapping_add(&rhs).as_ref()); - let lhs: WrappingInput = WrappingInput::MAX; - let rhs: WrappingInput = 1.into(); + let lhs: ValueInput = u64::MAX.into(); + let rhs: ValueInput = 1.into(); assert_eq!(0, *lhs.wrapping_add(&rhs).as_ref()); } #[test] fn sub() { - let lhs: WrappingInput = 7.into(); - let rhs: WrappingInput = 3.into(); + let lhs: ValueInput = 7.into(); + let rhs: ValueInput = 3.into(); assert_eq!(4, *lhs.sub(rhs).as_ref()); } #[test] fn wrapping_sub() { - let lhs: WrappingInput = 7.into(); - let rhs: WrappingInput = 3.into(); + let lhs: ValueInput = 7.into(); + let rhs: ValueInput = 3.into(); assert_eq!(4, *lhs.wrapping_sub(&rhs).as_ref()); - let lhs: WrappingInput = WrappingInput::MIN; - let rhs: WrappingInput = 1.into(); + let lhs: ValueInput = u64::MIN.into(); + let rhs: ValueInput = 1.into(); assert_eq!(u64::MAX, *lhs.wrapping_sub(&rhs).as_ref()); } #[test] fn not() { let unwrapped = 7; - let wrapped: WrappingInput = unwrapped.into(); + let wrapped: ValueInput = unwrapped.into(); assert_eq!(unwrapped.not(), *wrapped.not().as_ref()); } } diff --git a/libafl/src/mutators/numeric.rs b/libafl/src/mutators/numeric.rs index 2624d1103e..9aca85ab51 100644 --- a/libafl/src/mutators/numeric.rs +++ b/libafl/src/mutators/numeric.rs @@ -10,7 +10,7 @@ use tuple_list::{tuple_list, tuple_list_type}; use super::{MutationResult, Mutator}; use crate::{ corpus::Corpus, - inputs::wrapping::NumericConsts, + inputs::ValueInput, random_corpus_id_with_disabled, state::{HasCorpus, HasRand}, }; @@ -49,10 +49,10 @@ pub struct BitFlipMutator; impl Mutator for BitFlipMutator where S: HasRand, - I: Shl + BitXorAssign + NumericConsts + One, + I: Shl + BitXorAssign + One, { fn mutate(&mut self, state: &mut S, input: &mut I) -> Result { - *input ^= I::one() << state.rand_mut().choose(0..I::BITS).unwrap(); + *input ^= I::one() << state.rand_mut().choose(0..size_of::()).unwrap(); Ok(MutationResult::Mutated) } } @@ -69,11 +69,10 @@ pub struct FlipMutator; impl Mutator for FlipMutator where - I: Shl + NumericConsts + BitXorAssign + From, + I: Not + Copy, { fn mutate(&mut self, _state: &mut S, input: &mut I) -> Result { - *input ^= I::MAX as I; - + *input = !*input; Ok(MutationResult::Mutated) } } @@ -148,16 +147,24 @@ impl Named for NegMutator { #[derive(Debug)] pub struct RandMutator; -impl Mutator for RandMutator +impl Mutator, S> for RandMutator where S: HasRand, - I: Shl + NumericConsts + BitOrAssign + From + Zero, + ValueInput: Shl> + BitOrAssign, + I: From + Zero, { - fn mutate(&mut self, state: &mut S, input: &mut I) -> Result { - // set to byte-wise since the RNGs don't work for all numeric types - *input = I::zero(); - for offset in 0..I::BITS { - let mask: I = (state.rand_mut().next() as u8).into(); + fn mutate( + &mut self, + state: &mut S, + input: &mut ValueInput, + ) -> Result { + // set to random data byte-wise since the RNGs don't work for all numeric types + *input = I::zero().into(); + + for offset in 0..(size_of::() % size_of::()) { + let raw = state.rand_mut().next() as u8; + let inner: I = raw.into(); + let mask: ValueInput = inner.into(); *input |= mask << offset; } Ok(MutationResult::Mutated) @@ -206,7 +213,7 @@ mod tests { use super::int_mutators; use crate::{ corpus::{Corpus as _, InMemoryCorpus, Testcase}, - inputs::wrapping::U8Input, + inputs::value::I16Input, mutators::MutationResult, state::StdState, }; @@ -214,7 +221,7 @@ mod tests { #[test] fn all_mutate() { let mut corpus = InMemoryCorpus::new(); - corpus.add(Testcase::new(1_u8.into())).unwrap(); + corpus.add(Testcase::new(1_i16.into())).unwrap(); let mut state = StdState::new( StdRand::new(), corpus, @@ -224,7 +231,7 @@ mod tests { ) .unwrap(); - let mut input: U8Input = 0u8.into(); + let mut input: I16Input = 0_i16.into(); let mutators = int_mutators().into_vec();