in lain/src/new_fuzzed.rs [160:294]
fn new_fuzzed<R: Rng>(
mutator: &mut Mutator<R>,
constraints: Option<&Constraints<Self::RangeType>>,
) -> Vec<T> {
const MAX_NUM_ELEMENTS: usize = 0x1000;
let mut min: Self::RangeType;
let mut max: Self::RangeType;
let weight: Weighted;
let max_size: Option<usize>;
let mut used_size: usize = 0;
let mut output: Vec<T>;
trace!(
"Generating random Vec with constraints: {:#X?}",
constraints
);
if T::max_default_object_size() == 0 {
warn!("Size of element in vec is 0... returning early");
return vec![];
}
// if no min/max were supplied, we'll take a conservative approach of 64 elements
match constraints {
Some(constraints) => {
min = constraints.min.unwrap_or(0);
max = constraints.max.unwrap_or(MAX_NUM_ELEMENTS);
if min != max {
if min != 0 && mutator.gen_chance(crate::mutator::CHANCE_TO_IGNORE_MIN_MAX) {
min = 0;
}
if constraints.max.is_some()
&& mutator.gen_chance(crate::mutator::CHANCE_TO_IGNORE_MIN_MAX)
{
// we just hope this doesn't overflow.
max = constraints.max.unwrap() * 2;
}
}
weight = constraints.weighted;
max_size = constraints.max_size;
if let Some(max_size) = constraints.max_size {
max = cmp::min(max, max_size / T::max_default_object_size());
}
}
None => {
min = 0;
max = MAX_NUM_ELEMENTS;
max_size = None;
weight = Weighted::None;
}
}
if max == 0 {
return vec![];
}
if min > max {
min = 0;
}
// If min == max, that means the user probably wants this to be exactly that many elements.
let num_elements: usize = if min == max {
min
} else {
mutator.gen_weighted_range(min, max, weight)
};
output = Vec::with_capacity(num_elements);
let should_reuse_array_item =
mutator.gen_chance(crate::mutator::CHANCE_TO_REPEAT_ARRAY_VALUE);
if should_reuse_array_item {
let element: T = if let Some(ref max_size) = max_size {
T::new_fuzzed(
mutator,
Some(
&Constraints::new()
.max_size(max_size - used_size)
.set_base_size_accounted_for(),
),
)
} else {
T::new_fuzzed(mutator, None)
};
let element_serialized_size = element.serialized_size();
for _i in 0..num_elements {
if let Some(ref max_size) = max_size {
if used_size + element_serialized_size > *max_size {
break;
} else {
used_size += element_serialized_size;
}
}
output.push(element.clone());
}
} else {
for _i in 0..num_elements {
let element: T = if let Some(ref max_size) = max_size {
T::new_fuzzed(
mutator,
Some(
&Constraints::new()
.max_size(max_size - used_size)
.set_base_size_accounted_for(),
),
)
} else {
T::new_fuzzed(mutator, None)
};
let element_serialized_size = element.serialized_size();
if let Some(ref max_size) = max_size {
if used_size + element_serialized_size > *max_size {
break;
} else {
used_size += element_serialized_size;
}
}
output.push(element);
}
}
output
}