fuzzcheck/mutators/
fixed_len_vector.rs

1use std::any::Any;
2use std::cell::Cell;
3use std::marker::PhantomData;
4
5use fastrand::Rng;
6
7use super::CrossoverStep;
8use crate::{Mutator, CROSSOVER_RATE};
9
10/// A mutator for vectors of a specific length
11///
12/// A different mutator is used for each element of the vector
13pub struct FixedLenVecMutator<T, M>
14where
15    T: Clone + 'static,
16    M: Mutator<T>,
17{
18    pub rng: Rng,
19    mutators: Vec<M>,
20    initialized: Cell<bool>,
21    min_complexity: Cell<f64>,
22    max_complexity: Cell<f64>,
23    search_space_complexity: Cell<f64>,
24    has_inherent_complexity: bool,
25    inherent_complexity: Cell<f64>,
26    _phantom: PhantomData<T>,
27}
28impl<T, M> FixedLenVecMutator<T, M>
29where
30    T: Clone + 'static,
31    M: Mutator<T> + Clone,
32{
33    #[coverage(off)]
34    pub fn new_with_repeated_mutator(mutator: M, len: usize) -> Self {
35        Self::new(vec![mutator; len])
36    }
37}
38
39impl<T, M> FixedLenVecMutator<T, M>
40where
41    T: Clone + 'static,
42    M: Mutator<T>,
43{
44    /// Note: only use this function if you really know what you are doing!
45    ///
46    /// Create a `FixedLenVecMutator` using the given submutators.
47    /// The complexity of the generated vectors will be only the sum of the
48    /// complexities of their elements.
49    ///
50    /// This is not the default behaviour.
51    /// Normally, a vector such as `[1u8, 2u8]` would have a complexity of `17`:
52    /// `2 * 8` for the first two integers, and `+ 1` for the inherent
53    /// complexity of the vector itself. If the vector contains elements with a
54    /// minimum complexity of 0.0, then its length would also influence its
55    /// complexity. For example, `[(), ()]` would have a complexity of `3.0`:
56    /// `1` for the vector and  `+ 2` for the length.
57    ///
58    /// By using this function to create the `FixedLenVecMutator`, we get rid
59    /// of the "inherent" part of the vector complexity. For example, the vector
60    /// `[1u8, 2u8]` will have a complexity of 16.0 and the vector `[[], []]`
61    /// will have a complexity of 0.0.
62    ///
63    /// Note that *all mutators in a fuzz test must agree on the complexity of
64    /// a value*. For example, if you are mutating a 2-tuple of vectors:
65    /// `(Vec<u8>, Vec<u8>)` using two `FixedLenVecMutator`, then both must
66    /// agree on whether to include the inherent complexity of the vectors or
67    /// not. That is, given the value `([1, 2], [1, 2])`, it is an error to
68    /// evaluate the complexity of the first vector as `16.0` and the complexity
69    /// of the second vector as `17.0`.
70    #[coverage(off)]
71    pub fn new_without_inherent_complexity(mutators: Vec<M>) -> Self {
72        assert!(!mutators.is_empty());
73
74        Self {
75            rng: Rng::default(),
76            mutators,
77            initialized: Cell::new(false),
78            min_complexity: Cell::new(std::f64::INFINITY),
79            max_complexity: Cell::default(),
80            search_space_complexity: Cell::default(),
81            has_inherent_complexity: false,
82            inherent_complexity: Cell::default(),
83            _phantom: PhantomData,
84        }
85    }
86
87    #[coverage(off)]
88    pub fn new(mutators: Vec<M>) -> Self {
89        assert!(!mutators.is_empty());
90
91        Self {
92            rng: Rng::default(),
93            mutators,
94            initialized: Cell::new(false),
95            min_complexity: Cell::new(std::f64::INFINITY),
96            max_complexity: Cell::new(std::f64::INFINITY),
97            search_space_complexity: Cell::new(std::f64::INFINITY),
98            has_inherent_complexity: true,
99            inherent_complexity: Cell::default(),
100            _phantom: PhantomData,
101        }
102    }
103}
104
105#[derive(Clone)]
106pub struct MutationStep<T, S> {
107    inner: Vec<S>,
108    element_step: usize,
109    crossover_steps: Vec<CrossoverStep<T>>,
110}
111
112#[derive(Clone)]
113pub struct VecMutatorCache<C> {
114    inner: Vec<C>,
115    sum_cplx: f64,
116}
117impl<C> Default for VecMutatorCache<C> {
118    #[coverage(off)]
119    fn default() -> Self {
120        Self {
121            inner: Vec::new(),
122            sum_cplx: 0.0,
123        }
124    }
125}
126
127pub enum UnmutateVecToken<T: Clone + 'static, M: Mutator<T>> {
128    ReplaceElement(usize, T),
129    Element(usize, M::UnmutateToken),
130    Elements(Vec<(usize, M::UnmutateToken)>),
131    Replace(Vec<T>),
132}
133
134impl<T: Clone + 'static, M: Mutator<T>> FixedLenVecMutator<T, M> {
135    #[coverage(off)]
136    fn len(&self) -> usize {
137        self.mutators.len()
138    }
139    #[coverage(off)]
140    fn mutate_elements(
141        &self,
142        value: &mut [T],
143        cache: &mut VecMutatorCache<M::Cache>,
144        idcs: &[usize],
145        current_cplx: f64,
146        max_cplx: f64,
147    ) -> (UnmutateVecToken<T, M>, f64) {
148        let mut cplx = current_cplx;
149        let mut tokens = vec![];
150        for &idx in idcs {
151            let spare_cplx = max_cplx - cplx;
152            let mutator = &self.mutators[idx];
153            let el = &mut value[idx];
154            let el_cache = &mut cache.inner[idx];
155
156            let old_cplx = mutator.complexity(el, el_cache);
157
158            let (token, new_cplx) = mutator.random_mutate(el, el_cache, spare_cplx + old_cplx);
159            tokens.push((idx, token));
160            cplx = cplx - old_cplx + new_cplx;
161        }
162        (UnmutateVecToken::Elements(tokens), cplx)
163    }
164    #[coverage(off)]
165    fn mutate_element(
166        &self,
167        value: &mut [T],
168        cache: &mut VecMutatorCache<M::Cache>,
169        step: &mut MutationStep<T, M::MutationStep>,
170        subvalue_provider: &dyn crate::SubValueProvider,
171        idx: usize,
172        current_cplx: f64,
173        spare_cplx: f64,
174    ) -> Option<(UnmutateVecToken<T, M>, f64)> {
175        let mutator = &self.mutators[idx];
176        let el = &mut value[idx];
177        let el_cache = &mut cache.inner[idx];
178        let el_step = &mut step.inner[idx];
179
180        let old_cplx = mutator.complexity(el, el_cache);
181
182        if let Some((token, new_cplx)) =
183            mutator.ordered_mutate(el, el_cache, el_step, subvalue_provider, spare_cplx + old_cplx)
184        {
185            Some((
186                UnmutateVecToken::Element(idx, token),
187                current_cplx - old_cplx + new_cplx,
188            ))
189        } else {
190            None
191        }
192    }
193
194    #[coverage(off)]
195    fn new_input_with_complexity(&self, target_cplx: f64) -> (Vec<T>, f64) {
196        let mut v = Vec::with_capacity(self.len());
197        let mut sum_cplx = 0.0;
198        let mut remaining_cplx = target_cplx;
199        let mut remaining_min_complexity = self.min_complexity();
200        for (i, mutator) in self.mutators.iter().enumerate() {
201            let mut max_cplx_element = (remaining_cplx / ((self.len() - i) as f64)) - remaining_min_complexity;
202            let min_cplx_el = mutator.min_complexity();
203            if min_cplx_el >= max_cplx_element {
204                max_cplx_element = min_cplx_el;
205            }
206            let (x, x_cplx) = mutator.random_arbitrary(max_cplx_element);
207            v.push(x);
208            sum_cplx += x_cplx;
209            remaining_cplx -= x_cplx;
210            remaining_min_complexity -= mutator.min_complexity();
211        }
212        (v, sum_cplx)
213    }
214}
215
216impl<T: Clone + 'static, M: Mutator<T>> Mutator<Vec<T>> for FixedLenVecMutator<T, M> {
217    #[doc(hidden)]
218    type Cache = VecMutatorCache<M::Cache>;
219    #[doc(hidden)]
220    type MutationStep = MutationStep<T, M::MutationStep>;
221    #[doc(hidden)]
222    type ArbitraryStep = ();
223    #[doc(hidden)]
224    type UnmutateToken = UnmutateVecToken<T, M>;
225
226    #[doc(hidden)]
227    #[coverage(off)]
228    fn initialize(&self) {
229        for mutator in self.mutators.iter() {
230            mutator.initialize();
231        }
232        // NOTE: this agrees with the vector mutator
233        let inherent_complexity = if self.has_inherent_complexity {
234            1.0 + if self.mutators[0].min_complexity() == 0.0 {
235                self.mutators.len() as f64
236            } else {
237                0.0
238            }
239        } else {
240            0.0
241        };
242
243        let max_complexity = self.mutators.iter().fold(
244            0.0,
245            #[coverage(off)]
246            |cplx, m| cplx + m.max_complexity(),
247        ) + inherent_complexity;
248        let min_complexity = self.mutators.iter().fold(
249            0.0,
250            #[coverage(off)]
251            |cplx, m| cplx + m.min_complexity(),
252        ) + inherent_complexity;
253        let search_space_complexity = self.mutators.iter().fold(
254            0.0,
255            #[coverage(off)]
256            |cplx, m| cplx + m.global_search_space_complexity(),
257        );
258        self.inherent_complexity.set(inherent_complexity);
259        self.min_complexity.set(min_complexity);
260        self.max_complexity.set(max_complexity);
261        self.search_space_complexity.set(search_space_complexity);
262
263        self.initialized.set(true);
264    }
265
266    #[doc(hidden)]
267    #[coverage(off)]
268    fn default_arbitrary_step(&self) -> Self::ArbitraryStep {}
269
270    #[doc(hidden)]
271    #[coverage(off)]
272    fn is_valid(&self, value: &Vec<T>) -> bool {
273        if value.len() != self.mutators.len() {
274            return false;
275        }
276        for (m, v) in self.mutators.iter().zip(value.iter()) {
277            if !m.is_valid(v) {
278                return false;
279            }
280        }
281        true
282    }
283
284    #[doc(hidden)]
285    #[coverage(off)]
286    fn validate_value(&self, value: &Vec<T>) -> Option<Self::Cache> {
287        if value.len() != self.mutators.len() {
288            return None;
289        }
290        let inner_caches: Vec<_> = value
291            .iter()
292            .zip(self.mutators.iter())
293            .map(
294                #[coverage(off)]
295                |(x, mutator)| mutator.validate_value(x),
296            )
297            .collect::<Option<_>>()?;
298
299        let sum_cplx = value.iter().zip(self.mutators.iter()).zip(inner_caches.iter()).fold(
300            0.0,
301            #[coverage(off)]
302            |cplx, ((v, mutator), cache)| cplx + mutator.complexity(v, cache),
303        );
304
305        let cache = VecMutatorCache {
306            inner: inner_caches,
307            sum_cplx,
308        };
309        Some(cache)
310    }
311
312    #[doc(hidden)]
313    #[coverage(off)]
314    fn default_mutation_step(&self, value: &Vec<T>, cache: &Self::Cache) -> Self::MutationStep {
315        let inner = value
316            .iter()
317            .zip(cache.inner.iter())
318            .zip(self.mutators.iter())
319            .map(
320                #[coverage(off)]
321                |((v, c), m)| m.default_mutation_step(v, c),
322            )
323            .collect::<Vec<_>>();
324        MutationStep {
325            inner,
326            element_step: 0,
327            crossover_steps: vec![CrossoverStep::default(); value.len()],
328        }
329    }
330
331    #[doc(hidden)]
332    #[coverage(off)]
333    fn global_search_space_complexity(&self) -> f64 {
334        self.search_space_complexity.get()
335    }
336
337    #[doc(hidden)]
338    #[coverage(off)]
339    fn max_complexity(&self) -> f64 {
340        self.max_complexity.get()
341    }
342
343    #[doc(hidden)]
344    #[coverage(off)]
345    fn min_complexity(&self) -> f64 {
346        self.min_complexity.get()
347    }
348
349    #[doc(hidden)]
350    #[coverage(off)]
351    fn complexity(&self, _value: &Vec<T>, cache: &Self::Cache) -> f64 {
352        cache.sum_cplx + self.inherent_complexity.get()
353    }
354
355    #[doc(hidden)]
356    #[coverage(off)]
357    fn ordered_arbitrary(&self, _step: &mut Self::ArbitraryStep, max_cplx: f64) -> Option<(Vec<T>, f64)> {
358        if max_cplx < self.min_complexity() {
359            return None;
360        }
361        Some(self.random_arbitrary(max_cplx))
362    }
363
364    #[doc(hidden)]
365    #[coverage(off)]
366    fn random_arbitrary(&self, max_cplx: f64) -> (Vec<T>, f64) {
367        assert!(self.initialized.get());
368        let target_cplx = crate::mutators::gen_f64(&self.rng, 1.0..max_cplx);
369        let (v, sum_cplx) = self.new_input_with_complexity(target_cplx);
370        (v, sum_cplx + self.inherent_complexity.get())
371    }
372
373    #[doc(hidden)]
374    #[coverage(off)]
375    fn ordered_mutate(
376        &self,
377        value: &mut Vec<T>,
378        cache: &mut Self::Cache,
379        step: &mut Self::MutationStep,
380        subvalue_provider: &dyn crate::SubValueProvider,
381        max_cplx: f64,
382    ) -> Option<(Self::UnmutateToken, f64)> {
383        if max_cplx < self.min_complexity() {
384            return None;
385        }
386        if value.is_empty() || self.rng.usize(0..100) == 0 {
387            let (mut v, cplx) = self.random_arbitrary(max_cplx);
388            std::mem::swap(value, &mut v);
389            return Some((UnmutateVecToken::Replace(v), cplx));
390        }
391        if self.rng.u8(..CROSSOVER_RATE) == 0 {
392            let choice = self.rng.usize(..value.len());
393            let step = &mut step.crossover_steps[choice];
394            let old_el_cplx = self.mutators[choice].complexity(&value[choice], &cache.inner[choice]);
395            let current_cplx = self.complexity(value, cache);
396            let max_el_cplx = current_cplx - old_el_cplx - self.inherent_complexity.get();
397            if let Some((el, new_el_cplx)) = step.get_next_subvalue(subvalue_provider, max_el_cplx)
398                && self.mutators[choice].is_valid(el)
399            {
400                let mut el = el.clone();
401                std::mem::swap(&mut value[choice], &mut el);
402                let cplx = cache.sum_cplx - old_el_cplx + new_el_cplx + self.inherent_complexity.get();
403                let token = UnmutateVecToken::ReplaceElement(choice, el);
404                return Some((token, cplx));
405            }
406        }
407        let current_cplx = self.complexity(value, cache);
408        if value.len() > 1 && self.rng.usize(..20) == 0 {
409            let mut idcs = (0..value.len()).collect::<Vec<_>>();
410            self.rng.shuffle(&mut idcs);
411            let count = self.rng.usize(2..=value.len());
412            let idcs = &idcs[..count];
413            Some(self.mutate_elements(value, cache, idcs, current_cplx, max_cplx))
414        } else {
415            let spare_cplx = max_cplx - current_cplx - self.inherent_complexity.get();
416            let idx = step.element_step % value.len();
417            step.element_step += 1;
418            self.mutate_element(value, cache, step, subvalue_provider, idx, current_cplx, spare_cplx)
419                .or_else(
420                    #[coverage(off)]
421                    || Some(self.random_mutate(value, cache, max_cplx)),
422                )
423        }
424    }
425
426    #[doc(hidden)]
427    #[coverage(off)]
428    fn random_mutate(&self, value: &mut Vec<T>, cache: &mut Self::Cache, max_cplx: f64) -> (Self::UnmutateToken, f64) {
429        if value.is_empty() || self.rng.usize(0..100) == 0 {
430            let (mut v, cplx) = self.random_arbitrary(max_cplx);
431            std::mem::swap(value, &mut v);
432            return (UnmutateVecToken::Replace(v), cplx);
433        }
434        let current_cplx = self.complexity(value, cache);
435        if value.len() > 1 && self.rng.usize(..20) == 0 {
436            let mut idcs = (0..value.len()).collect::<Vec<_>>();
437            self.rng.shuffle(&mut idcs);
438            let count = self.rng.usize(2..=value.len());
439            let idcs = &idcs[..count];
440            return self.mutate_elements(value, cache, idcs, current_cplx, max_cplx);
441        }
442        let spare_cplx = max_cplx - current_cplx;
443
444        let idx = self.rng.usize(0..value.len());
445        let el = &mut value[idx];
446        let el_cache = &mut cache.inner[idx];
447
448        let old_el_cplx = self.mutators[idx].complexity(el, el_cache);
449        let (token, new_el_cplx) = self.mutators[idx].random_mutate(el, el_cache, spare_cplx + old_el_cplx);
450
451        (
452            UnmutateVecToken::Element(idx, token),
453            current_cplx - old_el_cplx + new_el_cplx,
454        )
455    }
456
457    #[doc(hidden)]
458    #[coverage(off)]
459    fn unmutate(&self, value: &mut Vec<T>, cache: &mut Self::Cache, t: Self::UnmutateToken) {
460        match t {
461            UnmutateVecToken::Element(idx, inner_t) => {
462                let el = &mut value[idx];
463                self.mutators[idx].unmutate(el, &mut cache.inner[idx], inner_t);
464            }
465            UnmutateVecToken::Elements(tokens) => {
466                for (idx, token) in tokens {
467                    let el = &mut value[idx];
468                    self.mutators[idx].unmutate(el, &mut cache.inner[idx], token);
469                }
470            }
471            UnmutateVecToken::Replace(new_value) => {
472                let _ = std::mem::replace(value, new_value);
473            }
474            UnmutateVecToken::ReplaceElement(idx, el) => {
475                let _ = std::mem::replace(&mut value[idx], el);
476            }
477        }
478    }
479
480    #[doc(hidden)]
481    #[coverage(off)]
482    fn visit_subvalues<'a>(&self, value: &'a Vec<T>, cache: &'a Self::Cache, visit: &mut dyn FnMut(&'a dyn Any, f64)) {
483        if !value.is_empty() {
484            for idx in 0..value.len() {
485                let cplx = self.mutators[idx].complexity(&value[idx], &cache.inner[idx]);
486                visit(&value[idx], cplx);
487            }
488            for ((el, el_cache), mutator) in value.iter().zip(cache.inner.iter()).zip(self.mutators.iter()) {
489                mutator.visit_subvalues(el, el_cache, visit);
490            }
491        }
492    }
493}
494#[cfg(test)]
495mod tests {
496    use super::FixedLenVecMutator;
497    use crate::mutators::integer::U8Mutator;
498    use crate::Mutator;
499    #[test]
500    #[coverage(off)]
501    fn test_constrained_length_mutator() {
502        let m = FixedLenVecMutator::<u8, U8Mutator>::new_with_repeated_mutator(U8Mutator::default(), 3);
503        m.initialize();
504        for _ in 0..100 {
505            let (x, _) = m.ordered_arbitrary(&mut (), 800.0).unwrap();
506            eprintln!("{:?}", x);
507        }
508    }
509}