mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-17 20:28:08 +00:00
custom mutator default descriptions
This commit is contained in:
@ -65,7 +65,7 @@ pub trait RawCustomMutator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn describe(&mut self, max_description: usize) -> Option<&str> {
|
fn describe(&mut self, max_description: usize) -> Option<&str> {
|
||||||
None
|
Some(default_mutator_describe::<Self>(max_description))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn introspection(&mut self) -> Option<&str> {
|
fn introspection(&mut self) -> Option<&str> {
|
||||||
@ -552,7 +552,7 @@ pub trait CustomMutator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn describe(&mut self, max_description: usize) -> Result<Option<&str>, Self::Error> {
|
fn describe(&mut self, max_description: usize) -> Result<Option<&str>, Self::Error> {
|
||||||
Ok(None)
|
Ok(Some(default_mutator_describe::<Self>(max_description)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn introspection(&mut self) -> Result<Option<&str>, Self::Error> {
|
fn introspection(&mut self) -> Result<Option<&str>, Self::Error> {
|
||||||
@ -657,3 +657,85 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// the default value to return from [`CustomMutator::describe`].
|
||||||
|
fn default_mutator_describe<T: ?Sized>(max_len: usize) -> &'static str {
|
||||||
|
truncate_str_unicode_safe(std::any::type_name::<T>(), max_len)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod default_mutator_describe {
|
||||||
|
struct MyMutator;
|
||||||
|
use super::CustomMutator;
|
||||||
|
impl CustomMutator for MyMutator {
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
|
fn init(_: u32) -> Result<Self, Self::Error> {
|
||||||
|
Ok(Self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fuzz<'b, 's: 'b>(
|
||||||
|
&'s mut self,
|
||||||
|
_: &'b mut [u8],
|
||||||
|
_: Option<&[u8]>,
|
||||||
|
_: usize,
|
||||||
|
) -> Result<Option<&'b [u8]>, Self::Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_default_describe() {
|
||||||
|
assert_eq!(
|
||||||
|
MyMutator::init(0).unwrap().describe(64).unwrap().unwrap(),
|
||||||
|
"custom_mutator::default_mutator_describe::MyMutator"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// little helper function to truncate a `str` to a maximum of bytes while retaining unicode safety
|
||||||
|
fn truncate_str_unicode_safe(s: &str, max_len: usize) -> &str {
|
||||||
|
if s.len() <= max_len {
|
||||||
|
s
|
||||||
|
} else {
|
||||||
|
if let Some((last_index, _)) = s
|
||||||
|
.char_indices()
|
||||||
|
.take_while(|(index, _)| *index <= max_len)
|
||||||
|
.last()
|
||||||
|
{
|
||||||
|
&s[..last_index]
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod truncate_test {
|
||||||
|
use super::truncate_str_unicode_safe;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_truncate() {
|
||||||
|
for (max_len, input, expected_output) in &[
|
||||||
|
(0usize, "a", ""),
|
||||||
|
(1, "a", "a"),
|
||||||
|
(1, "ä", ""),
|
||||||
|
(2, "ä", "ä"),
|
||||||
|
(3, "äa", "äa"),
|
||||||
|
(4, "äa", "äa"),
|
||||||
|
(1, "👎", ""),
|
||||||
|
(2, "👎", ""),
|
||||||
|
(3, "👎", ""),
|
||||||
|
(4, "👎", "👎"),
|
||||||
|
(1, "abc", "a"),
|
||||||
|
(2, "abc", "ab"),
|
||||||
|
] {
|
||||||
|
let actual_output = truncate_str_unicode_safe(input, *max_len);
|
||||||
|
assert_eq!(
|
||||||
|
&actual_output, expected_output,
|
||||||
|
"{:#?} truncated to {} bytes should be {:#?}, but is {:#?}",
|
||||||
|
input, max_len, expected_output, actual_output
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user