use crate::fuzzer::stages::minimization::shuffle;
use crate::{MutationType, Node};
use crate::{NodeType, Visitor};
use libafl::{
corpus::Corpus,
mutators::{MutationResult, Mutator},
state::{HasCorpus, HasRand},
HasMetadata,
};
use libafl_bolts::{HasLen, Named};
use std::{borrow::Cow, cell::RefCell, collections::VecDeque, marker::PhantomData, rc::Rc};
use crate::fuzzer::context::Context;
use super::commons::calculate_subslice_bounds;
pub const RECURSE_STACK: usize = 1000;
pub struct AutarkieRecurseMutator<I> {
max_subslice_size: usize,
visitor: Rc<RefCell<Visitor>>,
phantom: PhantomData<I>,
}
impl<I, S> Mutator<I, S> for AutarkieRecurseMutator<I>
where
I: Node,
S: HasCorpus<I> + HasRand + HasMetadata,
{
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, libafl::Error> {
if !self.visitor.borrow().has_recursive_types() {
return Ok(MutationResult::Skipped);
}
let mut metadata = state.metadata_mut::<Context>()?;
input.__autarkie_fields(&mut self.visitor.borrow_mut(), 0);
let mut fields = self.visitor.borrow_mut().fields();
shuffle(&mut fields, &mut self.visitor.borrow_mut());
let mut recursive_node = None;
for node in &fields {
if matches!(node.last().expect("____LqG7SD18").0 .1, NodeType::Recursive) {
recursive_node = Some(node);
}
}
println!("{:?}", recursive_node);
let mut all = Vec::new();
let mut start = Some(0);
if let Some(recursive_node) = recursive_node {
for node in &fields {
if let Some(index) = find_subsequence(&node, &recursive_node, start) {
if fields.get(index).unwrap().len() == recursive_node.len() + 1 {
all.push(fields.get(index).unwrap());
start = Some(index)
}
}
}
}
return Ok(MutationResult::Skipped);
}
fn post_exec(
&mut self,
_state: &mut S,
_new_corpus_id: Option<libafl::corpus::CorpusId>,
) -> Result<(), libafl::Error> {
Ok(())
}
}
impl<I> Named for AutarkieRecurseMutator<I> {
fn name(&self) -> &std::borrow::Cow<'static, str> {
&Cow::Borrowed("AutarkieRecurseMutator")
}
}
impl<I> AutarkieRecurseMutator<I> {
pub fn new(visitor: Rc<RefCell<Visitor>>, max_subslice_size: usize) -> Self {
Self {
visitor,
max_subslice_size,
phantom: PhantomData,
}
}
}
fn find_subsequence<T: PartialEq>(
haystack: &[T],
needle: &[T],
start: Option<usize>,
) -> Option<usize> {
haystack[start.unwrap_or(0)..]
.windows(needle.len())
.position(|window| window == needle)
}