LibAFL icon indicating copy to clipboard operation
LibAFL copied to clipboard

Annoying bound when extending StdState

Open wtdcode opened this issue 2 years ago • 2 comments

Not surprising finally I decide to extend StdState because RefCell doesn't satisfy SerdeAny so I can't save that to metadata (If there is some other way to do it, please let me know!).

So I try to write something like:

pub struct FuzzState<I, C, R, SC> {
    inner: StdState<I, C, R, SC>,

    meta: Rc<RefCell<MySuperData>>,
}

But soon when I try to mimic StdState::new (AFAIK, rust so far doesn't have simple solution for delegation?) I get stuck by this:

    pub fn new<F, O>(
        rand: R,
        corpus: C,
        solutions: SC,
        meta: &Rc<RefCell<MySuperData>>,
        feedback: &mut F,
        objective: &mut O,
    ) -> Result<Self, Error>
    where
        F: Feedback<Self>, // <--- This bound in StdState asks for Feedback<StdState>
        O: Feedback<Self>,
    {
        match StdState::new(rand, corpus, solutions, feedback, objective) { // <--- Here, rust complains: consider further restricting this bound: ` + libafl::feedbacks::Feedback<libafl::state::StdState<I, C, R, SC>>`
            Ok(r) => {
                let mut ret = Self {
                    inner: r,
                    meta: Rc::clone(meta),
                };
                Ok(ret)
            }
            Err(e) => Err(e),
        }
    }

However, this is totally not necessary because feedback and objective are not stored in StdState directly and their generic parameters S doesn't need to be StdState. So my final solution is:

    pub fn new<F, O>(
        rand: R,
        corpus: C,
        solutions: SC,
        meta: &Rc<RefCell<MySuperData>>>,
        feedback: &mut F,
        objective: &mut O,
    ) -> Result<Self, Error>
    where
        F: Feedback<Self>,
        O: Feedback<Self>,
    {
        // Just make stdstate happy.
        let mut fd = CrashFeedback::new();
        let mut fd2 = CrashFeedback::new();
        match StdState::new(rand, corpus, solutions, &mut fd, &mut fd2) {
            Ok(r) => {
                let mut ret = Self {
                    inner: r,
                    meta: Rc::clone(meta),
                };
                feedback.init_state(&mut ret);
                objective.init_state(&mut ret);
                Ok(ret)
            }
            Err(e) => Err(e),
        }
    }

Is there any other good way to do this or I do something wrong?

wtdcode avatar May 01 '23 21:05 wtdcode

You can technically use Serde with the refcell feature (or maybe the name is different, not sure), but the Serde folks don't recommend it (restoring it will not deduplicate refcells, or something like that)..

For the bounds: If we can take them away and it still compiles all testcases, feel free to open a PR :)

domenukk avatar May 02 '23 13:05 domenukk

You can technically use Serde with the refcell feature (or maybe the name is different, not sure), but the Serde folks don't recommend it (restoring it will not deduplicate refcells, or something like that)..

Yes, I could confirm it's possible with serde, but not with libafl's SerdeAny wrapper. I didn't check the reason exactly.

For the bounds: If we can take them away and it still compiles all testcases, feel free to open a PR :)

Will have a look once found some time. It should be trivial but then we should consider the right place to init both feedbacks.

wtdcode avatar May 02 '23 17:05 wtdcode

I'll close this for now, feel free to reopen if you have an idea what we can change/got more questions

domenukk avatar Mar 12 '24 23:03 domenukk