libafl/inputs/
nautilus.rs

1//! Input for the [`Nautilus`](https://github.com/RUB-SysSec/nautilus) grammar fuzzer methods
2use alloc::{rc::Rc, vec::Vec};
3use core::{
4    cell::RefCell,
5    hash::{Hash, Hasher},
6};
7
8use libafl_bolts::{HasLen, ownedref::OwnedSlice};
9use serde::{Deserialize, Serialize};
10
11use super::BytesInput;
12use crate::{
13    common::nautilus::grammartec::{
14        newtypes::NodeId,
15        rule::RuleIdOrCustom,
16        tree::{Tree, TreeLike},
17    },
18    generators::nautilus::NautilusContext,
19    inputs::{Input, InputConverter, InputToBytes},
20};
21
22/// An [`Input`] implementation for `Nautilus` grammar.
23#[derive(Serialize, Deserialize, Clone, Debug)]
24pub struct NautilusInput {
25    /// The input representation as Tree
26    pub tree: Tree,
27}
28
29impl Input for NautilusInput {}
30
31/// Rc Ref-cell from Input
32impl From<NautilusInput> for Rc<RefCell<NautilusInput>> {
33    fn from(input: NautilusInput) -> Self {
34        Rc::new(RefCell::new(input))
35    }
36}
37
38impl HasLen for NautilusInput {
39    #[inline]
40    fn len(&self) -> usize {
41        self.tree.size()
42    }
43}
44
45impl NautilusInput {
46    /// Creates a new codes input using the given terminals
47    #[must_use]
48    pub fn new(tree: Tree) -> Self {
49        Self { tree }
50    }
51
52    /// Create an empty [`Input`]
53    #[must_use]
54    pub fn empty() -> Self {
55        Self {
56            tree: Tree {
57                rules: vec![],
58                sizes: vec![],
59                paren: vec![],
60            },
61        }
62    }
63
64    /// Generate a `Nautilus` input from the given bytes
65    pub fn unparse(&self, context: &NautilusContext, bytes: &mut Vec<u8>) {
66        bytes.clear();
67        self.tree.unparse(NodeId::from(0), &context.ctx, bytes);
68    }
69
70    /// Get the tree representation of this input
71    #[must_use]
72    pub fn tree(&self) -> &Tree {
73        &self.tree
74    }
75
76    /// Get the tree representation of this input, as a mutable reference
77    #[must_use]
78    pub fn tree_mut(&mut self) -> &mut Tree {
79        &mut self.tree
80    }
81}
82
83impl Hash for NautilusInput {
84    fn hash<H: Hasher>(&self, state: &mut H) {
85        self.tree().paren.hash(state);
86        for r in &self.tree().rules {
87            match r {
88                RuleIdOrCustom::Custom(a, b) => {
89                    a.hash(state);
90                    b.hash(state);
91                }
92                RuleIdOrCustom::Rule(a) => a.hash(state),
93            }
94        }
95        self.tree().sizes.hash(state);
96    }
97}
98
99/// Convert from `NautilusInput` to `BytesInput`
100#[derive(Debug)]
101pub struct NautilusBytesConverter<'a> {
102    ctx: &'a NautilusContext,
103}
104
105impl<'a> NautilusBytesConverter<'a> {
106    #[must_use]
107    /// Create a new `NautilusBytesConverter` from a context
108    pub fn new(ctx: &'a NautilusContext) -> Self {
109        Self { ctx }
110    }
111}
112
113impl InputConverter for NautilusBytesConverter<'_> {
114    type From = NautilusInput;
115    type To = BytesInput;
116
117    fn convert(&mut self, input: Self::From) -> Result<Self::To, libafl_bolts::Error> {
118        let mut bytes = vec![];
119        input.unparse(self.ctx, &mut bytes);
120        Ok(BytesInput::new(bytes))
121    }
122}
123
124impl InputToBytes<NautilusInput> for NautilusBytesConverter<'_> {
125    fn to_bytes<'a>(&mut self, input: &'a NautilusInput) -> OwnedSlice<'a, u8> {
126        let mut bytes = vec![];
127        input.unparse(self.ctx, &mut bytes);
128        OwnedSlice::from(bytes)
129    }
130}