libafl_bolts: more rands
improvements (#2096)
* rands: add missing inline directives See: - https://nnethercote.github.io/perf-book/inlining.html - https://users.rust-lang.org/t/enable-cross-crate-inlining-without-suggesting-inlining/55004/6 * rands: better fast_bound() signature
This commit is contained in:
parent
0f42efa12b
commit
1e8667a9f9
@ -67,8 +67,8 @@ impl From<CorpusId> for usize {
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! random_corpus_id {
|
macro_rules! random_corpus_id {
|
||||||
($corpus:expr, $rand:expr) => {{
|
($corpus:expr, $rand:expr) => {{
|
||||||
let cnt = $corpus.count() as u64;
|
let cnt = $corpus.count();
|
||||||
let nth = $rand.below(cnt) as usize;
|
let nth = $rand.below(cnt);
|
||||||
$corpus.nth(nth)
|
$corpus.nth(nth)
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
@ -78,8 +78,8 @@ macro_rules! random_corpus_id {
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! random_corpus_id_with_disabled {
|
macro_rules! random_corpus_id_with_disabled {
|
||||||
($corpus:expr, $rand:expr) => {{
|
($corpus:expr, $rand:expr) => {{
|
||||||
let cnt = $corpus.count_all() as u64;
|
let cnt = $corpus.count_all();
|
||||||
let nth = $rand.below(cnt) as usize;
|
let nth = $rand.below(cnt);
|
||||||
$corpus.nth_from_all(nth)
|
$corpus.nth_from_all(nth)
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
@ -76,13 +76,13 @@ where
|
|||||||
.last()
|
.last()
|
||||||
.map_or(self.automaton.init_state, |last| {
|
.map_or(self.automaton.init_state, |last| {
|
||||||
let triggers = &self.automaton.pda[last.state];
|
let triggers = &self.automaton.pda[last.state];
|
||||||
let idx = state.rand_mut().below(triggers.len() as u64) as usize;
|
let idx = state.rand_mut().below(triggers.len());
|
||||||
triggers[idx].dest
|
triggers[idx].dest
|
||||||
});
|
});
|
||||||
|
|
||||||
while current_state != final_state {
|
while current_state != final_state {
|
||||||
let triggers = &self.automaton.pda[current_state];
|
let triggers = &self.automaton.pda[current_state];
|
||||||
let idx = state.rand_mut().below(triggers.len() as u64) as usize;
|
let idx = state.rand_mut().below(triggers.len());
|
||||||
let trigger = &triggers[idx];
|
let trigger = &triggers[idx];
|
||||||
input
|
input
|
||||||
.terminals_mut()
|
.terminals_mut()
|
||||||
|
@ -101,7 +101,7 @@ where
|
|||||||
S: HasRand,
|
S: HasRand,
|
||||||
{
|
{
|
||||||
fn generate(&mut self, state: &mut S) -> Result<BytesInput, Error> {
|
fn generate(&mut self, state: &mut S) -> Result<BytesInput, Error> {
|
||||||
let mut size = state.rand_mut().below(self.max_size as u64);
|
let mut size = state.rand_mut().below(self.max_size);
|
||||||
if size == 0 {
|
if size == 0 {
|
||||||
size = 1;
|
size = 1;
|
||||||
}
|
}
|
||||||
@ -141,7 +141,7 @@ where
|
|||||||
S: HasRand,
|
S: HasRand,
|
||||||
{
|
{
|
||||||
fn generate(&mut self, state: &mut S) -> Result<BytesInput, Error> {
|
fn generate(&mut self, state: &mut S) -> Result<BytesInput, Error> {
|
||||||
let mut size = state.rand_mut().below(self.max_size as u64);
|
let mut size = state.rand_mut().below(self.max_size);
|
||||||
if size == 0 {
|
if size == 0 {
|
||||||
size = 1;
|
size = 1;
|
||||||
}
|
}
|
||||||
|
@ -159,8 +159,8 @@ impl<S: HasRand> Mutator<EncodedInput, S> for EncodedDeleteMutator {
|
|||||||
return Ok(MutationResult::Skipped);
|
return Ok(MutationResult::Skipped);
|
||||||
}
|
}
|
||||||
|
|
||||||
let off = state.rand_mut().below(size as u64) as usize;
|
let off = state.rand_mut().below(size);
|
||||||
let len = state.rand_mut().below((size - off) as u64) as usize;
|
let len = state.rand_mut().below(size - off);
|
||||||
input.codes_mut().drain(off..off + len);
|
input.codes_mut().drain(off..off + len);
|
||||||
|
|
||||||
Ok(MutationResult::Mutated)
|
Ok(MutationResult::Mutated)
|
||||||
@ -198,8 +198,8 @@ where
|
|||||||
if size == 0 {
|
if size == 0 {
|
||||||
return Ok(MutationResult::Skipped);
|
return Ok(MutationResult::Skipped);
|
||||||
}
|
}
|
||||||
let off = state.rand_mut().below((size + 1) as u64) as usize;
|
let off = state.rand_mut().below(size + 1);
|
||||||
let mut len = 1 + state.rand_mut().below(min(16, size as u64)) as usize;
|
let mut len = 1 + state.rand_mut().below(min(16, size));
|
||||||
|
|
||||||
if size + len > max_size {
|
if size + len > max_size {
|
||||||
if max_size > size {
|
if max_size > size {
|
||||||
@ -212,7 +212,7 @@ where
|
|||||||
let from = if size == len {
|
let from = if size == len {
|
||||||
0
|
0
|
||||||
} else {
|
} else {
|
||||||
state.rand_mut().below((size - len) as u64) as usize
|
state.rand_mut().below(size - len)
|
||||||
};
|
};
|
||||||
|
|
||||||
input.codes_mut().resize(size + len, 0);
|
input.codes_mut().resize(size + len, 0);
|
||||||
@ -254,9 +254,9 @@ impl<S: HasRand> Mutator<EncodedInput, S> for EncodedCopyMutator {
|
|||||||
return Ok(MutationResult::Skipped);
|
return Ok(MutationResult::Skipped);
|
||||||
}
|
}
|
||||||
|
|
||||||
let from = state.rand_mut().below(size as u64) as usize;
|
let from = state.rand_mut().below(size);
|
||||||
let to = state.rand_mut().below(size as u64) as usize;
|
let to = state.rand_mut().below(size);
|
||||||
let len = 1 + state.rand_mut().below((size - max(from, to)) as u64) as usize;
|
let len = 1 + state.rand_mut().below(size - max(from, to));
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
buffer_self_copy(input.codes_mut(), from, to, len);
|
buffer_self_copy(input.codes_mut(), from, to, len);
|
||||||
@ -310,9 +310,9 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
let max_size = state.max_size();
|
let max_size = state.max_size();
|
||||||
let from = state.rand_mut().below(other_size as u64) as usize;
|
let from = state.rand_mut().below(other_size);
|
||||||
let to = state.rand_mut().below(size as u64) as usize;
|
let to = state.rand_mut().below(size);
|
||||||
let mut len = 1 + state.rand_mut().below((other_size - from) as u64) as usize;
|
let mut len = 1 + state.rand_mut().below(other_size - from);
|
||||||
|
|
||||||
if size + len > max_size {
|
if size + len > max_size {
|
||||||
if max_size > size {
|
if max_size > size {
|
||||||
@ -383,9 +383,9 @@ where
|
|||||||
return Ok(MutationResult::Skipped);
|
return Ok(MutationResult::Skipped);
|
||||||
}
|
}
|
||||||
|
|
||||||
let from = state.rand_mut().below(other_size as u64) as usize;
|
let from = state.rand_mut().below(other_size);
|
||||||
let len = state.rand_mut().below(min(other_size - from, size) as u64) as usize;
|
let len = state.rand_mut().below(min(other_size - from, size));
|
||||||
let to = state.rand_mut().below((size - len) as u64) as usize;
|
let to = state.rand_mut().below(size - len);
|
||||||
|
|
||||||
let other_testcase = state.corpus().get_from_all(idx)?.borrow_mut();
|
let other_testcase = state.corpus().get_from_all(idx)?.borrow_mut();
|
||||||
// no need to load the input again, it'll already be present at this point.
|
// no need to load the input again, it'll already be present at this point.
|
||||||
|
@ -20,7 +20,7 @@ use crate::{
|
|||||||
Error, HasMetadata,
|
Error, HasMetadata,
|
||||||
};
|
};
|
||||||
|
|
||||||
const RECUR_THRESHOLD: u64 = 5;
|
const RECUR_THRESHOLD: usize = 5;
|
||||||
|
|
||||||
/// A random mutator for grammar fuzzing
|
/// A random mutator for grammar fuzzing
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -41,7 +41,7 @@ where
|
|||||||
input: &mut GramatronInput,
|
input: &mut GramatronInput,
|
||||||
) -> Result<MutationResult, Error> {
|
) -> Result<MutationResult, Error> {
|
||||||
if !input.terminals().is_empty() {
|
if !input.terminals().is_empty() {
|
||||||
let size = state.rand_mut().below(input.terminals().len() as u64 + 1) as usize;
|
let size = state.rand_mut().below(input.terminals().len() + 1);
|
||||||
input.terminals_mut().truncate(size);
|
input.terminals_mut().truncate(size);
|
||||||
}
|
}
|
||||||
if self.generator.append_generated_terminals(input, state) > 0 {
|
if self.generator.append_generated_terminals(input, state) > 0 {
|
||||||
@ -119,7 +119,7 @@ where
|
|||||||
|
|
||||||
let idx = random_corpus_id!(state.corpus(), state.rand_mut());
|
let idx = random_corpus_id!(state.corpus(), state.rand_mut());
|
||||||
|
|
||||||
let insert_at = state.rand_mut().below(input.terminals().len() as u64) as usize;
|
let insert_at = state.rand_mut().below(input.terminals().len());
|
||||||
|
|
||||||
let rand_num = state.rand_mut().next();
|
let rand_num = state.rand_mut().next();
|
||||||
|
|
||||||
@ -212,11 +212,11 @@ where
|
|||||||
let chosen_nums = self.counters.get(&chosen).unwrap().0;
|
let chosen_nums = self.counters.get(&chosen).unwrap().0;
|
||||||
|
|
||||||
#[allow(clippy::cast_sign_loss, clippy::pedantic)]
|
#[allow(clippy::cast_sign_loss, clippy::pedantic)]
|
||||||
let mut first = state.rand_mut().below(chosen_nums as u64 - 1) as i64;
|
let mut first = state.rand_mut().below(chosen_nums - 1) as i64;
|
||||||
#[allow(clippy::cast_sign_loss, clippy::pedantic)]
|
#[allow(clippy::cast_sign_loss, clippy::pedantic)]
|
||||||
let mut second = state
|
let mut second = state
|
||||||
.rand_mut()
|
.rand_mut()
|
||||||
.between(first as u64 + 1, chosen_nums as u64 - 1) as i64;
|
.between(first as usize + 1, chosen_nums - 1) as i64;
|
||||||
|
|
||||||
let mut idx_1 = 0;
|
let mut idx_1 = 0;
|
||||||
let mut idx_2 = 0;
|
let mut idx_2 = 0;
|
||||||
|
@ -252,10 +252,10 @@ where
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let token_find = state.rand_mut().below(tokens_len as u64) as usize;
|
let token_find = state.rand_mut().below(tokens_len);
|
||||||
let mut token_replace = state.rand_mut().below(tokens_len as u64) as usize;
|
let mut token_replace = state.rand_mut().below(tokens_len);
|
||||||
if token_find == token_replace {
|
if token_find == token_replace {
|
||||||
token_replace = state.rand_mut().below(tokens_len as u64) as usize;
|
token_replace = state.rand_mut().below(tokens_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
let stop_at_first = state.rand_mut().coinflip(0.5);
|
let stop_at_first = state.rand_mut().coinflip(0.5);
|
||||||
@ -268,7 +268,7 @@ where
|
|||||||
let mut mutated = MutationResult::Skipped;
|
let mut mutated = MutationResult::Skipped;
|
||||||
|
|
||||||
let gen = generalised_meta.generalized_mut();
|
let gen = generalised_meta.generalized_mut();
|
||||||
let rand_idx = fast_bound(rand_idx, gen.len() as u64) as usize;
|
let rand_idx = fast_bound(rand_idx, gen.len());
|
||||||
|
|
||||||
'first: for item in &mut gen[..rand_idx] {
|
'first: for item in &mut gen[..rand_idx] {
|
||||||
if let GeneralizedItem::Bytes(bytes) = item {
|
if let GeneralizedItem::Bytes(bytes) = item {
|
||||||
@ -360,10 +360,8 @@ where
|
|||||||
{
|
{
|
||||||
self.gap_indices.push(i);
|
self.gap_indices.push(i);
|
||||||
}
|
}
|
||||||
let min_idx =
|
let min_idx = self.gap_indices[state.rand_mut().below(self.gap_indices.len())];
|
||||||
self.gap_indices[state.rand_mut().below(self.gap_indices.len() as u64) as usize];
|
let max_idx = self.gap_indices[state.rand_mut().below(self.gap_indices.len())];
|
||||||
let max_idx =
|
|
||||||
self.gap_indices[state.rand_mut().below(self.gap_indices.len() as u64) as usize];
|
|
||||||
|
|
||||||
let (min_idx, max_idx) = (min(min_idx, max_idx), max(min_idx, max_idx));
|
let (min_idx, max_idx) = (min(min_idx, max_idx), max(min_idx, max_idx));
|
||||||
|
|
||||||
|
@ -368,7 +368,7 @@ where
|
|||||||
mode: MOptMode,
|
mode: MOptMode,
|
||||||
finds_before: usize,
|
finds_before: usize,
|
||||||
mutations: MT,
|
mutations: MT,
|
||||||
max_stack_pow: u64,
|
max_stack_pow: usize,
|
||||||
phantom: PhantomData<(I, S)>,
|
phantom: PhantomData<(I, S)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -521,7 +521,7 @@ where
|
|||||||
pub fn new(
|
pub fn new(
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
mutations: MT,
|
mutations: MT,
|
||||||
max_stack_pow: u64,
|
max_stack_pow: usize,
|
||||||
swarm_num: usize,
|
swarm_num: usize,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
if !state.has_metadata::<MOpt>() {
|
if !state.has_metadata::<MOpt>() {
|
||||||
|
@ -44,7 +44,7 @@ where
|
|||||||
if input.parts().is_empty() {
|
if input.parts().is_empty() {
|
||||||
Ok(MutationResult::Skipped)
|
Ok(MutationResult::Skipped)
|
||||||
} else {
|
} else {
|
||||||
let selected = state.rand_mut().below(input.parts().len() as u64) as usize;
|
let selected = state.rand_mut().below(input.parts().len());
|
||||||
let mutated = input.part_mut(selected).unwrap();
|
let mutated = input.part_mut(selected).unwrap();
|
||||||
self.mutate(state, mutated)
|
self.mutate(state, mutated)
|
||||||
}
|
}
|
||||||
@ -153,7 +153,7 @@ where
|
|||||||
.map(|(idx, part)| (idx, part.bytes().len()));
|
.map(|(idx, part)| (idx, part.bytes().len()));
|
||||||
|
|
||||||
if let Some((part_idx, size)) = maybe_size {
|
if let Some((part_idx, size)) = maybe_size {
|
||||||
let target = state.rand_mut().below(size as u64) as usize;
|
let target = state.rand_mut().below(size);
|
||||||
let range = rand_range(state, other_size, min(other_size, size - target));
|
let range = rand_range(state, other_size, min(other_size, size - target));
|
||||||
|
|
||||||
let [part, chosen] = match part_idx.cmp(&choice) {
|
let [part, chosen] = match part_idx.cmp(&choice) {
|
||||||
@ -195,7 +195,7 @@ where
|
|||||||
drop(other_testcase);
|
drop(other_testcase);
|
||||||
let size = part.bytes().len();
|
let size = part.bytes().len();
|
||||||
|
|
||||||
let target = state.rand_mut().below(size as u64) as usize;
|
let target = state.rand_mut().below(size);
|
||||||
let range = rand_range(state, other_size, min(other_size, size - target));
|
let range = rand_range(state, other_size, min(other_size, size - target));
|
||||||
|
|
||||||
let other_testcase = state.corpus().get(idx)?.borrow_mut();
|
let other_testcase = state.corpus().get(idx)?.borrow_mut();
|
||||||
@ -257,7 +257,7 @@ where
|
|||||||
.map(|(idx, part)| (idx, part.bytes().len()));
|
.map(|(idx, part)| (idx, part.bytes().len()));
|
||||||
|
|
||||||
if let Some((part_idx, size)) = maybe_size {
|
if let Some((part_idx, size)) = maybe_size {
|
||||||
let target = state.rand_mut().below(size as u64) as usize;
|
let target = state.rand_mut().below(size);
|
||||||
let range = rand_range(state, other_size, min(other_size, size - target));
|
let range = rand_range(state, other_size, min(other_size, size - target));
|
||||||
|
|
||||||
let [part, chosen] = match part_idx.cmp(&choice) {
|
let [part, chosen] = match part_idx.cmp(&choice) {
|
||||||
@ -299,7 +299,7 @@ where
|
|||||||
drop(other_testcase);
|
drop(other_testcase);
|
||||||
let size = part.bytes().len();
|
let size = part.bytes().len();
|
||||||
|
|
||||||
let target = state.rand_mut().below(size as u64) as usize;
|
let target = state.rand_mut().below(size);
|
||||||
let range = rand_range(state, other_size, min(other_size, size - target));
|
let range = rand_range(state, other_size, min(other_size, size - target));
|
||||||
|
|
||||||
let other_testcase = state.corpus().get(idx)?.borrow_mut();
|
let other_testcase = state.corpus().get(idx)?.borrow_mut();
|
||||||
|
@ -65,9 +65,9 @@ pub fn buffer_set<T: Clone>(data: &mut [T], from: usize, len: usize, val: T) {
|
|||||||
/// This problem corresponds to: <https://oeis.org/A059036>
|
/// This problem corresponds to: <https://oeis.org/A059036>
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn rand_range<S: HasRand>(state: &mut S, upper: usize, max_len: usize) -> Range<usize> {
|
pub fn rand_range<S: HasRand>(state: &mut S, upper: usize, max_len: usize) -> Range<usize> {
|
||||||
let len = 1 + state.rand_mut().below(max_len as u64) as usize;
|
let len = 1 + state.rand_mut().below(max_len);
|
||||||
// sample from [1..upper + len]
|
// sample from [1..upper + len]
|
||||||
let mut offset2 = 1 + state.rand_mut().below((upper + len - 1) as u64) as usize;
|
let mut offset2 = 1 + state.rand_mut().below(upper + len - 1);
|
||||||
let offset1 = offset2.saturating_sub(len);
|
let offset1 = offset2.saturating_sub(len);
|
||||||
if offset2 > upper {
|
if offset2 > upper {
|
||||||
offset2 = upper;
|
offset2 = upper;
|
||||||
@ -77,7 +77,7 @@ pub fn rand_range<S: HasRand>(state: &mut S, upper: usize, max_len: usize) -> Ra
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The max value that will be added or subtracted during add mutations
|
/// The max value that will be added or subtracted during add mutations
|
||||||
pub const ARITH_MAX: u64 = 35;
|
pub const ARITH_MAX: usize = 35;
|
||||||
|
|
||||||
/// Interesting 8-bit values from AFL
|
/// Interesting 8-bit values from AFL
|
||||||
pub const INTERESTING_8: [i8; 9] = [-128, -1, 0, 1, 16, 32, 64, 100, 127];
|
pub const INTERESTING_8: [i8; 9] = [-128, -1, 0, 1, 16, 32, 64, 100, 127];
|
||||||
@ -413,8 +413,8 @@ macro_rules! interesting_mutator_impl {
|
|||||||
Ok(MutationResult::Skipped)
|
Ok(MutationResult::Skipped)
|
||||||
} else {
|
} else {
|
||||||
let bytes = input.bytes_mut();
|
let bytes = input.bytes_mut();
|
||||||
let upper_bound = (bytes.len() + 1 - size_of::<$size>()) as u64;
|
let upper_bound = (bytes.len() + 1 - size_of::<$size>());
|
||||||
let idx = state.rand_mut().below(upper_bound) as usize;
|
let idx = state.rand_mut().below(upper_bound);
|
||||||
let val = *state.rand_mut().choose(&$interesting) as $size;
|
let val = *state.rand_mut().choose(&$interesting) as $size;
|
||||||
let new_bytes = match state.rand_mut().choose(&[0, 1]) {
|
let new_bytes = match state.rand_mut().choose(&[0, 1]) {
|
||||||
0 => val.to_be_bytes(),
|
0 => val.to_be_bytes(),
|
||||||
@ -548,8 +548,8 @@ where
|
|||||||
return Ok(MutationResult::Skipped);
|
return Ok(MutationResult::Skipped);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut amount = 1 + state.rand_mut().below(16) as usize;
|
let mut amount = 1 + state.rand_mut().below(16);
|
||||||
let offset = state.rand_mut().below(size as u64 + 1) as usize;
|
let offset = state.rand_mut().below(size + 1);
|
||||||
|
|
||||||
if size + amount > max_size {
|
if size + amount > max_size {
|
||||||
if max_size > size {
|
if max_size > size {
|
||||||
@ -559,7 +559,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let val = input.bytes()[state.rand_mut().below(size as u64) as usize];
|
let val = input.bytes()[state.rand_mut().below(size)];
|
||||||
|
|
||||||
input.bytes_mut().resize(size + amount, 0);
|
input.bytes_mut().resize(size + amount, 0);
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -602,8 +602,8 @@ where
|
|||||||
return Ok(MutationResult::Skipped);
|
return Ok(MutationResult::Skipped);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut amount = 1 + state.rand_mut().below(16) as usize;
|
let mut amount = 1 + state.rand_mut().below(16);
|
||||||
let offset = state.rand_mut().below(size as u64 + 1) as usize;
|
let offset = state.rand_mut().below(size + 1);
|
||||||
|
|
||||||
if size + amount > max_size {
|
if size + amount > max_size {
|
||||||
if max_size > size {
|
if max_size > size {
|
||||||
@ -733,7 +733,7 @@ where
|
|||||||
return Ok(MutationResult::Skipped);
|
return Ok(MutationResult::Skipped);
|
||||||
}
|
}
|
||||||
|
|
||||||
let target = state.rand_mut().below(size as u64) as usize;
|
let target = state.rand_mut().below(size);
|
||||||
let range = rand_range(state, size, size - target);
|
let range = rand_range(state, size, size - target);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -776,7 +776,7 @@ where
|
|||||||
return Ok(MutationResult::Skipped);
|
return Ok(MutationResult::Skipped);
|
||||||
}
|
}
|
||||||
|
|
||||||
let target = state.rand_mut().below(size as u64) as usize;
|
let target = state.rand_mut().below(size);
|
||||||
// make sure that the sampled range is both in bounds and of an acceptable size
|
// make sure that the sampled range is both in bounds and of an acceptable size
|
||||||
let max_insert_len = min(size - target, state.max_size() - size);
|
let max_insert_len = min(size - target, state.max_size() - size);
|
||||||
let range = rand_range(state, size, min(16, max_insert_len));
|
let range = rand_range(state, size, min(16, max_insert_len));
|
||||||
@ -1091,7 +1091,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
let range = rand_range(state, other_size, min(other_size, max_size - size));
|
let range = rand_range(state, other_size, min(other_size, max_size - size));
|
||||||
let target = state.rand_mut().below(size as u64) as usize;
|
let target = state.rand_mut().below(size);
|
||||||
|
|
||||||
let other_testcase = state.corpus().get_from_all(idx)?.borrow_mut();
|
let other_testcase = state.corpus().get_from_all(idx)?.borrow_mut();
|
||||||
// No need to load the input again, it'll still be cached.
|
// No need to load the input again, it'll still be cached.
|
||||||
@ -1172,7 +1172,7 @@ where
|
|||||||
return Ok(MutationResult::Skipped);
|
return Ok(MutationResult::Skipped);
|
||||||
}
|
}
|
||||||
|
|
||||||
let target = state.rand_mut().below(size as u64) as usize;
|
let target = state.rand_mut().below(size);
|
||||||
let range = rand_range(state, other_size, min(other_size, size - target));
|
let range = rand_range(state, other_size, min(other_size, size - target));
|
||||||
|
|
||||||
let other_testcase = state.corpus().get_from_all(idx)?.borrow_mut();
|
let other_testcase = state.corpus().get_from_all(idx)?.borrow_mut();
|
||||||
@ -1243,13 +1243,13 @@ where
|
|||||||
let (f, l) = locate_diffs(input.bytes(), other.bytes());
|
let (f, l) = locate_diffs(input.bytes(), other.bytes());
|
||||||
|
|
||||||
if f != l && f >= 0 && l >= 2 {
|
if f != l && f >= 0 && l >= 2 {
|
||||||
(f as u64, l as u64)
|
(f as usize, l as usize)
|
||||||
} else {
|
} else {
|
||||||
return Ok(MutationResult::Skipped);
|
return Ok(MutationResult::Skipped);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let split_at = state.rand_mut().between(first_diff, last_diff) as usize;
|
let split_at = state.rand_mut().between(first_diff, last_diff);
|
||||||
|
|
||||||
let other_testcase = state.corpus().get_from_all(idx)?.borrow_mut();
|
let other_testcase = state.corpus().get_from_all(idx)?.borrow_mut();
|
||||||
// Input will already be loaded.
|
// Input will already be loaded.
|
||||||
|
@ -115,7 +115,7 @@ where
|
|||||||
{
|
{
|
||||||
name: Cow<'static, str>,
|
name: Cow<'static, str>,
|
||||||
mutations: MT,
|
mutations: MT,
|
||||||
max_stack_pow: u64,
|
max_stack_pow: usize,
|
||||||
phantom: PhantomData<(I, S)>,
|
phantom: PhantomData<(I, S)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,7 +186,7 @@ where
|
|||||||
/// Get the next mutation to apply
|
/// Get the next mutation to apply
|
||||||
fn schedule(&self, state: &mut S, _: &I) -> MutationId {
|
fn schedule(&self, state: &mut S, _: &I) -> MutationId {
|
||||||
debug_assert!(self.mutations.len() != 0);
|
debug_assert!(self.mutations.len() != 0);
|
||||||
state.rand_mut().below(self.mutations.len() as u64).into()
|
state.rand_mut().below(self.mutations.len()).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,7 +209,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new [`StdScheduledMutator`] instance specifying mutations and the maximun number of iterations
|
/// Create a new [`StdScheduledMutator`] instance specifying mutations and the maximun number of iterations
|
||||||
pub fn with_max_stack_pow(mutations: MT, max_stack_pow: u64) -> Self {
|
pub fn with_max_stack_pow(mutations: MT, max_stack_pow: usize) -> Self {
|
||||||
StdScheduledMutator {
|
StdScheduledMutator {
|
||||||
name: Cow::from(format!(
|
name: Cow::from(format!(
|
||||||
"StdScheduledMutator[{}]",
|
"StdScheduledMutator[{}]",
|
||||||
@ -437,7 +437,7 @@ where
|
|||||||
/// Get the next mutation to apply
|
/// Get the next mutation to apply
|
||||||
fn schedule(&self, state: &mut S, _: &I) -> MutationId {
|
fn schedule(&self, state: &mut S, _: &I) -> MutationId {
|
||||||
debug_assert!(MT::LEN != 0);
|
debug_assert!(MT::LEN != 0);
|
||||||
state.rand_mut().below(MT::LEN as u64).into()
|
state.rand_mut().below(MT::LEN).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scheduled_mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
|
fn scheduled_mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
|
||||||
|
@ -66,7 +66,7 @@ fn choose_start<R: Rand>(
|
|||||||
bytes: &[u8],
|
bytes: &[u8],
|
||||||
meta: &StringIdentificationMetadata,
|
meta: &StringIdentificationMetadata,
|
||||||
) -> Option<(usize, usize)> {
|
) -> Option<(usize, usize)> {
|
||||||
let idx = rand.below(bytes.len() as u64) as usize;
|
let idx = rand.below(bytes.len());
|
||||||
let mut options = Vec::new();
|
let mut options = Vec::new();
|
||||||
for (start, range) in meta.ranges() {
|
for (start, range) in meta.ranges() {
|
||||||
if idx
|
if idx
|
||||||
@ -83,9 +83,9 @@ fn choose_start<R: Rand>(
|
|||||||
_ => {
|
_ => {
|
||||||
// bias towards longer strings
|
// bias towards longer strings
|
||||||
options.sort_by_cached_key(|(_, entries)| entries.count_ones());
|
options.sort_by_cached_key(|(_, entries)| entries.count_ones());
|
||||||
let selected = libafl_bolts::math::integer_sqrt(
|
let selected =
|
||||||
rand.below((options.len() * options.len()) as u64),
|
libafl_bolts::math::integer_sqrt(rand.below(options.len() * options.len()) as u64)
|
||||||
) as usize;
|
as usize;
|
||||||
Some((options[selected].0, options[selected].1.len()))
|
Some((options[selected].0, options[selected].1.len()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -133,7 +133,7 @@ fn choose_category_range<R: Rand>(
|
|||||||
string: &str,
|
string: &str,
|
||||||
) -> (Range<usize>, &'static [(u32, u32)]) {
|
) -> (Range<usize>, &'static [(u32, u32)]) {
|
||||||
let chars = string.char_indices().collect::<Vec<_>>();
|
let chars = string.char_indices().collect::<Vec<_>>();
|
||||||
let idx = rand.below(chars.len() as u64) as usize;
|
let idx = rand.below(chars.len());
|
||||||
let c = chars[idx].1;
|
let c = chars[idx].1;
|
||||||
|
|
||||||
// figure out the categories for this char
|
// figure out the categories for this char
|
||||||
@ -160,7 +160,7 @@ fn choose_category_range<R: Rand>(
|
|||||||
)
|
)
|
||||||
});
|
});
|
||||||
let options = categories.len() * categories.len();
|
let options = categories.len() * categories.len();
|
||||||
let selected_idx = libafl_bolts::math::integer_sqrt(rand.below(options as u64)) as usize;
|
let selected_idx = libafl_bolts::math::integer_sqrt(rand.below(options) as u64) as usize;
|
||||||
|
|
||||||
let selected = categories[selected_idx];
|
let selected = categories[selected_idx];
|
||||||
|
|
||||||
@ -177,7 +177,7 @@ fn choose_category_range<R: Rand>(
|
|||||||
|
|
||||||
fn choose_subcategory_range<R: Rand>(rand: &mut R, string: &str) -> (Range<usize>, (u32, u32)) {
|
fn choose_subcategory_range<R: Rand>(rand: &mut R, string: &str) -> (Range<usize>, (u32, u32)) {
|
||||||
let chars = string.char_indices().collect::<Vec<_>>();
|
let chars = string.char_indices().collect::<Vec<_>>();
|
||||||
let idx = rand.below(chars.len() as u64) as usize;
|
let idx = rand.below(chars.len());
|
||||||
let c = chars[idx].1;
|
let c = chars[idx].1;
|
||||||
|
|
||||||
// figure out the categories for this char
|
// figure out the categories for this char
|
||||||
@ -197,7 +197,7 @@ fn choose_subcategory_range<R: Rand>(rand: &mut R, string: &str) -> (Range<usize
|
|||||||
|
|
||||||
subcategories.sort_by_key(|&(min, max)| Reverse(max - min + 1));
|
subcategories.sort_by_key(|&(min, max)| Reverse(max - min + 1));
|
||||||
let options = subcategories.len() * subcategories.len();
|
let options = subcategories.len() * subcategories.len();
|
||||||
let selected_idx = libafl_bolts::math::integer_sqrt(rand.below(options as u64)) as usize;
|
let selected_idx = libafl_bolts::math::integer_sqrt(rand.below(options) as u64) as usize;
|
||||||
let selected = subcategories[selected_idx];
|
let selected = subcategories[selected_idx];
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -238,7 +238,7 @@ fn rand_replace_range<S: HasRand + HasMaxSize, F: Fn(&mut S) -> char>(
|
|||||||
return MutationResult::Skipped;
|
return MutationResult::Skipped;
|
||||||
}
|
}
|
||||||
|
|
||||||
let replace_len = state.rand_mut().below(MAX_CHARS as u64) as usize;
|
let replace_len = state.rand_mut().below(MAX_CHARS);
|
||||||
let orig_len = range.end - range.start;
|
let orig_len = range.end - range.start;
|
||||||
if input.0.len() - orig_len + replace_len > state.max_size() {
|
if input.0.len() - orig_len + replace_len > state.max_size() {
|
||||||
return MutationResult::Skipped;
|
return MutationResult::Skipped;
|
||||||
@ -298,15 +298,15 @@ where
|
|||||||
core::str::from_utf8(&bytes[range.clone()])
|
core::str::from_utf8(&bytes[range.clone()])
|
||||||
);
|
);
|
||||||
|
|
||||||
let options: u64 = category
|
let options: usize = category
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&(start, end)| u64::from(end) - u64::from(start) + 1)
|
.map(|&(start, end)| end as usize - start as usize + 1)
|
||||||
.sum();
|
.sum();
|
||||||
let char_gen = |state: &mut S| loop {
|
let char_gen = |state: &mut S| loop {
|
||||||
let mut selected = state.rand_mut().below(options);
|
let mut selected = state.rand_mut().below(options);
|
||||||
for &(min, max) in category {
|
for &(min, max) in category {
|
||||||
if let Some(next_selected) =
|
if let Some(next_selected) =
|
||||||
selected.checked_sub(u64::from(max) - u64::from(min) + 1)
|
selected.checked_sub(max as usize - min as usize + 1)
|
||||||
{
|
{
|
||||||
selected = next_selected;
|
selected = next_selected;
|
||||||
} else if let Some(new_c) = char::from_u32(selected as u32 + min) {
|
} else if let Some(new_c) = char::from_u32(selected as u32 + min) {
|
||||||
@ -357,7 +357,7 @@ where
|
|||||||
core::str::from_utf8(&bytes[range.clone()])
|
core::str::from_utf8(&bytes[range.clone()])
|
||||||
);
|
);
|
||||||
|
|
||||||
let options: u64 = u64::from(subcategory.1) - u64::from(subcategory.0) + 1;
|
let options = subcategory.1 as usize - subcategory.0 as usize + 1;
|
||||||
let char_gen = |state: &mut S| loop {
|
let char_gen = |state: &mut S| loop {
|
||||||
let selected = state.rand_mut().below(options);
|
let selected = state.rand_mut().below(options);
|
||||||
if let Some(new_c) = char::from_u32(selected as u32 + subcategory.0) {
|
if let Some(new_c) = char::from_u32(selected as u32 + subcategory.0) {
|
||||||
@ -401,7 +401,7 @@ where
|
|||||||
}
|
}
|
||||||
meta.tokens().len()
|
meta.tokens().len()
|
||||||
};
|
};
|
||||||
let token_idx = state.rand_mut().below(tokens_len as u64) as usize;
|
let token_idx = state.rand_mut().below(tokens_len);
|
||||||
|
|
||||||
let bytes = input.0.bytes();
|
let bytes = input.0.bytes();
|
||||||
let meta = &input.1;
|
let meta = &input.1;
|
||||||
@ -461,7 +461,7 @@ where
|
|||||||
}
|
}
|
||||||
meta.tokens().len()
|
meta.tokens().len()
|
||||||
};
|
};
|
||||||
let token_idx = state.rand_mut().below(tokens_len as u64) as usize;
|
let token_idx = state.rand_mut().below(tokens_len);
|
||||||
|
|
||||||
let bytes = input.0.bytes();
|
let bytes = input.0.bytes();
|
||||||
let meta = &input.1;
|
let meta = &input.1;
|
||||||
|
@ -318,10 +318,10 @@ where
|
|||||||
}
|
}
|
||||||
meta.tokens().len()
|
meta.tokens().len()
|
||||||
};
|
};
|
||||||
let token_idx = state.rand_mut().below(tokens_len as u64) as usize;
|
let token_idx = state.rand_mut().below(tokens_len);
|
||||||
|
|
||||||
let size = input.bytes().len();
|
let size = input.bytes().len();
|
||||||
let off = state.rand_mut().below((size + 1) as u64) as usize;
|
let off = state.rand_mut().below(size + 1);
|
||||||
|
|
||||||
let meta = state.metadata_map().get::<Tokens>().unwrap();
|
let meta = state.metadata_map().get::<Tokens>().unwrap();
|
||||||
let token = &meta.tokens()[token_idx];
|
let token = &meta.tokens()[token_idx];
|
||||||
@ -385,9 +385,9 @@ where
|
|||||||
}
|
}
|
||||||
meta.tokens().len()
|
meta.tokens().len()
|
||||||
};
|
};
|
||||||
let token_idx = state.rand_mut().below(tokens_len as u64) as usize;
|
let token_idx = state.rand_mut().below(tokens_len);
|
||||||
|
|
||||||
let off = state.rand_mut().below(size as u64) as usize;
|
let off = state.rand_mut().below(size);
|
||||||
|
|
||||||
let meta = state.metadata_map().get::<Tokens>().unwrap();
|
let meta = state.metadata_map().get::<Tokens>().unwrap();
|
||||||
let token = &meta.tokens()[token_idx];
|
let token = &meta.tokens()[token_idx];
|
||||||
@ -446,9 +446,9 @@ where
|
|||||||
}
|
}
|
||||||
meta.list.len()
|
meta.list.len()
|
||||||
};
|
};
|
||||||
let idx = state.rand_mut().below(cmps_len as u64) as usize;
|
let idx = state.rand_mut().below(cmps_len);
|
||||||
|
|
||||||
let off = state.rand_mut().below(size as u64) as usize;
|
let off = state.rand_mut().below(size);
|
||||||
let len = input.bytes().len();
|
let len = input.bytes().len();
|
||||||
let bytes = input.bytes_mut();
|
let bytes = input.bytes_mut();
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ where
|
|||||||
{
|
{
|
||||||
name: Cow<'static, str>,
|
name: Cow<'static, str>,
|
||||||
mutations: MT,
|
mutations: MT,
|
||||||
max_stack_pow: u64,
|
max_stack_pow: usize,
|
||||||
phantom: PhantomData<(I, S)>,
|
phantom: PhantomData<(I, S)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,7 +223,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
// fall back to random if no entries in either vec, the scheduling is not tuned.
|
// fall back to random if no entries in either vec, the scheduling is not tuned.
|
||||||
state.rand_mut().below(self.mutations.len() as u64).into()
|
state.rand_mut().below(self.mutations.len()).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ where
|
|||||||
fn mutator_mut(&mut self) -> &mut M;
|
fn mutator_mut(&mut self) -> &mut M;
|
||||||
|
|
||||||
/// Gets the number of iterations this mutator should run for.
|
/// Gets the number of iterations this mutator should run for.
|
||||||
fn iterations(&self, state: &mut Z::State) -> Result<u64, Error>;
|
fn iterations(&self, state: &mut Z::State) -> Result<usize, Error>;
|
||||||
|
|
||||||
/// Gets the number of executions this mutator already did since it got first called in this fuzz round.
|
/// Gets the number of executions this mutator already did since it got first called in this fuzz round.
|
||||||
fn execs_since_progress_start(&mut self, state: &mut Z::State) -> Result<u64, Error>;
|
fn execs_since_progress_start(&mut self, state: &mut Z::State) -> Result<u64, Error>;
|
||||||
@ -150,7 +150,7 @@ where
|
|||||||
|
|
||||||
/// Default value, how many iterations each stage gets, as an upper bound.
|
/// Default value, how many iterations each stage gets, as an upper bound.
|
||||||
/// It may randomly continue earlier.
|
/// It may randomly continue earlier.
|
||||||
pub static DEFAULT_MUTATIONAL_MAX_ITERATIONS: u64 = 128;
|
pub static DEFAULT_MUTATIONAL_MAX_ITERATIONS: usize = 128;
|
||||||
|
|
||||||
/// The default mutational stage
|
/// The default mutational stage
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@ -158,7 +158,7 @@ pub struct StdMutationalStage<E, EM, I, M, Z> {
|
|||||||
/// The mutator(s) to use
|
/// The mutator(s) to use
|
||||||
mutator: M,
|
mutator: M,
|
||||||
/// The maximum amount of iterations we should do each round
|
/// The maximum amount of iterations we should do each round
|
||||||
max_iterations: u64,
|
max_iterations: usize,
|
||||||
/// The progress helper for this mutational stage
|
/// The progress helper for this mutational stage
|
||||||
restart_helper: ExecutionCountRestartHelper,
|
restart_helper: ExecutionCountRestartHelper,
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
@ -187,7 +187,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the number of iterations as a random number
|
/// Gets the number of iterations as a random number
|
||||||
fn iterations(&self, state: &mut Z::State) -> Result<u64, Error> {
|
fn iterations(&self, state: &mut Z::State) -> Result<usize, Error> {
|
||||||
Ok(1 + state.rand_mut().below(self.max_iterations))
|
Ok(1 + state.rand_mut().below(self.max_iterations))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,7 +258,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new mutational stage with the given max iterations
|
/// Creates a new mutational stage with the given max iterations
|
||||||
pub fn with_max_iterations(mutator: M, max_iterations: u64) -> Self {
|
pub fn with_max_iterations(mutator: M, max_iterations: usize) -> Self {
|
||||||
Self::transforming_with_max_iterations(mutator, max_iterations)
|
Self::transforming_with_max_iterations(mutator, max_iterations)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -277,7 +277,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new transforming mutational stage with the given max iterations
|
/// Creates a new transforming mutational stage with the given max iterations
|
||||||
pub fn transforming_with_max_iterations(mutator: M, max_iterations: u64) -> Self {
|
pub fn transforming_with_max_iterations(mutator: M, max_iterations: usize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
mutator,
|
mutator,
|
||||||
max_iterations,
|
max_iterations,
|
||||||
|
@ -54,10 +54,10 @@ where
|
|||||||
|
|
||||||
/// Gets the number of iterations as a random number
|
/// Gets the number of iterations as a random number
|
||||||
#[allow(clippy::cast_sign_loss)]
|
#[allow(clippy::cast_sign_loss)]
|
||||||
fn iterations(&self, state: &mut E::State) -> Result<u64, Error> {
|
fn iterations(&self, state: &mut E::State) -> Result<usize, Error> {
|
||||||
// Update handicap
|
// Update handicap
|
||||||
let mut testcase = state.current_testcase_mut()?;
|
let mut testcase = state.current_testcase_mut()?;
|
||||||
let score = F::compute(state, &mut testcase)? as u64;
|
let score = F::compute(state, &mut testcase)? as usize;
|
||||||
|
|
||||||
Ok(score)
|
Ok(score)
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ use crate::{
|
|||||||
use crate::{monitors::PerfFeature, state::HasClientPerfMonitor};
|
use crate::{monitors::PerfFeature, state::HasClientPerfMonitor};
|
||||||
|
|
||||||
/// The default maximum number of mutations to perform per input.
|
/// The default maximum number of mutations to perform per input.
|
||||||
pub static DEFAULT_MUTATIONAL_MAX_ITERATIONS: u64 = 128;
|
pub static DEFAULT_MUTATIONAL_MAX_ITERATIONS: usize = 128;
|
||||||
/// A Mutational push stage is the stage in a fuzzing run that mutates inputs.
|
/// A Mutational push stage is the stage in a fuzzing run that mutates inputs.
|
||||||
/// Mutational push stages will usually have a range of mutations that are
|
/// Mutational push stages will usually have a range of mutations that are
|
||||||
/// being applied to the input one by one, between executions.
|
/// being applied to the input one by one, between executions.
|
||||||
@ -72,7 +72,7 @@ where
|
|||||||
/// Gets the number of iterations as a random number
|
/// Gets the number of iterations as a random number
|
||||||
#[allow(clippy::unused_self, clippy::unnecessary_wraps)] // TODO: we should put this function into a trait later
|
#[allow(clippy::unused_self, clippy::unnecessary_wraps)] // TODO: we should put this function into a trait later
|
||||||
fn iterations(&self, state: &mut CS::State, _corpus_idx: CorpusId) -> Result<usize, Error> {
|
fn iterations(&self, state: &mut CS::State, _corpus_idx: CorpusId) -> Result<usize, Error> {
|
||||||
Ok(1 + state.rand_mut().below(DEFAULT_MUTATIONAL_MAX_ITERATIONS) as usize)
|
Ok(1 + state.rand_mut().below(DEFAULT_MUTATIONAL_MAX_ITERATIONS))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the current corpus index
|
/// Sets the current corpus index
|
||||||
|
@ -169,7 +169,6 @@ where
|
|||||||
{
|
{
|
||||||
/// Runs this (mutational) stage for the given `testcase`
|
/// Runs this (mutational) stage for the given `testcase`
|
||||||
/// Exactly the same functionality as [`MutationalStage::perform_mutational`], but with added timeout support.
|
/// Exactly the same functionality as [`MutationalStage::perform_mutational`], but with added timeout support.
|
||||||
#[allow(clippy::cast_possible_wrap)] // more than i32 stages on 32 bit system - highly unlikely...
|
|
||||||
fn perform_mutational(
|
fn perform_mutational(
|
||||||
&mut self,
|
&mut self,
|
||||||
fuzzer: &mut Z,
|
fuzzer: &mut Z,
|
||||||
@ -221,7 +220,7 @@ where
|
|||||||
// fall back to random
|
// fall back to random
|
||||||
let iters = self
|
let iters = self
|
||||||
.iterations(state)?
|
.iterations(state)?
|
||||||
.saturating_sub(self.execs_since_progress_start(state)?);
|
.saturating_sub(self.execs_since_progress_start(state)? as usize);
|
||||||
for _ in 1..=iters {
|
for _ in 1..=iters {
|
||||||
self.perform_mutation(fuzzer, executor, state, manager, &input)?;
|
self.perform_mutation(fuzzer, executor, state, manager, &input)?;
|
||||||
}
|
}
|
||||||
@ -243,8 +242,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the number of iterations as a random number
|
/// Gets the number of iterations as a random number
|
||||||
#[allow(clippy::cast_possible_truncation)]
|
fn iterations(&self, state: &mut Z::State) -> Result<usize, Error> {
|
||||||
fn iterations(&self, state: &mut Z::State) -> Result<u64, Error> {
|
|
||||||
Ok(
|
Ok(
|
||||||
// fall back to random
|
// fall back to random
|
||||||
1 + state.rand_mut().below(DEFAULT_MUTATIONAL_MAX_ITERATIONS),
|
1 + state.rand_mut().below(DEFAULT_MUTATIONAL_MAX_ITERATIONS),
|
||||||
|
@ -30,7 +30,7 @@ where
|
|||||||
debug_assert!(iter.len() > 0, "choosing from an empty iterator");
|
debug_assert!(iter.len() > 0, "choosing from an empty iterator");
|
||||||
|
|
||||||
// pick a random, valid index
|
// pick a random, valid index
|
||||||
let index = fast_bound(rand, iter.len() as u64) as usize;
|
let index = fast_bound(rand, iter.len());
|
||||||
|
|
||||||
// return the item chosen
|
// return the item chosen
|
||||||
iter.nth(index).unwrap()
|
iter.nth(index).unwrap()
|
||||||
@ -42,11 +42,12 @@ where
|
|||||||
/// At least 2^2*(64-N) samples are required to detect this amount of bias.
|
/// At least 2^2*(64-N) samples are required to detect this amount of bias.
|
||||||
///
|
///
|
||||||
/// See: [An optimal algorithm for bounded random integers](https://github.com/apple/swift/pull/39143).
|
/// See: [An optimal algorithm for bounded random integers](https://github.com/apple/swift/pull/39143).
|
||||||
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn fast_bound(rand: u64, n: u64) -> u64 {
|
pub fn fast_bound(rand: u64, n: usize) -> usize {
|
||||||
debug_assert_ne!(n, 0);
|
debug_assert_ne!(n, 0);
|
||||||
let mul = u128::from(rand).wrapping_mul(u128::from(n));
|
let mul = u128::from(rand).wrapping_mul(u128::from(n as u64));
|
||||||
(mul >> 64) as u64
|
(mul >> 64) as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ways to get random around here.
|
/// Ways to get random around here.
|
||||||
@ -60,6 +61,7 @@ pub trait Rand: Debug + Serialize + DeserializeOwned {
|
|||||||
fn next(&mut self) -> u64;
|
fn next(&mut self) -> u64;
|
||||||
|
|
||||||
/// Gets a value between 0.0 (inclusive) and 1.0 (exclusive)
|
/// Gets a value between 0.0 (inclusive) and 1.0 (exclusive)
|
||||||
|
#[inline]
|
||||||
#[allow(clippy::cast_precision_loss)]
|
#[allow(clippy::cast_precision_loss)]
|
||||||
fn next_float(&mut self) -> f64 {
|
fn next_float(&mut self) -> f64 {
|
||||||
// both 2^53 and 2^-53 can be represented in f64 exactly
|
// both 2^53 and 2^-53 can be represented in f64 exactly
|
||||||
@ -70,18 +72,21 @@ pub trait Rand: Debug + Serialize + DeserializeOwned {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true with specified probability
|
/// Returns true with specified probability
|
||||||
|
#[inline]
|
||||||
fn coinflip(&mut self, success_prob: f64) -> bool {
|
fn coinflip(&mut self, success_prob: f64) -> bool {
|
||||||
debug_assert!((0.0..=1.0).contains(&success_prob));
|
debug_assert!((0.0..=1.0).contains(&success_prob));
|
||||||
self.next_float() < success_prob
|
self.next_float() < success_prob
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets a value below the given 64 bit val (exclusive)
|
/// Gets a value below the given bound (exclusive)
|
||||||
fn below(&mut self, upper_bound_excl: u64) -> u64 {
|
#[inline]
|
||||||
|
fn below(&mut self, upper_bound_excl: usize) -> usize {
|
||||||
fast_bound(self.next(), upper_bound_excl)
|
fast_bound(self.next(), upper_bound_excl)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets a value between the given lower bound (inclusive) and upper bound (inclusive)
|
/// Gets a value between the given lower bound (inclusive) and upper bound (inclusive)
|
||||||
fn between(&mut self, lower_bound_incl: u64, upper_bound_incl: u64) -> u64 {
|
#[inline]
|
||||||
|
fn between(&mut self, lower_bound_incl: usize, upper_bound_incl: usize) -> usize {
|
||||||
debug_assert!(lower_bound_incl <= upper_bound_incl);
|
debug_assert!(lower_bound_incl <= upper_bound_incl);
|
||||||
lower_bound_incl + self.below(upper_bound_incl - lower_bound_incl + 1)
|
lower_bound_incl + self.below(upper_bound_incl - lower_bound_incl + 1)
|
||||||
}
|
}
|
||||||
@ -404,6 +409,7 @@ impl Rand for Sfc64Rand {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn next(&mut self) -> u64 {
|
fn next(&mut self) -> u64 {
|
||||||
let out = self.a.wrapping_add(self.b).wrapping_add(self.w);
|
let out = self.a.wrapping_add(self.b).wrapping_add(self.w);
|
||||||
self.w = self.w.wrapping_add(1);
|
self.w = self.w.wrapping_add(1);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user