Rename string stages to unicode stages for consistency (#2293)

This commit is contained in:
Dominik Maier 2024-06-08 16:59:49 +01:00 committed by GitHub
parent e905743ef6
commit 93085782d6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 69 additions and 68 deletions

View File

@ -13,10 +13,10 @@ use libafl::{
feedbacks::{CrashFeedback, MaxMapFeedback}, feedbacks::{CrashFeedback, MaxMapFeedback},
fuzzer::{Fuzzer, StdFuzzer}, fuzzer::{Fuzzer, StdFuzzer},
inputs::{BytesInput, HasTargetBytes}, inputs::{BytesInput, HasTargetBytes},
mutators::{StdScheduledMutator, StringCategoryRandMutator, StringSubcategoryRandMutator}, mutators::{StdScheduledMutator, UnicodeCategoryRandMutator, UnicodeSubcategoryRandMutator},
observers::StdMapObserver, observers::StdMapObserver,
schedulers::QueueScheduler, schedulers::QueueScheduler,
stages::{mutational::StdMutationalStage, StringIdentificationStage}, stages::{mutational::StdMutationalStage, UnicodeIdentificationStage},
state::StdState, state::StdState,
Evaluator, Evaluator,
}; };
@ -121,14 +121,14 @@ pub fn main() {
// Setup a mutational stage with a basic bytes mutator // Setup a mutational stage with a basic bytes mutator
let mutator = StdScheduledMutator::new(tuple_list!( let mutator = StdScheduledMutator::new(tuple_list!(
StringCategoryRandMutator, UnicodeCategoryRandMutator,
StringSubcategoryRandMutator, UnicodeSubcategoryRandMutator,
StringSubcategoryRandMutator, UnicodeSubcategoryRandMutator,
StringSubcategoryRandMutator, UnicodeSubcategoryRandMutator,
StringSubcategoryRandMutator UnicodeSubcategoryRandMutator
)); ));
let mut stages = tuple_list!( let mut stages = tuple_list!(
StringIdentificationStage::new(), UnicodeIdentificationStage::new(),
StdMutationalStage::transforming(mutator) StdMutationalStage::transforming(mutator)
); );

View File

@ -85,7 +85,7 @@ concolic_mutation = ["z3"]
## Enable the fancy TuiMonitor for a termanal UI using crossterm ## Enable the fancy TuiMonitor for a termanal UI using crossterm
tui_monitor = ["ratatui", "crossterm"] tui_monitor = ["ratatui", "crossterm"]
## Enables `StringClassificationStage` and associated mutators, which allow for mutations which preserve the Unicode property data ## Enables `UnicodeClassificationStage` and associated mutators, which allow for mutations which preserve the Unicode property data
unicode = ["libafl_bolts/alloc", "ahash/std", "serde/rc", "bitvec"] unicode = ["libafl_bolts/alloc", "ahash/std", "serde/rc", "bitvec"]
## Enable multi-part input formats and mutators ## Enable multi-part input formats and mutators

View File

@ -21,9 +21,9 @@ pub mod tuneable;
pub use tuneable::*; pub use tuneable::*;
#[cfg(feature = "unicode")] #[cfg(feature = "unicode")]
pub mod string; pub mod unicode;
#[cfg(feature = "unicode")] #[cfg(feature = "unicode")]
pub use string::*; pub use unicode::*;
#[cfg(feature = "multipart_inputs")] #[cfg(feature = "multipart_inputs")]
pub mod multi; pub mod multi;

View File

@ -1,4 +1,5 @@
//! Mutators for preserving string categories, which may be useful for certain targets which are primarily string-oriented. //! Mutators for preserving unicode string categories,
//! which may be useful for certain targets which are primarily string-oriented.
use alloc::{borrow::Cow, vec::Vec}; use alloc::{borrow::Cow, vec::Vec};
use core::{ use core::{
cmp::{Ordering, Reverse}, cmp::{Ordering, Reverse},
@ -14,7 +15,7 @@ use crate::{
stages::{ stages::{
extract_metadata, extract_metadata,
mutational::{MutatedTransform, MutatedTransformPost}, mutational::{MutatedTransform, MutatedTransformPost},
StringIdentificationMetadata, UnicodeIdentificationMetadata,
}, },
state::{HasCorpus, HasMaxSize, HasRand}, state::{HasCorpus, HasMaxSize, HasRand},
HasMetadata, HasMetadata,
@ -27,17 +28,17 @@ use crate::{
pub mod unicode_categories; pub mod unicode_categories;
/// Input which contains the context necessary to perform unicode mutations /// Input which contains the context necessary to perform unicode mutations
pub type UnicodeInput = (BytesInput, StringIdentificationMetadata); pub type UnicodeInput = (BytesInput, UnicodeIdentificationMetadata);
impl<S> MutatedTransform<BytesInput, S> for UnicodeInput impl<S> MutatedTransform<BytesInput, S> for UnicodeInput
where where
S: HasCorpus<Input = BytesInput> + HasTestcase, S: HasCorpus<Input = BytesInput> + HasTestcase,
{ {
type Post = StringIdentificationMetadata; type Post = UnicodeIdentificationMetadata;
fn try_transform_from(base: &mut Testcase<BytesInput>, state: &S) -> Result<Self, Error> { fn try_transform_from(base: &mut Testcase<BytesInput>, state: &S) -> Result<Self, Error> {
let input = base.load_input(state.corpus())?.clone(); let input = base.load_input(state.corpus())?.clone();
let metadata = base.metadata::<StringIdentificationMetadata>().cloned()?; let metadata = base.metadata::<UnicodeIdentificationMetadata>().cloned()?;
Ok((input, metadata)) Ok((input, metadata))
} }
@ -46,7 +47,7 @@ where
} }
} }
impl<S> MutatedTransformPost<S> for StringIdentificationMetadata impl<S> MutatedTransformPost<S> for UnicodeIdentificationMetadata
where where
S: HasTestcase, S: HasTestcase,
{ {
@ -64,7 +65,7 @@ const MAX_CHARS: usize = 16;
fn choose_start<R: Rand>( fn choose_start<R: Rand>(
rand: &mut R, rand: &mut R,
bytes: &[u8], bytes: &[u8],
meta: &StringIdentificationMetadata, meta: &UnicodeIdentificationMetadata,
) -> Option<(usize, usize)> { ) -> Option<(usize, usize)> {
let idx = rand.below(bytes.len()); let idx = rand.below(bytes.len());
let mut options = Vec::new(); let mut options = Vec::new();
@ -268,16 +269,16 @@ fn rand_replace_range<S: HasRand + HasMaxSize, F: Fn(&mut S) -> char>(
/// Mutator which randomly replaces a randomly selected range of bytes with bytes that preserve the /// Mutator which randomly replaces a randomly selected range of bytes with bytes that preserve the
/// range's category /// range's category
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct StringCategoryRandMutator; pub struct UnicodeCategoryRandMutator;
impl Named for StringCategoryRandMutator { impl Named for UnicodeCategoryRandMutator {
fn name(&self) -> &Cow<'static, str> { fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("string-category-rand"); static NAME: Cow<'static, str> = Cow::Borrowed("string-category-rand");
&NAME &NAME
} }
} }
impl<S> Mutator<UnicodeInput, S> for StringCategoryRandMutator impl<S> Mutator<UnicodeInput, S> for UnicodeCategoryRandMutator
where where
S: HasRand + HasMaxSize, S: HasRand + HasMaxSize,
{ {
@ -327,16 +328,16 @@ where
/// Mutator which randomly replaces a randomly selected range of bytes with bytes that preserve the /// Mutator which randomly replaces a randomly selected range of bytes with bytes that preserve the
/// range's subcategory /// range's subcategory
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct StringSubcategoryRandMutator; pub struct UnicodeSubcategoryRandMutator;
impl Named for StringSubcategoryRandMutator { impl Named for UnicodeSubcategoryRandMutator {
fn name(&self) -> &Cow<'static, str> { fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("string-subcategory-rand"); static NAME: Cow<'static, str> = Cow::Borrowed("string-subcategory-rand");
&NAME &NAME
} }
} }
impl<S> Mutator<UnicodeInput, S> for StringSubcategoryRandMutator impl<S> Mutator<UnicodeInput, S> for UnicodeSubcategoryRandMutator
where where
S: HasRand + HasMaxSize, S: HasRand + HasMaxSize,
{ {
@ -374,16 +375,16 @@ where
/// Mutator which randomly replaces a full category-contiguous region of chars with a random token /// Mutator which randomly replaces a full category-contiguous region of chars with a random token
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct StringCategoryTokenReplaceMutator; pub struct UnicodeCategoryTokenReplaceMutator;
impl Named for StringCategoryTokenReplaceMutator { impl Named for UnicodeCategoryTokenReplaceMutator {
fn name(&self) -> &Cow<'static, str> { fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("string-category-token-replace"); static NAME: Cow<'static, str> = Cow::Borrowed("string-category-token-replace");
&NAME &NAME
} }
} }
impl<S> Mutator<UnicodeInput, S> for StringCategoryTokenReplaceMutator impl<S> Mutator<UnicodeInput, S> for UnicodeCategoryTokenReplaceMutator
where where
S: HasRand + HasMaxSize + HasMetadata, S: HasRand + HasMaxSize + HasMetadata,
{ {
@ -434,16 +435,16 @@ where
/// Mutator which randomly replaces a full subcategory-contiguous region of chars with a random token /// Mutator which randomly replaces a full subcategory-contiguous region of chars with a random token
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct StringSubcategoryTokenReplaceMutator; pub struct UnicodeSubcategoryTokenReplaceMutator;
impl Named for StringSubcategoryTokenReplaceMutator { impl Named for UnicodeSubcategoryTokenReplaceMutator {
fn name(&self) -> &Cow<'static, str> { fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("string-subcategory-replace"); static NAME: Cow<'static, str> = Cow::Borrowed("string-subcategory-replace");
&NAME &NAME
} }
} }
impl<S> Mutator<UnicodeInput, S> for StringSubcategoryTokenReplaceMutator impl<S> Mutator<UnicodeInput, S> for UnicodeSubcategoryTokenReplaceMutator
where where
S: HasRand + HasMaxSize + HasMetadata, S: HasRand + HasMaxSize + HasMetadata,
{ {
@ -499,7 +500,7 @@ mod test {
use crate::{ use crate::{
corpus::NopCorpus, corpus::NopCorpus,
inputs::{BytesInput, HasMutatorBytes}, inputs::{BytesInput, HasMutatorBytes},
mutators::{Mutator, StringCategoryRandMutator, StringSubcategoryRandMutator}, mutators::{Mutator, UnicodeCategoryRandMutator, UnicodeSubcategoryRandMutator},
stages::extract_metadata, stages::extract_metadata,
state::StdState, state::StdState,
}; };
@ -511,7 +512,7 @@ mod test {
let hex = "0123456789abcdef0123456789abcdef"; let hex = "0123456789abcdef0123456789abcdef";
let mut bytes = BytesInput::from(hex.as_bytes()); let mut bytes = BytesInput::from(hex.as_bytes());
let mut mutator = StringCategoryRandMutator; let mut mutator = UnicodeCategoryRandMutator;
let mut state = StdState::new( let mut state = StdState::new(
StdRand::with_seed(0), StdRand::with_seed(0),
@ -543,7 +544,7 @@ mod test {
let hex = "0123456789abcdef0123456789abcdef"; let hex = "0123456789abcdef0123456789abcdef";
let mut bytes = BytesInput::from(hex.as_bytes()); let mut bytes = BytesInput::from(hex.as_bytes());
let mut mutator = StringSubcategoryRandMutator; let mut mutator = UnicodeSubcategoryRandMutator;
let mut state = StdState::new( let mut state = StdState::new(
StdRand::with_seed(0), StdRand::with_seed(0),

View File

@ -27,8 +27,6 @@ pub use mutational::{MutationalStage, StdMutationalStage};
pub use power::{PowerMutationalStage, StdPowerMutationalStage}; pub use power::{PowerMutationalStage, StdPowerMutationalStage};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
pub use stats::AflStatsStage; pub use stats::AflStatsStage;
#[cfg(feature = "unicode")]
pub use string::*;
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use sync::*; pub use sync::*;
pub use tmin::{ pub use tmin::{
@ -37,6 +35,8 @@ pub use tmin::{
pub use tracing::{ShadowTracingStage, TracingStage}; pub use tracing::{ShadowTracingStage, TracingStage};
pub use tuneable::*; pub use tuneable::*;
use tuple_list::NonEmptyTuple; use tuple_list::NonEmptyTuple;
#[cfg(feature = "unicode")]
pub use unicode::*;
use crate::{ use crate::{
corpus::{CorpusId, HasCurrentCorpusId}, corpus::{CorpusId, HasCurrentCorpusId},
@ -68,12 +68,12 @@ pub mod generation;
pub mod logics; pub mod logics;
pub mod power; pub mod power;
pub mod stats; pub mod stats;
#[cfg(feature = "unicode")]
pub mod string;
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub mod sync; pub mod sync;
pub mod tracing; pub mod tracing;
pub mod tuneable; pub mod tuneable;
#[cfg(feature = "unicode")]
pub mod unicode;
/// A stage is one step in the fuzzing process. /// A stage is one step in the fuzzing process.
/// Multiple stages will be scheduled one by one for each input. /// Multiple stages will be scheduled one by one for each input.

View File

@ -17,13 +17,13 @@ use crate::{
/// Metadata which stores the list of pre-computed string-like ranges in the input /// Metadata which stores the list of pre-computed string-like ranges in the input
#[derive(Debug, Default, Serialize, Deserialize, Clone)] #[derive(Debug, Default, Serialize, Deserialize, Clone)]
pub struct StringIdentificationMetadata { pub struct UnicodeIdentificationMetadata {
ranges: Rc<Vec<(usize, BitVec)>>, ranges: Rc<Vec<(usize, BitVec)>>,
} }
impl_serdeany!(StringIdentificationMetadata); impl_serdeany!(UnicodeIdentificationMetadata);
impl StringIdentificationMetadata { impl UnicodeIdentificationMetadata {
/// The list of pre-computed string-like ranges in the input /// The list of pre-computed string-like ranges in the input
#[must_use] #[must_use]
pub fn ranges(&self) -> &Vec<(usize, BitVec)> { pub fn ranges(&self) -> &Vec<(usize, BitVec)> {
@ -31,7 +31,7 @@ impl StringIdentificationMetadata {
} }
} }
pub(crate) fn extract_metadata(bytes: &[u8]) -> StringIdentificationMetadata { pub(crate) fn extract_metadata(bytes: &[u8]) -> UnicodeIdentificationMetadata {
let mut ranges = Vec::new(); let mut ranges = Vec::new();
if !bytes.is_empty() { if !bytes.is_empty() {
@ -64,24 +64,24 @@ pub(crate) fn extract_metadata(bytes: &[u8]) -> StringIdentificationMetadata {
} }
} }
StringIdentificationMetadata { UnicodeIdentificationMetadata {
ranges: Rc::new(ranges), ranges: Rc::new(ranges),
} }
} }
/// Stage which identifies potential strings in the provided input /// Stage which identifies potential strings in the provided input
#[derive(Debug)] #[derive(Debug)]
pub struct StringIdentificationStage<S> { pub struct UnicodeIdentificationStage<S> {
phantom: PhantomData<S>, phantom: PhantomData<S>,
} }
impl<S> Default for StringIdentificationStage<S> { impl<S> Default for UnicodeIdentificationStage<S> {
fn default() -> Self { fn default() -> Self {
Self::new() Self::new()
} }
} }
impl<S> StringIdentificationStage<S> { impl<S> UnicodeIdentificationStage<S> {
/// Create a new instance of the string identification stage /// Create a new instance of the string identification stage
#[must_use] #[must_use]
pub fn new() -> Self { pub fn new() -> Self {
@ -91,14 +91,14 @@ impl<S> StringIdentificationStage<S> {
} }
} }
impl<S> UsesState for StringIdentificationStage<S> impl<S> UsesState for UnicodeIdentificationStage<S>
where where
S: State, S: State,
{ {
type State = S; type State = S;
} }
impl<S, E, EM, Z> Stage<E, EM, Z> for StringIdentificationStage<S> impl<S, E, EM, Z> Stage<E, EM, Z> for UnicodeIdentificationStage<S>
where where
S: HasTestcase<Input = BytesInput> + HasCorpus + State, S: HasTestcase<Input = BytesInput> + HasCorpus + State,
E: UsesState<State = S>, E: UsesState<State = S>,
@ -113,7 +113,7 @@ where
_manager: &mut EM, _manager: &mut EM,
) -> Result<(), Error> { ) -> Result<(), Error> {
let mut tc = state.current_testcase_mut()?; let mut tc = state.current_testcase_mut()?;
if tc.has_metadata::<StringIdentificationMetadata>() { if tc.has_metadata::<UnicodeIdentificationMetadata>() {
return Ok(()); // skip recompute return Ok(()); // skip recompute
} }

View File

@ -155,8 +155,8 @@ macro_rules! fuzz_with {
mutators::{ mutators::{
GrimoireExtensionMutator, GrimoireRecursiveReplacementMutator, GrimoireRandomDeleteMutator, GrimoireExtensionMutator, GrimoireRecursiveReplacementMutator, GrimoireRandomDeleteMutator,
GrimoireStringReplacementMutator, havoc_crossover, havoc_mutations, havoc_mutations_no_crossover, GrimoireStringReplacementMutator, havoc_crossover, havoc_mutations, havoc_mutations_no_crossover,
I2SRandReplace, StdScheduledMutator, StringCategoryRandMutator, StringSubcategoryRandMutator, I2SRandReplace, StdScheduledMutator, UnicodeCategoryRandMutator, UnicodeSubcategoryRandMutator,
StringCategoryTokenReplaceMutator, StringSubcategoryTokenReplaceMutator, Tokens, tokens_mutations UnicodeCategoryTokenReplaceMutator, UnicodeSubcategoryTokenReplaceMutator, Tokens, tokens_mutations
}, },
observers::{stacktrace::BacktraceObserver, TimeObserver, CanTrack}, observers::{stacktrace::BacktraceObserver, TimeObserver, CanTrack},
schedulers::{ schedulers::{
@ -164,7 +164,7 @@ macro_rules! fuzz_with {
}, },
stages::{ stages::{
CalibrationStage, GeneralizationStage, IfStage, StdMutationalStage, CalibrationStage, GeneralizationStage, IfStage, StdMutationalStage,
StdPowerMutationalStage, StringIdentificationStage, TracingStage, StdPowerMutationalStage, UnicodeIdentificationStage, TracingStage,
}, },
state::{HasCorpus, StdState}, state::{HasCorpus, StdState},
StdFuzzer, StdFuzzer,
@ -289,29 +289,29 @@ macro_rules! fuzz_with {
// Set up a string category analysis stage for unicode mutations // Set up a string category analysis stage for unicode mutations
let unicode_used = $options.unicode(); let unicode_used = $options.unicode();
let string_mutator = StdScheduledMutator::new( let unicode_mutator = StdScheduledMutator::new(
tuple_list!( tuple_list!(
StringCategoryRandMutator, UnicodeCategoryRandMutator,
StringSubcategoryRandMutator, UnicodeSubcategoryRandMutator,
StringSubcategoryRandMutator, UnicodeSubcategoryRandMutator,
StringSubcategoryRandMutator, UnicodeSubcategoryRandMutator,
StringSubcategoryRandMutator, UnicodeSubcategoryRandMutator,
) )
); );
let string_replace_mutator = StdScheduledMutator::new( let unicode_replace_mutator = StdScheduledMutator::new(
tuple_list!( tuple_list!(
StringCategoryTokenReplaceMutator, UnicodeCategoryTokenReplaceMutator,
StringSubcategoryTokenReplaceMutator, UnicodeSubcategoryTokenReplaceMutator,
StringSubcategoryTokenReplaceMutator, UnicodeSubcategoryTokenReplaceMutator,
StringSubcategoryTokenReplaceMutator, UnicodeSubcategoryTokenReplaceMutator,
StringSubcategoryTokenReplaceMutator, UnicodeSubcategoryTokenReplaceMutator,
) )
); );
let string_power = StdMutationalStage::transforming(string_mutator); let unicode_power = StdMutationalStage::transforming(unicode_mutator);
let string_replace_power = StdMutationalStage::transforming(string_replace_mutator); let unicode_replace_power = StdMutationalStage::transforming(unicode_replace_mutator);
let string_analysis = StringIdentificationStage::new(); let unicode_analysis = UnicodeIdentificationStage::new();
let string_analysis = IfStage::new(|_, _, _, _| Ok((unicode_used && mutator_status.std_mutational).into()), tuple_list!(string_analysis, string_power, string_replace_power)); let unicode_analysis = IfStage::new(|_, _, _, _| Ok((unicode_used && mutator_status.std_mutational).into()), tuple_list!(unicode_analysis, unicode_power, unicode_replace_power));
// Attempt to use tokens from libfuzzer dicts // Attempt to use tokens from libfuzzer dicts
if !state.has_metadata::<Tokens>() { if !state.has_metadata::<Tokens>() {
@ -481,7 +481,7 @@ macro_rules! fuzz_with {
calibration, calibration,
generalization, generalization,
tracing, tracing,
string_analysis, unicode_analysis,
i2s, i2s,
cm_i2s, cm_i2s,
std_power, std_power,