Rename libafl_bolts::rands::Rand::zero_upto to below_or_zero. (#2911)

Hi LibAFL!

I was playing with the [`Rand`] trait when I realized that the
documentation of [`Rand::zero_upto`] did not match what I was expected:

fd6271fa35/libafl_bolts/src/rands/mod.rs (L139-L142)

When using the following RNGs, [`Rand::zero_upto`] never returns the upper bound `n` as it would have been expected according to the documentation:

 - `RomuDuoJrRand`
 - `RomuTrioRand`
 - `Sfc64Rand`
 - `XkcdRand`
 - `XorShift64Rand`
 - `Xoshiro256PlusPlusRand`

The default implementation of [`Rand::zero_upto`] is to use [`fast_bound_usize`],
which excludes the given upper bound, thus I believe here that the default implementation
of [`Rand::zero_upto`] is wrong.

As discussed here: https://github.com/AFLplusplus/LibAFL/pull/2911#issuecomment-2623773829,
we believe that renaming the method would be better than changing the actual
implementation.

[`Rand`]: fd6271fa35/libafl_bolts/src/rands/mod.rs (L108)
[`Rand::zero_upto`]: fd6271fa35/libafl_bolts/src/rands/mod.rs (L139-L142)
[`fast_bound_usize`]: fd6271fa35/libafl_bolts/src/rands/mod.rs (L100-L103)
This commit is contained in:
Railroad6230 2025-01-30 14:16:23 +01:00 committed by GitHub
parent 5c5f6affcb
commit 85c1d03425
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 6 additions and 6 deletions

View File

@ -608,7 +608,7 @@ where
{
/// Compute the number of iterations used to apply stacked mutations
fn iterations(&self, state: &mut S, _: &I) -> u64 {
1 << (1 + state.rand_mut().zero_upto(self.max_stack_pow))
1 << (1 + state.rand_mut().below_or_zero(self.max_stack_pow))
}
/// Get the next mutation to apply

View File

@ -73,7 +73,7 @@ pub fn buffer_set<T: Clone>(data: &mut [T], from: usize, len: usize, val: T) {
pub fn rand_range<S: HasRand>(state: &mut S, upper: usize, max_len: NonZeroUsize) -> Range<usize> {
let len = 1 + state.rand_mut().below(max_len);
// sample from [1..upper + len]
let mut offset2 = 1 + state.rand_mut().zero_upto(upper + len - 1);
let mut offset2 = 1 + state.rand_mut().below_or_zero(upper + len - 1);
let offset1 = offset2.saturating_sub(len);
if offset2 > upper {
offset2 = upper;

View File

@ -145,7 +145,7 @@ where
{
/// Compute the number of iterations used to apply stacked mutations
fn iterations(&self, state: &mut S, _: &I) -> u64 {
1 << (1 + state.rand_mut().zero_upto(self.max_stack_pow))
1 << (1 + state.rand_mut().below_or_zero(self.max_stack_pow))
}
/// Get the next mutation to apply

View File

@ -132,7 +132,7 @@ where
iters
} else {
// fall back to random
1 << (1 + state.rand_mut().zero_upto(self.max_stack_pow))
1 << (1 + state.rand_mut().below_or_zero(self.max_stack_pow))
}
} else {
// We will sample using the mutation probabilities.

View File

@ -136,8 +136,8 @@ pub trait Rand: Debug + Serialize + DeserializeOwned {
fast_bound(self.next(), upper_bound_excl)
}
/// Gets a value between [0, n]
fn zero_upto(&mut self, n: usize) -> usize {
/// Gets a value below the given one or zero
fn below_or_zero(&mut self, n: usize) -> usize {
fast_bound_usize(self.next(), n)
}