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:
Gregory Petrosyan 2024-04-24 15:01:37 +03:00 committed by GitHub
parent 0f42efa12b
commit 1e8667a9f9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 108 additions and 106 deletions

View File

@ -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)
}}; }};
} }

View File

@ -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()

View File

@ -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;
} }

View File

@ -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.

View File

@ -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;

View File

@ -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));

View File

@ -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>() {

View File

@ -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();

View File

@ -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.

View File

@ -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> {

View File

@ -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;

View File

@ -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();

View File

@ -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()
} }
} }

View File

@ -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,

View File

@ -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)
} }

View File

@ -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

View File

@ -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),

View File

@ -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);