lain/
mutatable.rs

1use crate::mutator::Mutator;
2use crate::rand::seq::index;
3use crate::rand::Rng;
4use crate::traits::*;
5use crate::types::*;
6use crate::NewFuzzed;
7
8use num_traits::{Bounded, NumCast};
9use num_traits::{WrappingAdd, WrappingSub};
10use std::cmp::min;
11use std::ops::BitXor;
12
13// we'll shrink by a factor of 1/4, 1/2, 3/4, or down to [0, 8] bytes
14#[derive(Copy, Clone, NewFuzzed, PartialEq)]
15enum VecResizeCount {
16    Quarter,
17    Half,
18    ThreeQuarters,
19    FixedBytes,
20    AllBytes,
21}
22
23#[derive(Copy, Clone, NewFuzzed)]
24enum VecResizeDirection {
25    FromBeginning,
26    FromEnd,
27}
28
29#[derive(Copy, Clone, PartialEq, NewFuzzed)]
30enum VecResizeType {
31    Grow,
32    Shrink,
33}
34
35/// Grows a `Vec`.
36/// This will randomly select to grow by a factor of 1/4, 1/2, 3/4, or a fixed number of bytes
37/// in the range of [1, 8]. Elements may be added randomly to the beginning or end of the the vec
38fn grow_vec<T: NewFuzzed + SerializedSize, R: Rng>(
39    vec: &mut Vec<T>,
40    mutator: &mut Mutator<R>,
41    mut max_size: Option<usize>,
42) {
43    let resize_count = VecResizeCount::new_fuzzed(mutator, None);
44    let mut num_elements = if vec.is_empty() {
45        mutator.gen_range(1, 9)
46    } else {
47        match resize_count {
48            VecResizeCount::Quarter => vec.len() / 4,
49            VecResizeCount::Half => vec.len() / 2,
50            VecResizeCount::ThreeQuarters => vec.len() - (vec.len() / 4),
51            VecResizeCount::FixedBytes => mutator.gen_range(1, 9),
52            VecResizeCount::AllBytes => {
53                mutator.gen_range(1, vec.len() + 1)
54            }
55        }
56    };
57
58    // If we were given a size constraint, we need to respect it
59    if let Some(max_size) = max_size.clone() {
60        num_elements = min(num_elements, max_size / T::max_default_object_size());
61    }
62
63    if num_elements == 0 {
64        return;
65    }
66
67    match VecResizeDirection::new_fuzzed(mutator, None) {
68        VecResizeDirection::FromBeginning => {
69            // to avoid shifting the the entire vec on every iteration, we will
70            // instead allocate a new vec, then extend it with the previous one
71            let mut new_vec = Vec::with_capacity(num_elements);
72            for _i in 0..num_elements {
73                let constraints = max_size.map(|max_size| {
74                    let mut c = Constraints::new();
75                    c.max_size(max_size);
76                    c.base_object_size_accounted_for = true;
77
78                    c
79                });
80
81                let element = T::new_fuzzed(mutator, constraints.as_ref());
82                if let Some(inner_max_size) = max_size {
83                    // if this element is larger than the size we're allotted,
84                    // then let's just exit
85                    let element_size = element.serialized_size();
86                    if element_size > inner_max_size {
87                        break;
88                    }
89
90                    max_size = Some(inner_max_size - element_size);
91                }
92
93                new_vec.push(element);
94            }
95
96            new_vec.append(vec);
97            *vec = new_vec
98        }
99        VecResizeDirection::FromEnd => {
100            for _i in 0..num_elements {
101                let constraints = max_size.map(|max_size| {
102                    let mut c = Constraints::new();
103                    c.max_size(max_size);
104                    c.base_object_size_accounted_for = true;
105
106                    c
107                });
108
109                let element = T::new_fuzzed(mutator, constraints.as_ref());
110                if let Some(inner_max_size) = max_size {
111                    // if this element is larger than the size we're allotted,
112                    // then let's just exit
113                    let element_size = element.serialized_size();
114                    if element_size > inner_max_size {
115                        break;
116                    }
117
118                    max_size = Some(inner_max_size - element_size);
119                }
120
121                vec.push(element);
122            }
123        }
124    }
125}
126
127/// Shrinks a `Vec`.
128/// This will randomly select to resize by a factor of 1/4, 1/2, 3/4, or a fixed number of bytes
129/// in the range of [1, 8]. Elements may be removed randomly from the beginning or end of the the vec
130fn shrink_vec<T, R: Rng>(vec: &mut Vec<T>, mutator: &mut Mutator<R>) {
131    if vec.is_empty() {
132        return;
133    }
134
135    let resize_count = VecResizeCount::new_fuzzed(mutator, None);
136    let mut num_elements = match resize_count {
137        VecResizeCount::Quarter => vec.len() / 4,
138        VecResizeCount::Half => vec.len() / 2,
139        VecResizeCount::ThreeQuarters => vec.len() - (vec.len() / 4),
140        VecResizeCount::FixedBytes => mutator.gen_range(1, 9),
141        VecResizeCount::AllBytes => vec.len(),
142    };
143
144    if num_elements == 0 {
145        num_elements = mutator.gen_range(0, vec.len() + 1);
146    }
147
148    num_elements = std::cmp::min(num_elements, vec.len());
149
150    // Special case probably isn't required here, but better to be explicit
151    if num_elements == vec.len() {
152        vec.drain(..);
153        return;
154    }
155
156    match VecResizeDirection::new_fuzzed(mutator, None) {
157        VecResizeDirection::FromBeginning => {
158            vec.drain(0..num_elements);
159        }
160        VecResizeDirection::FromEnd => {
161            vec.drain(vec.len() - num_elements..);
162        }
163    }
164}
165
166impl<T> Mutatable for Vec<T>
167where
168    T: Mutatable + SerializedSize,
169    T::RangeType: Clone,
170{
171    default type RangeType = usize;
172
173    default fn mutate<R: rand::Rng>(
174        &mut self,
175        mutator: &mut Mutator<R>,
176        constraints: Option<&Constraints<Self::RangeType>>,
177    ) {
178        const CHANCE_TO_RESIZE_VEC: f64 = 0.01;
179
180        // 1% chance to resize this vec
181        if mutator.gen_chance(CHANCE_TO_RESIZE_VEC) {
182            shrink_vec(self, mutator);
183        } else {
184            // Recreate the constraints so that the min/max types match
185            let constraints = constraints.and_then(|c| {
186                if c.max_size.is_none() {
187                    None
188                } else {
189                    let mut new_constraints = Constraints::new();
190                    new_constraints.base_object_size_accounted_for =
191                        c.base_object_size_accounted_for;
192                    new_constraints.max_size = c.max_size;
193
194                    Some(new_constraints)
195                }
196            });
197
198            self.as_mut_slice().mutate(mutator, constraints.as_ref());
199        }
200    }
201}
202
203impl<T> Mutatable for Vec<T>
204where
205    T: Mutatable + NewFuzzed + SerializedSize + Clone,
206    <T as Mutatable>::RangeType: Clone,
207{
208    fn mutate<R: rand::Rng>(
209        &mut self,
210        mutator: &mut Mutator<R>,
211        constraints: Option<&Constraints<Self::RangeType>>,
212    ) {
213        const CHANCE_TO_RESIZE_VEC: f64 = 0.01;
214
215        if T::max_default_object_size() == 0 {
216            return;
217        }
218
219        // we can grow the vector if we have no size constraint or the max size quota hasn't
220        // been fulfilled
221        let can_grow = constraints
222            .map(|c| {
223                c.max_size
224                    .map(|s| s > 0 && s > T::max_default_object_size())
225                    .unwrap_or(true)
226            })
227            .unwrap_or(false);
228
229        if mutator.gen_chance(CHANCE_TO_RESIZE_VEC) {
230            let resize_type = VecResizeType::new_fuzzed(mutator, None);
231            if resize_type == VecResizeType::Grow && can_grow {
232                grow_vec(self, mutator, constraints.and_then(|c| c.max_size));
233            } else {
234                shrink_vec(self, mutator);
235            }
236        } else {
237            // Recreate the constraints so that the min/max types match
238            let constraints = constraints.and_then(|c| {
239                if c.max_size.is_none() {
240                    None
241                } else {
242                    let mut new_constraints = Constraints::new();
243                    new_constraints.base_object_size_accounted_for =
244                        c.base_object_size_accounted_for;
245                    new_constraints.max_size = c.max_size;
246
247                    Some(new_constraints)
248                }
249            });
250
251            self.as_mut_slice().mutate(mutator, constraints.as_ref());
252        }
253    }
254}
255
256impl<T> Mutatable for Vec<T>
257where
258    T: Mutatable + NewFuzzed + SerializedSize,
259    <T as Mutatable>::RangeType: Clone,
260{
261    type RangeType = usize;
262
263    default fn mutate<R: rand::Rng>(
264        &mut self,
265        mutator: &mut Mutator<R>,
266        constraints: Option<&Constraints<Self::RangeType>>,
267    ) {
268        const CHANCE_TO_RESIZE_VEC: f64 = 0.01;
269
270        if T::max_default_object_size() == 0 {
271            return;
272        }
273
274        // we can grow the vector if we have no size constraint or the max size quota hasn't
275        // been fulfilled
276        let can_grow = constraints
277            .map(|c| c.max_size.map(|s| s > 0).unwrap_or(true))
278            .unwrap_or(false);
279
280        if mutator.gen_chance(CHANCE_TO_RESIZE_VEC) {
281            let resize_type = VecResizeType::new_fuzzed(mutator, None);
282            if resize_type == VecResizeType::Grow && can_grow {
283                grow_vec(self, mutator, constraints.and_then(|c| c.max_size));
284            } else {
285                shrink_vec(self, mutator);
286            }
287        } else {
288            // Recreate the constraints so that the min/max types match
289            let constraints = constraints.and_then(|c| {
290                if c.max_size.is_none() {
291                    None
292                } else {
293                    let mut new_constraints = Constraints::new();
294                    new_constraints.base_object_size_accounted_for =
295                        c.base_object_size_accounted_for;
296                    new_constraints.max_size = c.max_size;
297
298                    Some(new_constraints)
299                }
300            });
301
302            self.as_mut_slice().mutate(mutator, constraints.as_ref());
303        }
304    }
305}
306
307impl<T> Mutatable for [T]
308where
309    T: Mutatable + SerializedSize,
310    T::RangeType: Clone,
311{
312    type RangeType = T::RangeType;
313
314    default fn mutate<R: Rng>(
315        &mut self,
316        mutator: &mut Mutator<R>,
317        constraints: Option<&Constraints<Self::RangeType>>,
318    ) {
319        let mut constraints = constraints.and_then(|c| {
320            if c.max_size.is_none() {
321                None
322            } else {
323                let mut new_constraints = Constraints::new();
324                new_constraints.base_object_size_accounted_for = c.base_object_size_accounted_for;
325                new_constraints.max_size = c.max_size;
326
327                Some(new_constraints)
328            }
329        });
330
331        // Check if we can even mutate this item
332        if let Some(max_size) = constraints.as_ref().map(|c| c.max_size).flatten().clone() {
333            if T::min_nonzero_elements_size() < max_size || T::max_default_object_size() > max_size
334            {
335                return;
336            }
337        }
338
339        for item in self.iter_mut() {
340            T::mutate(item, mutator, constraints.as_ref());
341
342            if mutator.should_early_bail_mutation() {
343                return;
344            }
345        }
346    }
347}
348
349impl<T> Mutatable for [T]
350where
351    T: Mutatable + SerializedSize + Clone,
352    T::RangeType: Clone,
353{
354    fn mutate<R: Rng>(
355        &mut self,
356        mutator: &mut Mutator<R>,
357        constraints: Option<&Constraints<Self::RangeType>>,
358    ) {
359        let mut constraints = constraints.and_then(|c| {
360            if c.max_size.is_none() {
361                None
362            } else {
363                let mut new_constraints = Constraints::new();
364                new_constraints.base_object_size_accounted_for = c.base_object_size_accounted_for;
365                new_constraints.max_size = c.max_size;
366
367                Some(new_constraints)
368            }
369        });
370
371        // Check if we can even mutate this item
372        if let Some(max_size) = constraints.as_ref().map(|c| c.max_size).flatten().clone() {
373            if T::min_nonzero_elements_size() < max_size {
374                return;
375            }
376        }
377
378        for item in self.iter_mut() {
379            let parent_constraints = constraints.clone();
380            if let Some(constraints) = constraints.as_mut() {
381                if let Some(max_size) = constraints.max_size.as_mut() {
382                    let prev_size = item.serialized_size();
383
384                    if T::max_default_object_size() > *max_size {
385                        let prev_obj = item.clone();
386
387                        T::mutate(item, mutator, parent_constraints.as_ref());
388                        if item.serialized_size() > *max_size {
389                            // the mutated object is too large --
390                            *item = prev_obj
391                        } else {
392                            continue;
393                        }
394                    } else {
395                        T::mutate(item, mutator, parent_constraints.as_ref());
396                    }
397
398                    let new_size = item.serialized_size();
399
400                    let delta = (new_size as isize) - (prev_size as isize);
401                    *max_size = (*max_size as isize - delta) as usize;
402                }
403            } else {
404                T::mutate(item, mutator, constraints.as_ref());
405            }
406
407            if mutator.should_early_bail_mutation() {
408                return;
409            }
410        }
411    }
412}
413
414impl Mutatable for bool {
415    type RangeType = u8;
416
417    fn mutate<R: Rng>(
418        &mut self,
419        mutator: &mut Mutator<R>,
420        _constraints: Option<&Constraints<Self::RangeType>>,
421    ) {
422        *self = mutator.gen_range(0u8, 2u8) != 0;
423    }
424}
425
426impl<T, I> Mutatable for UnsafeEnum<T, I>
427where
428    T: ToPrimitive<Output = I>,
429    I: BitXor<Output = I>
430        + NumCast
431        + Bounded
432        + Copy
433        + std::fmt::Debug
434        + Default
435        + DangerousNumber<I>
436        + std::fmt::Display
437        + WrappingAdd
438        + WrappingSub,
439{
440    type RangeType = I;
441
442    fn mutate<R: Rng>(
443        &mut self,
444        mutator: &mut Mutator<R>,
445        _constraints: Option<&Constraints<Self::RangeType>>,
446    ) {
447        if let UnsafeEnum::Valid(ref value) = *self {
448            *self = UnsafeEnum::Invalid(value.to_primitive());
449        }
450
451        match *self {
452            UnsafeEnum::Invalid(ref mut value) => {
453                mutator.mutate(value);
454            }
455            _ => unreachable!(),
456        }
457    }
458}
459
460impl Mutatable for AsciiString {
461    type RangeType = u8;
462
463    fn mutate<R: Rng>(
464        &mut self,
465        mutator: &mut Mutator<R>,
466        _constraints: Option<&Constraints<Self::RangeType>>,
467    ) {
468        trace!("performing mutation on an AsciiString");
469
470        // TODO: Implement logic for resizing?
471        let num_mutations = mutator.gen_range(1, self.inner.len());
472        for idx in index::sample(&mut mutator.rng, self.inner.len(), num_mutations).iter() {
473            self.inner[idx] = AsciiChar::new_fuzzed(mutator, None);
474        }
475    }
476}
477
478impl Mutatable for Utf8String {
479    type RangeType = u8;
480
481    fn mutate<R: Rng>(
482        &mut self,
483        mutator: &mut Mutator<R>,
484        _constraints: Option<&Constraints<Self::RangeType>>,
485    ) {
486        trace!("performing mutation on a Utf8String");
487
488        // TODO: Implement logic for resizing?
489        let num_mutations = mutator.gen_range(1, self.inner.len());
490        for idx in index::sample(&mut mutator.rng, self.inner.len(), num_mutations).iter() {
491            self.inner[idx] = Utf8Char::new_fuzzed(mutator, None);
492        }
493    }
494}
495
496macro_rules! impl_mutatable {
497    ( $($name:ident),* ) => {
498        $(
499            impl Mutatable for $name {
500                type RangeType = $name;
501
502                #[inline(always)]
503                fn mutate<R: Rng>(&mut self, mutator: &mut Mutator<R>, _constraints: Option<&Constraints<Self::RangeType>>) {
504                    mutator.mutate(self);
505                }
506            }
507        )*
508    }
509}
510
511impl_mutatable!(u64, u32, u16, u8);
512
513impl Mutatable for i8 {
514    type RangeType = i8;
515
516    #[inline(always)]
517    fn mutate<R: Rng>(
518        &mut self,
519        mutator: &mut Mutator<R>,
520        _constraints: Option<&Constraints<Self::RangeType>>,
521    ) {
522        let mut val = *self as u8;
523        mutator.mutate(&mut val);
524        *self = val as i8;
525    }
526}
527
528impl Mutatable for i16 {
529    type RangeType = i16;
530
531    #[inline(always)]
532    fn mutate<R: Rng>(
533        &mut self,
534        mutator: &mut Mutator<R>,
535        _constraints: Option<&Constraints<Self::RangeType>>,
536    ) {
537        let mut val = *self as u16;
538        mutator.mutate(&mut val);
539        *self = val as i16;
540    }
541}
542
543impl Mutatable for i32 {
544    type RangeType = i32;
545
546    #[inline(always)]
547    fn mutate<R: Rng>(
548        &mut self,
549        mutator: &mut Mutator<R>,
550        _constraints: Option<&Constraints<Self::RangeType>>,
551    ) {
552        let mut val = *self as u32;
553        mutator.mutate(&mut val);
554        *self = val as i32;
555    }
556}
557
558impl Mutatable for i64 {
559    type RangeType = i64;
560
561    #[inline(always)]
562    fn mutate<R: Rng>(
563        &mut self,
564        mutator: &mut Mutator<R>,
565        _constraints: Option<&Constraints<Self::RangeType>>,
566    ) {
567        let mut val = *self as u64;
568        mutator.mutate(&mut val);
569        *self = val as i64;
570    }
571}
572
573impl<T> Mutatable for [T; 0]
574where
575    T: Mutatable,
576{
577    type RangeType = u8;
578
579    fn mutate<R: Rng>(
580        &mut self,
581        _mutator: &mut Mutator<R>,
582        _constraints: Option<&Constraints<Self::RangeType>>,
583    ) {
584        // nop
585    }
586}
587
588impl Mutatable for *const std::ffi::c_void {
589    type RangeType = u8;
590
591    fn mutate<R: Rng>(
592        &mut self,
593        _mutator: &mut Mutator<R>,
594        _constraints: Option<&Constraints<Self::RangeType>>,
595    ) {
596        // nop
597    }
598}
599
600impl Mutatable for *mut std::ffi::c_void {
601    type RangeType = u8;
602
603    fn mutate<R: Rng>(
604        &mut self,
605        _mutator: &mut Mutator<R>,
606        _constraints: Option<&Constraints<Self::RangeType>>,
607    ) {
608        // nop
609    }
610}
611
612impl<T> Mutatable for Option<T>
613where
614    T: Mutatable + NewFuzzed<RangeType = <T as Mutatable>::RangeType>,
615{
616    type RangeType = <T as Mutatable>::RangeType;
617
618    fn mutate<R: Rng>(
619        &mut self,
620        mutator: &mut Mutator<R>,
621        constraints: Option<&Constraints<Self::RangeType>>,
622    ) {
623        const CHANCE_TO_FLIP_OPTION_STATE: f64 = 0.01;
624        match self {
625            Some(inner) => {
626                // small chance to make this None
627                if mutator.gen_chance(CHANCE_TO_FLIP_OPTION_STATE) {
628                    *self = None;
629                } else {
630                    inner.mutate(mutator, constraints);
631                }
632            }
633            None => {
634                if mutator.gen_chance(CHANCE_TO_FLIP_OPTION_STATE) {
635                    let mut new_item = T::new_fuzzed(mutator, constraints);
636
637                    *self = Some(new_item);
638                }
639            }
640        }
641    }
642}
643
644impl<T> Mutatable for Box<T>
645where
646    T: Mutatable + NewFuzzed<RangeType = <T as Mutatable>::RangeType>,
647{
648    type RangeType = <T as Mutatable>::RangeType;
649
650    fn mutate<R: Rng>(
651        &mut self,
652        mutator: &mut Mutator<R>,
653        constraints: Option<&Constraints<Self::RangeType>>,
654    ) {
655        self.as_mut().mutate(mutator, constraints);
656    }
657}
658
659macro_rules! impl_mutatable_array {
660    ( $($size:expr),* ) => {
661        $(
662            impl<T> Mutatable for [T; $size]
663            where
664                T: Mutatable + SerializedSize,
665                T::RangeType: Clone,
666            {
667                type RangeType = T::RangeType;
668
669                #[inline(always)]
670                fn mutate<R: Rng>(&mut self, mutator: &mut Mutator<R>, constraints: Option<&Constraints<Self::RangeType>>) {
671                    // Treat this as a slice
672                    self[..].mutate(mutator, constraints);
673                }
674            }
675        )*
676    }
677}
678
679impl_mutatable_array!(
680    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
681    27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
682    51, 52, 53, 54, 55, 56, 57, 58, 59, 60
683);