Use nonzero! macro (#2589)

* nonzero_lit

* nonzero

* std instead of core

* a

* l

* test

* import

* api

* api

* aaaaa

* apiapi

* api

* api

* api

* mm

* api

* non zero

* FMT

* pls

* nnnaaasdfadsfafdsa

* pls

* MM

* fix

* a

* sat add

* aa

* mistake

* unreachable

* no generic

* api change

* a
This commit is contained in:
Dongjia "toka" Zhang 2024-10-18 23:33:03 +02:00 committed by GitHub
parent 3b31b4d796
commit fda1596ee2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
51 changed files with 282 additions and 286 deletions

View File

@ -3,7 +3,6 @@ extern crate libafl;
extern crate libafl_bolts;
use std::path::PathBuf;
use libafl::{
corpus::{InMemoryCorpus, OnDiskCorpus},
events::SimpleEventManager,
@ -15,7 +14,7 @@ use libafl::{
schedulers::QueueScheduler,
state::StdState,
};
use libafl_bolts::{rands::StdRand, tuples::tuple_list, AsSlice};
use libafl_bolts::{rands::StdRand, tuples::tuple_list, AsSlice, nonzero};
/* ANCHOR_END: use */
fn main() {
@ -77,7 +76,7 @@ fn main() {
/* ANCHOR: generator */
// Generator of printable bytearrays of max size 32
let mut generator = RandPrintablesGenerator::new(32).unwrap();
let mut generator = RandPrintablesGenerator::new(nonzero!(32));
// Generate 8 initial inputs
state

View File

@ -15,7 +15,7 @@ use libafl::{
schedulers::QueueScheduler,
state::StdState,
};
use libafl_bolts::{rands::StdRand, tuples::tuple_list, AsSlice};
use libafl_bolts::{rands::StdRand, tuples::tuple_list, AsSlice, nonzero};
use std::path::PathBuf;
/* ANCHOR_END: use */
@ -105,7 +105,7 @@ fn main() {
/* ANCHOR_END: executor_with_observer */
// Generator of printable bytearrays of max size 32
let mut generator = RandPrintablesGenerator::new(32).unwrap();
let mut generator = RandPrintablesGenerator::new(nonzero!(32));
// Generate 8 initial inputs
state

View File

@ -1,6 +1,7 @@
/* ANCHOR: use */
extern crate libafl;
extern crate libafl_bolts;
use std::num::NonZeroUsize;
use libafl::{
corpus::{InMemoryCorpus, OnDiskCorpus},
@ -17,7 +18,7 @@ use libafl::{
stages::mutational::StdMutationalStage,
state::StdState,
};
use libafl_bolts::{rands::StdRand, tuples::tuple_list, AsSlice};
use libafl_bolts::{rands::StdRand, tuples::tuple_list, AsSlice, nonzero};
use std::path::PathBuf;
/* ANCHOR_END: use */
@ -97,7 +98,7 @@ fn main() {
.expect("Failed to create the Executor");
// Generator of printable bytearrays of max size 32
let mut generator = RandPrintablesGenerator::new(32).unwrap();
let mut generator = RandPrintablesGenerator::new(nonzero!(32));
// Generate 8 initial inputs
state

View File

@ -20,7 +20,7 @@ use libafl::{
stages::mutational::StdMutationalStage,
state::StdState,
};
use libafl_bolts::{current_nanos, rands::StdRand, tuples::tuple_list, AsSlice};
use libafl_bolts::{current_nanos, nonzero, rands::StdRand, tuples::tuple_list, AsSlice};
/// Coverage map with explicit assignments due to the lack of instrumentation
static mut SIGNALS: [u8; 16] = [0; 16];
@ -116,7 +116,7 @@ pub fn main() {
.expect("Failed to create the Executor");
// Generator of printable bytearrays of max size 32
let mut generator = RandPrintablesGenerator::new(32).unwrap();
let mut generator = RandPrintablesGenerator::new(nonzero!(32));
// Generate 8 initial inputs
state

View File

@ -86,7 +86,7 @@ pub fn main() -> Result<(), Error> {
.expect("Failed to create the Executor");
// Generator of printable bytearrays of max size 32
let mut generator = RandPrintablesGenerator::new(32).unwrap();
let mut generator = RandPrintablesGenerator::new(nonzero!(32));
// Generate 8 initial inputs
state

View File

@ -23,7 +23,7 @@ use libafl::{
stages::mutational::StdMutationalStage,
state::{HasSolutions, StdState},
};
use libafl_bolts::{rands::StdRand, tuples::tuple_list, AsSlice};
use libafl_bolts::{nonzero, rands::StdRand, tuples::tuple_list, AsSlice};
use libafl_targets::{edges_max_num, DifferentialAFLMapSwapObserver};
#[cfg(not(miri))]
use mimalloc::MiMalloc;
@ -247,7 +247,7 @@ pub fn main() {
);
// Generator of printable bytearrays of max size 32
let mut generator = RandPrintablesGenerator::new(32).unwrap();
let mut generator = RandPrintablesGenerator::new(nonzero!(32));
// Generate 8 initial inputs
state

View File

@ -17,6 +17,7 @@ use libafl::{
state::StdState,
};
use libafl_bolts::{
nonzero,
ownedref::OwnedRefMut,
rands::StdRand,
shmem::{ShMemProvider, StdShMemProvider},
@ -103,7 +104,7 @@ pub fn main() {
.expect("Failed to create the Executor");
// Generator of printable bytearrays of max size 32
let mut generator = RandPrintablesGenerator::new(32).unwrap();
let mut generator = RandPrintablesGenerator::new(nonzero!(32));
// Generate 8 initial inputs
state

View File

@ -16,7 +16,7 @@ use libafl::{
stages::mutational::StdMutationalStage,
state::StdState,
};
use libafl_bolts::{rands::StdRand, tuples::tuple_list, AsSlice};
use libafl_bolts::{nonzero, rands::StdRand, tuples::tuple_list, AsSlice};
use libc::c_uchar;
extern crate libc;
@ -89,7 +89,7 @@ pub fn main() {
.expect("Failed to create the Executor");
// Generator of printable bytearrays of max size 32
let mut generator = RandPrintablesGenerator::new(32).unwrap();
let mut generator = RandPrintablesGenerator::new(nonzero!(32));
// Generate 8 initial inputs
state

View File

@ -25,6 +25,7 @@ use libafl::{
Error,
};
use libafl_bolts::{
nonzero,
rands::StdRand,
shmem::{unix_shmem, ShMem, ShMemId, ShMemProvider},
tuples::tuple_list,
@ -112,7 +113,7 @@ pub fn main() {
let mut executor = MyExecutor { shmem_id }.into_executor(tuple_list!(observer, bt_observer));
// Generator of printable bytearrays of max size 32
let mut generator = RandPrintablesGenerator::new(32).unwrap();
let mut generator = RandPrintablesGenerator::new(nonzero!(32));
// Generate 8 initial inputs
state

View File

@ -21,6 +21,7 @@ use libafl_bolts::shmem::StdShMemProvider;
#[cfg(target_vendor = "apple")]
use libafl_bolts::shmem::UnixShMemProvider;
use libafl_bolts::{
nonzero,
rands::StdRand,
shmem::{ShMem, ShMemProvider},
tuples::tuple_list,
@ -97,7 +98,7 @@ pub fn main() {
.unwrap();
// Generator of printable bytearrays of max size 32
let mut generator = RandPrintablesGenerator::new(3).unwrap();
let mut generator = RandPrintablesGenerator::new(nonzero!(32));
// Generate 8 initial inputs
state

View File

@ -19,6 +19,7 @@ use libafl::{
state::StdState,
};
use libafl_bolts::{
nonzero,
ownedref::OwnedRefMut,
rands::StdRand,
shmem::{unix_shmem, ShMem, ShMemProvider},
@ -122,7 +123,7 @@ pub fn main() {
.expect("Failed to create the Executor");
// Generator of printable bytearrays of max size 32
let mut generator = RandPrintablesGenerator::new(32).unwrap();
let mut generator = RandPrintablesGenerator::new(nonzero!(32));
// Generate 8 initial inputs
state

View File

@ -18,7 +18,7 @@ use libafl::{
stages::mutational::StdMutationalStage,
state::StdState,
};
use libafl_bolts::{rands::StdRand, tuples::tuple_list, AsSlice};
use libafl_bolts::{nonzero, rands::StdRand, tuples::tuple_list, AsSlice};
/// Coverage map with explicit assignments due to the lack of instrumentation
static mut SIGNALS: [u8; 16] = [0; 16];
@ -113,7 +113,7 @@ pub fn main() {
.expect("Failed to create the Executor");
// Generator of printable bytearrays of max size 32
let mut generator = RandPrintablesGenerator::new(32).unwrap();
let mut generator = RandPrintablesGenerator::new(nonzero!(32));
// Generate 8 initial inputs
state

View File

@ -18,6 +18,7 @@ use libafl::{
state::StdState,
};
use libafl_bolts::{
nonzero,
rands::StdRand,
shmem::{unix_shmem, ShMemProvider},
tuples::tuple_list,
@ -115,7 +116,7 @@ pub fn main() {
.expect("Failed to create the Executor");
// Generator of printable bytearrays of max size 32
let mut generator = RandPrintablesGenerator::new(32).unwrap();
let mut generator = RandPrintablesGenerator::new(nonzero!(32));
// Generate 8 initial inputs
state

View File

@ -206,8 +206,7 @@ pub fn main() {
// Setup a mutational stage with a basic bytes mutator
let mutator =
StdScheduledMutator::with_max_stack_pow(havoc_mutations().merge(tokens_mutations()), 6)
.unwrap();
StdScheduledMutator::with_max_stack_pow(havoc_mutations().merge(tokens_mutations()), 6);
let mut stages = tuple_list!(StdMutationalStage::new(mutator));
fuzzer

View File

@ -202,8 +202,7 @@ pub fn main() {
// Setup a mutational stage with a basic bytes mutator
let mutator =
StdScheduledMutator::with_max_stack_pow(havoc_mutations().merge(tokens_mutations()), 6)
.unwrap();
StdScheduledMutator::with_max_stack_pow(havoc_mutations().merge(tokens_mutations()), 6);
let mut stages = tuple_list!(StdMutationalStage::new(mutator));
fuzzer

View File

@ -15,7 +15,9 @@ use libafl::{
state::{HasSolutions, StdState},
Fuzzer, StdFuzzer,
};
use libafl_bolts::{rands::StdRand, serdeany::RegistryBuilder, tuples::tuple_list, AsSlice};
use libafl_bolts::{
nonzero, rands::StdRand, serdeany::RegistryBuilder, tuples::tuple_list, AsSlice,
};
use wasm_bindgen::prelude::*;
use web_sys::{Performance, Window};
@ -126,7 +128,7 @@ pub fn fuzz() {
.expect("Failed to create the Executor");
// Generator of printable bytearrays of max size 32
let mut generator = RandPrintablesGenerator::new(32).unwrap();
let mut generator = RandPrintablesGenerator::new(nonzero!(32));
// Generate 8 initial inputs
state

View File

@ -25,7 +25,7 @@ use libafl::{
stages::mutational::StdMutationalStage,
state::StdState,
};
use libafl_bolts::{rands::StdRand, tuples::tuple_list, AsSlice};
use libafl_bolts::{nonzero, rands::StdRand, tuples::tuple_list, AsSlice};
#[cfg(any(windows, unix))]
use libc::{abort, printf};
use static_alloc::Bump;
@ -144,7 +144,7 @@ pub extern "C" fn main(_argc: isize, _argv: *const *const u8) -> isize {
.expect("Failed to create the Executor");
// Generator of printable bytearrays of max size 32
let mut generator = RandPrintablesGenerator::new(32).unwrap();
let mut generator = RandPrintablesGenerator::new(nonzero!(32));
// Generate 8 initial inputs
state

View File

@ -34,6 +34,7 @@ use libafl::{
};
use libafl_bolts::{
core_affinity::Cores,
nonzero,
rands::StdRand,
shmem::{ShMemProvider, StdShMemProvider},
tuples::{tuple_list, Merge},
@ -240,7 +241,7 @@ pub extern "C" fn LLVMFuzzerRunDriver(
if state.must_load_initial_inputs() {
if input_dirs.is_empty() {
// Generator of printable bytearrays of max size 32
let mut generator = RandBytesGenerator::new(32).unwrap();
let mut generator = RandBytesGenerator::new(nonzero!(32));
// Generate 8 initial inputs
state

View File

@ -18,7 +18,7 @@ use libafl::{
stages::mutational::StdMutationalStage,
state::StdState,
};
use libafl_bolts::{current_nanos, rands::StdRand, tuples::tuple_list, AsSlice};
use libafl_bolts::{current_nanos, nonzero, rands::StdRand, tuples::tuple_list, AsSlice};
/// Coverage map with explicit assignments due to the lack of instrumentation
static mut SIGNALS: [u8; 16] = [0; 16];
@ -93,7 +93,7 @@ fn input_generator() {
.expect("Failed to create the Executor");
// Generator of printable bytearrays of max size 32
let mut generator = RandPrintablesGenerator::new(32).unwrap();
let mut generator = RandPrintablesGenerator::new(nonzero!(32));
// Generate 8 initial inputs
state

View File

@ -602,8 +602,8 @@ fn fuzz_text(
GrimoireRandomDeleteMutator::new(),
),
3,
)
.unwrap();
);
let grimoire = StdMutationalStage::transforming(grimoire_mutator);
// A minimization+queue policy to get testcasess from the corpus

View File

@ -1,3 +1,4 @@
use core::num::NonZeroUsize;
use std::{
borrow::Cow,
hash::{DefaultHasher, Hash, Hasher},
@ -59,20 +60,20 @@ impl CustomInput {
}
/// A generator for [`CustomInput`] used in this example
pub struct CustomInputGenerator<S: HasRand> {
pub bytes_generator: RandBytesGenerator<S>,
pub struct CustomInputGenerator {
pub bytes_generator: RandBytesGenerator,
}
impl<S: HasRand> CustomInputGenerator<S> {
impl CustomInputGenerator {
/// Creates a new [`CustomInputGenerator`]
pub fn new(max_len: usize) -> Result<Self, Error> {
Ok(Self {
bytes_generator: RandBytesGenerator::new(max_len)?,
})
pub fn new(max_len: NonZeroUsize) -> Self {
Self {
bytes_generator: RandBytesGenerator::new(max_len),
}
}
}
impl<S> Generator<CustomInput, S> for CustomInputGenerator<S>
impl<S> Generator<CustomInput, S> for CustomInputGenerator
where
S: HasRand,
{
@ -99,15 +100,12 @@ pub struct ToggleOptionalByteArrayMutator<G> {
generator: G,
}
impl<S> ToggleOptionalByteArrayMutator<RandBytesGenerator<S>>
where
S: HasRand,
{
impl ToggleOptionalByteArrayMutator<RandBytesGenerator> {
/// Creates a new [`ToggleOptionalByteArrayMutator`]
pub fn new(length: usize) -> Result<Self, Error> {
Ok(Self {
generator: RandBytesGenerator::new(length)?,
})
pub fn new(length: NonZeroUsize) -> Self {
Self {
generator: RandBytesGenerator::new(length),
}
}
}

View File

@ -26,7 +26,7 @@ use libafl::{
state::StdState,
};
use libafl_bolts::{
current_nanos,
current_nanos, nonzero,
rands::StdRand,
tuples::{tuple_list, Merge, Prepend},
};
@ -42,7 +42,7 @@ use {
/// Coverage map with explicit assignments due to the lack of instrumentation
const SIGNALS_LEN: usize = 16;
static mut SIGNALS: [u8; SIGNALS_LEN] = [0; 16];
static mut SIGNALS_PTR: *mut u8 = unsafe { addr_of_mut!(SIGNALS) as _ };
static mut SIGNALS_PTR: *mut u8 = addr_of_mut!(SIGNALS) as _;
/// Assign a signal to the signals map
fn signals_set(idx: usize) {
@ -131,8 +131,7 @@ pub fn main() {
.expect("Failed to create the Executor");
// Generator of printable bytearrays of max size 32
let mut generator =
CustomInputGenerator::new(1).expect("Failed to create our custom input generator");
let mut generator = CustomInputGenerator::new(nonzero!(1));
// Generate 8 initial inputs
state
@ -183,9 +182,7 @@ pub fn main() {
// Then, mutators for the optional byte array, these return MutationResult::Skipped if the part is not present
.merge(optional_mapped_mutators)
// A custom mutator that sets the optional byte array to None if present, and generates a random byte array of length 1 if it is not
.prepend(
ToggleOptionalByteArrayMutator::new(1).expect("Failed to create bytearray mutator"),
)
.prepend(ToggleOptionalByteArrayMutator::new(nonzero!(1)))
// Finally, a custom mutator that toggles the boolean part of the input
.prepend(ToggleBooleanMutator);

View File

@ -156,8 +156,7 @@ pub fn main() {
GramatronRecursionMutator::new()
),
2,
)
.unwrap();
);
let mut stages = tuple_list!(StdMutationalStage::new(mutator));
fuzzer

View File

@ -139,7 +139,7 @@ pub fn main() {
.expect("Failed to create the Executor");
// Setup a mutational stage with a basic bytes mutator
let mutator = StdScheduledMutator::with_max_stack_pow(havoc_mutations(), 2).unwrap();
let mutator = StdScheduledMutator::with_max_stack_pow(havoc_mutations(), 2);
let grimoire_mutator = StdScheduledMutator::with_max_stack_pow(
tuple_list!(
GrimoireExtensionMutator::new(),
@ -150,8 +150,7 @@ pub fn main() {
GrimoireRandomDeleteMutator::new(),
),
3,
)
.unwrap();
);
let mut stages = tuple_list!(
generalization,
StdMutationalStage::new(mutator),

View File

@ -158,8 +158,7 @@ pub fn main() {
NautilusSpliceMutator::new(&context),
),
2,
)
.unwrap();
);
let mut stages = tuple_list!(StdMutationalStage::new(mutator));
fuzzer

View File

@ -116,7 +116,7 @@ pub fn main() {
.expect("Failed to create the Executor");
// Setup a mutational stage with a basic bytes mutator
let mutator = StdScheduledMutator::with_max_stack_pow(encoded_mutations(), 2).unwrap();
let mutator = StdScheduledMutator::with_max_stack_pow(encoded_mutations(), 2);
let mut stages = tuple_list!(StdMutationalStage::new(mutator));
println!("Decoder {:?} ...", &encoder_decoder);

View File

@ -230,8 +230,7 @@ pub extern "C" fn libafl_main() {
NautilusSpliceMutator::new(&context),
),
2,
)
.unwrap();
);
if let Some(conv) = event_converter.take() {
let mut stages = tuple_list!(

View File

@ -2,7 +2,10 @@ use alloc::{borrow::ToOwned, string::String, vec::Vec};
use core::num::NonZero;
use hashbrown::HashMap;
use libafl_bolts::rands::{Rand, RomuDuoJrRand};
use libafl_bolts::{
nonzero,
rands::{Rand, RomuDuoJrRand},
};
use pyo3::prelude::PyObject;
use super::{
@ -265,7 +268,7 @@ impl Context {
.take_while(move |r| self.rules_to_min_size[*r] <= max_len)
.filter(move |r| {
self.rules_to_num_options[*r] > 1
|| rand.below(NonZero::new(100).unwrap()) <= p_include_short_rules
|| rand.below(nonzero!(100)) <= p_include_short_rules
})
}

View File

@ -1,16 +1,15 @@
//! Generators may generate bytes or, in general, data, for inputs.
use alloc::vec::Vec;
use core::{
marker::PhantomData,
num::{NonZero, NonZeroUsize},
};
use core::{marker::PhantomData, num::NonZeroUsize};
use libafl_bolts::rands::Rand;
use crate::{inputs::bytes::BytesInput, state::HasRand, Error};
use crate::{inputs::bytes::BytesInput, nonzero, state::HasRand, Error};
pub mod gramatron;
use core::cmp::min;
pub use gramatron::*;
#[cfg(feature = "nautilus")]
@ -74,64 +73,45 @@ where
#[derive(Clone, Debug)]
/// Generates random bytes
pub struct RandBytesGenerator<S> {
pub struct RandBytesGenerator {
max_size: NonZeroUsize,
phantom: PhantomData<S>,
}
impl<S> Generator<BytesInput, S> for RandBytesGenerator<S>
impl<S> Generator<BytesInput, S> for RandBytesGenerator
where
S: HasRand,
{
fn generate(&mut self, state: &mut S) -> Result<BytesInput, Error> {
let mut size = state.rand_mut().below(self.max_size);
if size == 0 {
size = 1;
}
size = min(size, 1);
let random_bytes: Vec<u8> = (0..size)
.map(|_| state.rand_mut().below(NonZero::new(256).unwrap()) as u8)
.map(|_| state.rand_mut().below(nonzero!(256)) as u8)
.collect();
Ok(BytesInput::new(random_bytes))
}
}
impl<S> RandBytesGenerator<S> {
/// Returns a new [`RandBytesGenerator`], generating up to `max_size` random bytes.
///
/// If you want to save one 0 check, use [`Self::from_nonzero`].
pub fn new(max_size: usize) -> Result<Self, Error> {
let Some(max_size) = NonZero::new(max_size) else {
return Err(Error::illegal_argument("The max_size may not be 0."));
};
Ok(Self::from_nonzero(max_size))
}
impl RandBytesGenerator {
/// Returns a new [`RandBytesGenerator`], generating up to `max_size` random bytes.
#[must_use]
pub fn from_nonzero(max_size: NonZeroUsize) -> Self {
Self {
max_size,
phantom: PhantomData,
}
pub fn new(max_size: NonZeroUsize) -> Self {
Self { max_size }
}
}
#[derive(Clone, Debug)]
/// Generates random printable characters
pub struct RandPrintablesGenerator<S> {
pub struct RandPrintablesGenerator {
max_size: NonZeroUsize,
phantom: PhantomData<S>,
}
impl<S> Generator<BytesInput, S> for RandPrintablesGenerator<S>
impl<S> Generator<BytesInput, S> for RandPrintablesGenerator
where
S: HasRand,
{
fn generate(&mut self, state: &mut S) -> Result<BytesInput, Error> {
let mut size = state.rand_mut().below(self.max_size);
if size == 0 {
size = 1;
}
size = min(size, 1);
let printables = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz \t\n!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~".as_bytes();
let random_bytes: Vec<u8> = (0..size)
.map(|_| *state.rand_mut().choose(printables).unwrap())
@ -140,23 +120,10 @@ where
}
}
impl<S> RandPrintablesGenerator<S> {
/// Creates a new [`RandPrintablesGenerator`], generating up to `max_size` random printable characters.
///
/// To skip the 0 `max_size` check, create this using [`Self::from_nonzero`] instead.
pub fn new(max_size: usize) -> Result<Self, Error> {
let Some(max_size) = NonZero::new(max_size) else {
return Err(Error::illegal_argument("The max_size may not be 0."));
};
Ok(Self::from_nonzero(max_size))
}
impl RandPrintablesGenerator {
/// Returns a new [`RandBytesGenerator`], generating up to `max_size` random bytes.
#[must_use]
pub fn from_nonzero(max_size: NonZeroUsize) -> Self {
Self {
max_size,
phantom: PhantomData,
}
pub fn new(max_size: NonZeroUsize) -> Self {
Self { max_size }
}
}

View File

@ -83,7 +83,7 @@ pub mod stages;
pub mod state;
pub use fuzzer::*;
pub use libafl_bolts::Error;
pub use libafl_bolts::{nonzero, Error};
/// The purpose of this module is to alleviate imports of many components by adding a glob import.
#[cfg(feature = "prelude")]

View File

@ -18,7 +18,7 @@ use crate::{
mutations::{buffer_copy, buffer_self_copy, ARITH_MAX},
MutationResult, Mutator, Named,
},
random_corpus_id_with_disabled,
nonzero, random_corpus_id_with_disabled,
state::{HasCorpus, HasMaxSize, HasRand},
Error,
};
@ -126,8 +126,8 @@ impl<S: HasRand> Mutator<EncodedInput, S> for EncodedAddMutator {
Ok(MutationResult::Skipped)
} else {
let val = state.rand_mut().choose(input.codes_mut()).unwrap();
let num = 1 + state.rand_mut().below(NonZero::new(ARITH_MAX).unwrap()) as u32;
*val = match state.rand_mut().below(NonZero::new(2).unwrap()) {
let num = 1 + state.rand_mut().below(nonzero!(ARITH_MAX)) as u32;
*val = match state.rand_mut().below(nonzero!(2)) {
0 => val.wrapping_add(num),
_ => val.wrapping_sub(num),
};
@ -205,7 +205,7 @@ where
fn mutate(&mut self, state: &mut S, input: &mut EncodedInput) -> Result<MutationResult, Error> {
let max_size = state.max_size();
let size = input.codes().len();
let Some(nonzero_size) = NonZero::new(size) else {
let Some(nz) = NonZero::new(size) else {
return Ok(MutationResult::Skipped);
};
@ -215,7 +215,7 @@ where
let off = state
.rand_mut()
.below(unsafe { NonZero::new(size + 1).unwrap_unchecked() });
let mut len = 1 + state.rand_mut().below(nonzero_size);
let mut len = 1 + state.rand_mut().below(nz);
if size + len > max_size {
if max_size > size {
@ -266,17 +266,23 @@ pub struct EncodedCopyMutator;
impl<S: HasRand> Mutator<EncodedInput, S> for EncodedCopyMutator {
fn mutate(&mut self, state: &mut S, input: &mut EncodedInput) -> Result<MutationResult, Error> {
let size = input.codes().len();
let Some(size) = NonZero::new(size) else {
if size <= 1 {
return Ok(MutationResult::Skipped);
};
let from = state.rand_mut().below(size);
let to = state.rand_mut().below(size);
// # Safety
// it's larger than 1
let from = state
.rand_mut()
.below(unsafe { NonZero::new(size).unwrap_unchecked() });
let to = state
.rand_mut()
.below(unsafe { NonZero::new(size).unwrap_unchecked() });
// # Safety
// Both from and to are smaller than size, so size minus any of these can never be 0.
let len = 1 + state
.rand_mut()
.below(unsafe { NonZero::new(size.get() - max(from, to)).unwrap_unchecked() });
.below(unsafe { NonZero::new(size - max(from, to)).unwrap_unchecked() });
unsafe {
buffer_self_copy(input.codes_mut(), from, to, len);
@ -321,7 +327,7 @@ where
}
}
let Some(non_zero_size) = NonZero::new(size) else {
let Some(nz) = NonZero::new(size) else {
return Ok(MutationResult::Skipped);
};
@ -335,13 +341,13 @@ where
return Ok(MutationResult::Skipped);
}
let Some(non_zero_other_size) = NonZero::new(other_size) else {
return Ok(MutationResult::Skipped);
};
// # Safety
// it's larger than 1
let max_size = state.max_size();
let from = state.rand_mut().below(non_zero_other_size);
let to = state.rand_mut().below(non_zero_size);
let from = state
.rand_mut()
.below(unsafe { NonZero::new(other_size).unwrap_unchecked() });
let to = state.rand_mut().below(nz);
// # Safety
// from is smaller than other_size, other_size is larger than 2, so the subtraction is larger than 0.
let mut len = 1 + state
@ -414,18 +420,18 @@ where
if other_size < 2 {
return Ok(MutationResult::Skipped);
}
// # Safety
// other_size >= 2
let from = state
.rand_mut()
.below(unsafe { NonZero::new(other_size).unwrap_unchecked() });
let Some(non_zero_other_size) = NonZero::new(other_size) else {
return Ok(MutationResult::Skipped);
};
// # Safety
// size > 0, other_size > from,
let len = state
.rand_mut()
.below(unsafe { NonZero::new(min(other_size - from, size)).unwrap_unchecked() });
let from = state.rand_mut().below(non_zero_other_size);
let Some(non_zero_min_len) = NonZero::new(min(other_size - from, size)) else {
return Ok(MutationResult::Skipped);
};
let len = state.rand_mut().below(non_zero_min_len);
// # Safety
// size is non-zero, len is below min(size, ...), so the subtraction will always be positive.
let to = state

View File

@ -16,7 +16,7 @@ use crate::{
generators::GramatronGenerator,
inputs::{GramatronInput, Terminal},
mutators::{MutationResult, Mutator},
random_corpus_id,
nonzero, random_corpus_id,
state::{HasCorpus, HasRand},
Error, HasMetadata,
};
@ -222,12 +222,12 @@ where
let chosen = *state.rand_mut().choose(&self.states).unwrap();
let chosen_nums = self.counters.get(&chosen).unwrap().0;
let Some(non_zero_chosen_nums_minus_one) = NonZero::new(chosen_nums - 1) else {
let Some(minus_one) = NonZero::new(chosen_nums - 1) else {
return Ok(MutationResult::Skipped);
};
#[allow(clippy::cast_sign_loss, clippy::pedantic)]
let mut first = state.rand_mut().below(non_zero_chosen_nums_minus_one) as i64;
let mut first = state.rand_mut().below(minus_one) as i64;
#[allow(clippy::cast_sign_loss, clippy::pedantic)]
let mut second = state
.rand_mut()
@ -259,10 +259,7 @@ where
input.terminals_mut().truncate(idx_1);
for _ in 0..state
.rand_mut()
.below(NonZero::new(RECUR_THRESHOLD).unwrap())
{
for _ in 0..state.rand_mut().below(nonzero!(RECUR_THRESHOLD)) {
input.terminals_mut().extend_from_slice(&self.feature);
}

View File

@ -259,6 +259,11 @@ where
}
};
let gen = generalised_meta.generalized_mut();
let Some(_) = NonZero::new(gen.len()) else {
return Err(Error::illegal_state("No generalized metadata found."));
};
let token_find = state.rand_mut().below(tokens_len);
let mut token_replace = state.rand_mut().below(tokens_len);
if token_find == token_replace {
@ -274,11 +279,11 @@ where
let mut mutated = MutationResult::Skipped;
let gen = generalised_meta.generalized_mut();
let rand_idx = fast_bound(
rand_idx,
NonZero::new(gen.len()).ok_or_else(|| Error::empty("No Generalized Metadata found"))?,
);
// # Safety
// gen.len() is positive.
let rand_idx = fast_bound(rand_idx, unsafe {
NonZero::new(gen.len()).unwrap_unchecked()
});
'first: for item in &mut gen[..rand_idx] {
if let GeneralizedItem::Bytes(bytes) = item {

View File

@ -3,10 +3,7 @@
//! It uses a modified Particle Swarm Optimization algorithm to determine an optimal distribution of mutators.
//! See <https://github.com/puppet-meteor/MOpt-AFL> and <https://www.usenix.org/conference/usenixsecurity19/presentation/lyu>
use alloc::{borrow::Cow, string::ToString, vec::Vec};
use core::{
fmt::{self, Debug},
num::{NonZero, NonZeroUsize},
};
use core::fmt::{self, Debug};
use libafl_bolts::{
rands::{Rand, StdRand},
@ -370,7 +367,7 @@ pub struct StdMOptMutator<MT> {
mode: MOptMode,
finds_before: usize,
mutations: MT,
max_stack_pow: NonZeroUsize,
max_stack_pow: usize,
}
impl<I, MT, S> Mutator<I, S> for StdMOptMutator<MT>
@ -514,11 +511,7 @@ impl<MT> StdMOptMutator<MT> {
let rand_seed = state.rand_mut().next();
state.add_metadata::<MOpt>(MOpt::new(MT::LEN, swarm_num, rand_seed)?);
}
let Some(max_stack_pow) = NonZero::new(max_stack_pow) else {
return Err(Error::illegal_argument(
"Got 0 as value for max_stack_pow in StdMOptMutator.",
));
};
Ok(Self {
name: Cow::from(format!("StdMOptMutator[{}]", mutations.names().join(","))),
mode: MOptMode::Pilotfuzzing,
@ -618,7 +611,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().below(self.max_stack_pow))
1 << (1 + state.rand_mut().zero_upto(self.max_stack_pow))
}
/// Get the next mutation to apply

View File

@ -156,10 +156,10 @@ where
.map(|(id, part)| (id, part.bytes().len()));
if let Some((part_idx, size)) = maybe_size {
let Some(nonzero_size) = NonZero::new(size) else {
let Some(nz) = NonZero::new(size) else {
return Ok(MutationResult::Skipped);
};
let target = state.rand_mut().below(nonzero_size);
let target = state.rand_mut().below(nz);
// # Safety
// size is nonzero here (checked above), target is smaller than size
// -> the subtraction result is greater than 0.
@ -212,11 +212,11 @@ where
.unwrap();
drop(other_testcase);
let size = part.bytes().len();
let Some(nonzero_size) = NonZero::new(size) else {
let Some(nz) = NonZero::new(size) else {
return Ok(MutationResult::Skipped);
};
let target = state.rand_mut().below(nonzero_size);
let target = state.rand_mut().below(nz);
// # Safety
// other_size is larger than 0, checked above.
// size is larger than 0.
@ -285,11 +285,11 @@ where
.map(|(id, part)| (id, part.bytes().len()));
if let Some((part_idx, size)) = maybe_size {
let Some(nonzero_size) = NonZero::new(size) else {
let Some(nz) = NonZero::new(size) else {
return Ok(MutationResult::Skipped);
};
let target = state.rand_mut().below(nonzero_size);
let target = state.rand_mut().below(nz);
// # Safety
// other_size is checked above.
// size is larger than than target and larger than 1. The subtraction result will always be positive.
@ -335,11 +335,11 @@ where
.unwrap();
drop(other_testcase);
let size = part.bytes().len();
let Some(nonzero_size) = NonZero::new(size) else {
let Some(nz) = NonZero::new(size) else {
return Ok(MutationResult::Skipped);
};
let target = state.rand_mut().below(nonzero_size);
let target = state.rand_mut().below(nz);
// # Safety
// other_size is checked above.
// size is larger than than target and larger than 1. The subtraction result will always be positive.

View File

@ -18,7 +18,7 @@ use crate::{
corpus::Corpus,
inputs::HasMutatorBytes,
mutators::{MutationResult, Mutator},
random_corpus_id_with_disabled,
nonzero, random_corpus_id_with_disabled,
state::{HasCorpus, HasMaxSize, HasRand},
Error,
};
@ -73,10 +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 Some(upper_len_minus1) = NonZero::new(upper + len - 1) else {
return 0..0;
};
let mut offset2 = 1 + state.rand_mut().below(upper_len_minus1);
let mut offset2 = 1 + state.rand_mut().zero_upto(upper + len - 1);
let offset1 = offset2.saturating_sub(len);
if offset2 > upper {
offset2 = upper;
@ -314,7 +311,7 @@ where
Ok(MutationResult::Skipped)
} else {
let byte = state.rand_mut().choose(input.bytes_mut()).unwrap();
*byte ^= 1 + state.rand_mut().below(NonZero::new(254).unwrap()) as u8;
*byte ^= 1 + state.rand_mut().below(nonzero!(254)) as u8;
Ok(MutationResult::Mutated)
}
}
@ -365,8 +362,8 @@ macro_rules! add_mutator_impl {
let val = <$size>::from_ne_bytes(bytes.try_into().unwrap());
// mutate
let num = 1 + state.rand_mut().below(NonZero::new(ARITH_MAX).unwrap()) as $size;
let new_val = match state.rand_mut().below(NonZero::new(4).unwrap()) {
let num = 1 + state.rand_mut().below(nonzero!(ARITH_MAX)) as $size;
let new_val = match state.rand_mut().below(nonzero!(4)) {
0 => val.wrapping_add(num),
1 => val.wrapping_sub(num),
2 => val.swap_bytes().wrapping_add(num).swap_bytes(),
@ -569,7 +566,7 @@ where
return Ok(MutationResult::Skipped);
}
let mut amount = 1 + state.rand_mut().below(NonZero::new(16).unwrap());
let mut amount = 1 + state.rand_mut().below(nonzero!(16));
// # Safety
// It's a safe assumption that size + 1 is never 0.
// If we wrap around we have _a lot_ of elements - and the code will break later anyway.
@ -632,7 +629,7 @@ where
return Ok(MutationResult::Skipped);
}
let mut amount = 1 + state.rand_mut().below(NonZero::new(16).unwrap());
let mut amount = 1 + state.rand_mut().below(nonzero!(16));
// # Safety
// size + 1 can never be 0
let offset = state
@ -835,9 +832,9 @@ where
let max_insert_len = min(size - target, state.max_size() - size);
let max_insert_len = min(16, max_insert_len);
let Some(max_insert_len) = NonZero::new(max_insert_len) else {
return Ok(MutationResult::Skipped);
};
// # Safety
// size > target and state.max_size() > size
let max_insert_len = unsafe { NonZero::new(max_insert_len).unwrap_unchecked() };
let range = rand_range(state, size, max_insert_len);
@ -989,13 +986,6 @@ where
}
Ok(MutationResult::Mutated)
} else if first.end != size {
// The first range comes before the second range
debug_assert!(
first.end < size,
"First.end ({}) should never be larger than size ({})!",
first.end,
size
);
// # Safety
// first.end is not equal to size, so subtracting them can never be 0.
let mut second = rand_range(state, size - first.end, unsafe {

View File

@ -3,7 +3,7 @@
use alloc::{borrow::Cow, vec::Vec};
use core::{
fmt::Debug,
num::{NonZero, NonZeroUsize},
num::NonZero,
ops::{Deref, DerefMut},
};
@ -21,6 +21,7 @@ use crate::{
token_mutations::{TokenInsert, TokenReplace},
MutationResult, Mutator, MutatorsTuple,
},
nonzero,
state::{HasCorpus, HasRand},
Error, HasMetadata,
};
@ -102,7 +103,7 @@ where
pub struct StdScheduledMutator<MT> {
name: Cow<'static, str>,
mutations: MT,
max_stack_pow: NonZeroUsize,
max_stack_pow: usize,
}
impl<MT> Named for StdScheduledMutator<MT> {
@ -144,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().below(self.max_stack_pow))
1 << (1 + state.rand_mut().zero_upto(self.max_stack_pow))
}
/// Get the next mutation to apply
@ -171,7 +172,7 @@ where
mutations.names().join(", ")
)),
mutations,
max_stack_pow: NonZero::new(7).unwrap(),
max_stack_pow: 7,
}
}
@ -180,18 +181,15 @@ where
/// # Errors
/// Will return [`Error::IllegalArgument`] for `max_stack_pow` of 0.
#[inline]
pub fn with_max_stack_pow(mutations: MT, max_stack_pow: usize) -> Result<Self, Error> {
let Some(max_stack_pow) = NonZero::new(max_stack_pow) else {
return Err(Error::illegal_argument("Max stack pow may not be 0."));
};
Ok(Self {
pub fn with_max_stack_pow(mutations: MT, max_stack_pow: usize) -> Self {
Self {
name: Cow::from(format!(
"StdScheduledMutator[{}]",
mutations.names().join(", ")
)),
mutations,
max_stack_pow,
})
}
}
}
@ -266,7 +264,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().below(NonZero::new(6).unwrap()))
1 << (1 + state.rand_mut().below(nonzero!(7)))
}
/// Get the next mutation to apply

View File

@ -323,9 +323,12 @@ where
let token_idx = state.rand_mut().below(tokens_len);
let size = input.bytes().len();
// # Safety
// after saturating add it's always above 0
let off = state
.rand_mut()
.below(NonZero::new(size.wrapping_add(1)).unwrap());
.below(unsafe { NonZero::new(size.saturating_add(1)).unwrap_unchecked() });
let meta = state.metadata_map().get::<Tokens>().unwrap();
let token = &meta.tokens()[token_idx];
@ -376,7 +379,9 @@ where
{
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
let size = input.bytes().len();
let Some(nonzero_size) = NonZero::new(size) else {
let off = if let Some(nz) = NonZero::new(size) {
state.rand_mut().below(nz)
} else {
return Ok(MutationResult::Skipped);
};
@ -392,8 +397,6 @@ where
};
let token_idx = state.rand_mut().below(tokens_len);
let off = state.rand_mut().below(nonzero_size);
let meta = state.metadata_map().get::<Tokens>().unwrap();
let token = &meta.tokens()[token_idx];
let mut len = token.len();

View File

@ -4,10 +4,7 @@
//! a specific mutator for a specified amount of iterations
use alloc::{borrow::Cow, vec::Vec};
use core::{
fmt::Debug,
num::{NonZero, NonZeroUsize},
};
use core::{fmt::Debug, num::NonZero};
use libafl_bolts::{
impl_serdeany, math::calculate_cumulative_distribution_in_place, rands::Rand,
@ -86,7 +83,7 @@ impl TuneableScheduledMutatorMetadata {
pub struct TuneableScheduledMutator<MT> {
name: Cow<'static, str>,
mutations: MT,
max_stack_pow: NonZeroUsize,
max_stack_pow: usize,
}
impl<I, MT, S> Mutator<I, S> for TuneableScheduledMutator<MT>
@ -135,7 +132,7 @@ where
iters
} else {
// fall back to random
1 << (1 + state.rand_mut().below(self.max_stack_pow))
1 << (1 + state.rand_mut().zero_upto(self.max_stack_pow))
}
} else {
// We will sample using the mutation probabilities.
@ -218,7 +215,7 @@ impl<MT> TuneableScheduledMutator<MT> {
TuneableScheduledMutator {
name: Cow::from(format!("TuneableMutator[{}]", mutations.names().join(", "))),
mutations,
max_stack_pow: NonZero::new(7).unwrap(),
max_stack_pow: 7,
}
}
}

View File

@ -13,6 +13,7 @@ use crate::{
corpus::{Corpus, CorpusId, HasTestcase, Testcase},
inputs::{BytesInput, HasMutatorBytes},
mutators::{rand_range, MutationResult, Mutator, Tokens},
nonzero,
stages::{
extract_metadata,
mutational::{MutatedTransform, MutatedTransformPost},
@ -233,11 +234,7 @@ fn rand_replace_range<S: HasRand + HasMaxSize, F: Fn(&mut S) -> char>(
range: Range<usize>,
char_gen: F,
) -> MutationResult {
let temp_range = rand_range(
state,
range.end - range.start,
NonZero::new(MAX_CHARS).unwrap(),
);
let temp_range = rand_range(state, range.end - range.start, nonzero!(MAX_CHARS));
let range = (range.start + temp_range.start)..(range.start + temp_range.end);
let range = match core::str::from_utf8(&input.0.bytes()[range.clone()]) {
Ok(_) => range,
@ -254,7 +251,7 @@ fn rand_replace_range<S: HasRand + HasMaxSize, F: Fn(&mut S) -> char>(
return MutationResult::Skipped;
}
let replace_len = state.rand_mut().below(NonZero::new(MAX_CHARS).unwrap());
let replace_len = state.rand_mut().below(nonzero!(MAX_CHARS));
let orig_len = range.end - range.start;
if input.0.len() - orig_len + replace_len > state.max_size() {
return MutationResult::Skipped;

View File

@ -4,7 +4,7 @@ use alloc::{
collections::binary_heap::BinaryHeap,
vec::Vec,
};
use core::{cmp::Ordering, fmt::Debug, marker::PhantomData, num::NonZero, ops::Range};
use core::{cmp::Ordering, fmt::Debug, marker::PhantomData, ops::Range};
use libafl_bolts::{
rands::Rand,
@ -19,6 +19,7 @@ use crate::{
executors::{Executor, HasObservers},
inputs::{HasMutatorBytes, UsesInput},
mutators::mutations::buffer_copy,
nonzero,
observers::{MapObserver, ObserversTuple},
stages::{RetryCountRestartHelper, Stage},
state::{HasCorpus, HasCurrentTestcase, HasRand, UsesState},
@ -353,11 +354,11 @@ where
let c = match bytes[idx] {
0x41..=0x46 => {
// 'A' + 1 + rand('F' - 'A')
0x41 + 1 + state.rand_mut().below(NonZero::new(5).unwrap()) as u8
0x41 + 1 + state.rand_mut().below(nonzero!(5)) as u8
}
0x61..=0x66 => {
// 'a' + 1 + rand('f' - 'a')
0x61 + 1 + state.rand_mut().below(NonZero::new(5).unwrap()) as u8
0x61 + 1 + state.rand_mut().below(nonzero!(5)) as u8
}
0x30 => {
// '0' -> '1'
@ -369,35 +370,35 @@ where
}
0x32..=0x39 => {
// '2' + 1 + rand('9' - '2')
0x32 + 1 + state.rand_mut().below(NonZero::new(7).unwrap()) as u8
0x32 + 1 + state.rand_mut().below(nonzero!(7)) as u8
}
0x47..=0x5a => {
// 'G' + 1 + rand('Z' - 'G')
0x47 + 1 + state.rand_mut().below(NonZero::new(19).unwrap()) as u8
0x47 + 1 + state.rand_mut().below(nonzero!(19)) as u8
}
0x67..=0x7a => {
// 'g' + 1 + rand('z' - 'g')
0x67 + 1 + state.rand_mut().below(NonZero::new(19).unwrap()) as u8
0x67 + 1 + state.rand_mut().below(nonzero!(19)) as u8
}
0x21..=0x2a => {
// '!' + 1 + rand('*' - '!');
0x21 + 1 + state.rand_mut().below(NonZero::new(9).unwrap()) as u8
0x21 + 1 + state.rand_mut().below(nonzero!(9)) as u8
}
0x2c..=0x2e => {
// ',' + 1 + rand('.' - ',')
0x2c + 1 + state.rand_mut().below(NonZero::new(2).unwrap()) as u8
0x2c + 1 + state.rand_mut().below(nonzero!(2)) as u8
}
0x3a..=0x40 => {
// ':' + 1 + rand('@' - ':')
0x3a + 1 + state.rand_mut().below(NonZero::new(6).unwrap()) as u8
0x3a + 1 + state.rand_mut().below(nonzero!(6)) as u8
}
0x5b..=0x60 => {
// '[' + 1 + rand('`' - '[')
0x5b + 1 + state.rand_mut().below(NonZero::new(5).unwrap()) as u8
0x5b + 1 + state.rand_mut().below(nonzero!(5)) as u8
}
0x7b..=0x7e => {
// '{' + 1 + rand('~' - '{')
0x7b + 1 + state.rand_mut().below(NonZero::new(3).unwrap()) as u8
0x7b + 1 + state.rand_mut().below(nonzero!(3)) as u8
}
0x2b => {
// '+' -> '/'

View File

@ -5,10 +5,7 @@ use alloc::{
borrow::{Cow, ToOwned},
string::ToString,
};
use core::{
marker::PhantomData,
num::{NonZero, NonZeroUsize},
};
use core::{marker::PhantomData, num::NonZeroUsize};
use libafl_bolts::{rands::Rand, Named};
@ -18,6 +15,7 @@ use crate::{
inputs::Input,
mark_feature_time,
mutators::{MultiMutator, MutationResult, Mutator},
nonzero,
stages::{RetryCountRestartHelper, Stage},
start_timer,
state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasRand, UsesState},
@ -155,7 +153,7 @@ where
/// Default value, how many iterations each stage gets, as an upper bound.
/// It may randomly continue earlier.
pub static DEFAULT_MUTATIONAL_MAX_ITERATIONS: usize = 128;
pub const DEFAULT_MUTATIONAL_MAX_ITERATIONS: usize = 128;
/// The default mutational stage
#[derive(Clone, Debug)]
@ -263,12 +261,12 @@ where
/// Creates a new default mutational stage
pub fn new(mutator: M) -> Self {
// Safe to unwrap: DEFAULT_MUTATIONAL_MAX_ITERATIONS is never 0.
Self::transforming_with_max_iterations(mutator, DEFAULT_MUTATIONAL_MAX_ITERATIONS).unwrap()
Self::transforming_with_max_iterations(mutator, nonzero!(DEFAULT_MUTATIONAL_MAX_ITERATIONS))
}
/// Creates a new mutational stage with the given max iterations
#[inline]
pub fn with_max_iterations(mutator: M, max_iterations: usize) -> Result<Self, Error> {
pub fn with_max_iterations(mutator: M, max_iterations: NonZeroUsize) -> Self {
Self::transforming_with_max_iterations(mutator, max_iterations)
}
}
@ -284,7 +282,7 @@ where
/// Creates a new transforming mutational stage with the default max iterations
pub fn transforming(mutator: M) -> Self {
// Safe to unwrap: DEFAULT_MUTATIONAL_MAX_ITERATIONS is never 0.
Self::transforming_with_max_iterations(mutator, DEFAULT_MUTATIONAL_MAX_ITERATIONS).unwrap()
Self::transforming_with_max_iterations(mutator, nonzero!(DEFAULT_MUTATIONAL_MAX_ITERATIONS))
}
/// Creates a new transforming mutational stage with the given max iterations
@ -292,14 +290,7 @@ where
/// # Errors
/// Will return [`Error::IllegalArgument`] for `max_iterations` of 0.
#[inline]
pub fn transforming_with_max_iterations(
mutator: M,
max_iterations: usize,
) -> Result<Self, Error> {
// unsafe but impossible that you create two threads both instantiating this instance
let Some(max_iterations) = NonZero::new(max_iterations) else {
return Err(Error::illegal_argument("0 max iterations is not allowed.."));
};
pub fn transforming_with_max_iterations(mutator: M, max_iterations: NonZeroUsize) -> Self {
let stage_id = unsafe {
let ret = MUTATIONAL_STAGE_ID;
MUTATIONAL_STAGE_ID += 1;
@ -307,12 +298,12 @@ where
};
let name =
Cow::Owned(MUTATIONAL_STAGE_NAME.to_owned() + ":" + stage_id.to_string().as_str());
Ok(Self {
Self {
name,
mutator,
max_iterations,
phantom: PhantomData,
})
}
}
}

View File

@ -5,7 +5,6 @@ use alloc::rc::Rc;
use core::{
cell::{Cell, RefCell},
fmt::Debug,
num::NonZero,
};
use libafl_bolts::rands::Rand;
@ -19,6 +18,7 @@ use crate::{
inputs::UsesInput,
mark_feature_time,
mutators::Mutator,
nonzero,
observers::ObserversTuple,
schedulers::Scheduler,
start_timer,
@ -29,7 +29,7 @@ use crate::{
use crate::{monitors::PerfFeature, state::HasClientPerfMonitor};
/// The default maximum number of mutations to perform per input.
pub static DEFAULT_MUTATIONAL_MAX_ITERATIONS: usize = 128;
pub const DEFAULT_MUTATIONAL_MAX_ITERATIONS: usize = 128;
/// A Mutational push stage is the stage in a fuzzing run that mutates inputs.
///
@ -74,7 +74,7 @@ where
fn iterations(&self, state: &mut Z::State, _corpus_id: CorpusId) -> Result<usize, Error> {
Ok(1 + state
.rand_mut()
.below(NonZero::new(DEFAULT_MUTATIONAL_MAX_ITERATIONS).unwrap()))
.below(nonzero!(DEFAULT_MUTATIONAL_MAX_ITERATIONS)))
}
/// Sets the current corpus index

View File

@ -1,7 +1,7 @@
//! A [`crate::stages::MutationalStage`] where the mutator iteration can be tuned at runtime
use alloc::string::{String, ToString};
use core::{marker::PhantomData, num::NonZero, time::Duration};
use core::{marker::PhantomData, time::Duration};
use libafl_bolts::{current_time, impl_serdeany, rands::Rand};
use serde::{Deserialize, Serialize};
@ -10,6 +10,7 @@ use crate::{
corpus::Corpus,
mark_feature_time,
mutators::{MutationResult, Mutator},
nonzero,
stages::{
mutational::{MutatedTransform, MutatedTransformPost, DEFAULT_MUTATIONAL_MAX_ITERATIONS},
ExecutionCountRestartHelper, MutationalStage, Stage,
@ -250,7 +251,7 @@ where
// fall back to random
1 + state
.rand_mut()
.below(NonZero::new(DEFAULT_MUTATIONAL_MAX_ITERATIONS).unwrap()),
.below(nonzero!(DEFAULT_MUTATIONAL_MAX_ITERATIONS)),
)
}
}

View File

@ -1050,6 +1050,46 @@ pub unsafe fn set_error_print_panic_hook(new_stderr: RawFd) {
}));
}
// Credit goes to https://github.com/thomcc/nonzero_lit
// We don't want add another dependency and just want to use usize macro of it.
#[doc(hidden)]
pub mod _private {
pub use core::num::NonZeroUsize;
macro_rules! define_nz_ctor {
($(pub fn $nz_func:ident($n:ident : $int:ident) -> $NonZeroInt:ident;)+) => {$(
#[inline]
#[must_use]
pub const fn $nz_func($n : $int) -> $NonZeroInt {
// Note: Hacky const fn assert.
let _ = ["N must not be zero"][($n == 0) as usize];
match $NonZeroInt::new($n) {
Some(x) => x,
// The assert above makes this branch unreachable
None => unreachable!(),
}
}
)+};
}
define_nz_ctor! {
pub fn nz_usize(n: usize) -> NonZeroUsize;
}
}
/// 0 cost way to create check nonzero on compilation.
#[macro_export]
macro_rules! nonzero {
($val:expr $(,)?) => {{
const __E: usize = $val;
{
const NZ: $crate::_private::NonZeroUsize = $crate::_private::nz_usize(__E);
NZ
}
}};
}
#[cfg(feature = "python")]
#[allow(missing_docs)]
pub mod pybind {

View File

@ -96,6 +96,13 @@ pub fn fast_bound(rand: u64, n: NonZeroUsize) -> usize {
(mul >> 64) as usize
}
#[inline]
#[must_use]
fn fast_bound_usize(rand: u64, n: usize) -> usize {
let mul = u128::from(rand).wrapping_mul(u128::from(n as u64));
(mul >> 64) as usize
}
/// Ways to get random around here.
/// Please note that these are not cryptographically secure.
/// Or, even if some might be by accident, at least they are not seeded in a cryptographically secure fashion.
@ -130,14 +137,9 @@ pub trait Rand: Debug + Serialize + DeserializeOwned {
fast_bound(self.next(), upper_bound_excl)
}
/// Gets a value below the given bound (inclusive)
#[inline]
fn below_incl(&mut self, upper_bound_incl: usize) -> usize {
let Some(upper_bound) = NonZero::new(upper_bound_incl.wrapping_add(1)) else {
// The max value + 1 wrapped around to 0. We just do a "normal" random.
return self.next() as usize;
};
self.below(upper_bound)
/// Gets a value between [0, n]
fn zero_upto(&mut self, n: usize) -> usize {
fast_bound_usize(self.next(), n)
}
/// Gets a value between the given lower bound (inclusive) and upper bound (inclusive)
@ -548,17 +550,18 @@ impl XkcdRand {
#[cfg(test)]
mod tests {
use core::num::NonZero;
use crate::rands::{
Rand, RomuDuoJrRand, RomuTrioRand, Sfc64Rand, StdRand, XorShift64Rand,
Xoshiro256PlusPlusRand,
use crate::{
nonzero,
rands::{
Rand, RomuDuoJrRand, RomuTrioRand, Sfc64Rand, StdRand, XorShift64Rand,
Xoshiro256PlusPlusRand,
},
};
fn test_single_rand<R: Rand>(rand: &mut R) {
assert_ne!(rand.next(), rand.next());
assert!(rand.below(NonZero::new(100).unwrap()) < 100);
assert_eq!(rand.below(NonZero::new(1).unwrap()), 0);
assert!(rand.below(nonzero!(100)) < 100);
assert_eq!(rand.below(nonzero!(1)), 0);
assert_eq!(rand.between(10, 10), 10);
assert!(rand.between(11, 20) > 10);
}

View File

@ -77,8 +77,8 @@ pub mod executor;
pub mod utils;
// for parsing asan and cmplog cores
use libafl_bolts::core_affinity::{get_core_ids, CoreId, Cores};
use libafl_bolts::core_affinity::{get_core_ids, CoreId, Cores};
/// A representation of the various Frida options
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
#[allow(clippy::struct_excessive_bools)]
@ -326,6 +326,7 @@ impl Default for FridaOptions {
#[cfg(test)]
mod tests {
use core::num::NonZero;
use std::sync::OnceLock;
use clap::Parser;
@ -504,8 +505,10 @@ mod tests {
);
let mutator = StdScheduledMutator::new(tuple_list!(BitFlipMutator::new()));
let mut stages =
tuple_list!(StdMutationalStage::with_max_iterations(mutator, 1).unwrap());
let mut stages = tuple_list!(StdMutationalStage::with_max_iterations(
mutator,
NonZero::new(1).unwrap()
));
log::info!("Starting fuzzing!");
fuzzer

View File

@ -170,9 +170,10 @@ macro_rules! fuzz_with {
StdFuzzer,
};
use libafl_targets::{CmpLogObserver, LLVMCustomMutator, OomFeedback, OomObserver, CMP_MAP};
use libafl_bolts::nonzero;
use rand::{thread_rng, RngCore};
use std::{env::temp_dir, fs::create_dir, path::PathBuf};
use core::num::NonZeroUsize;
use crate::{
CustomMutationStatus,
corpus::{ArtifactCorpus, LibfuzzerCorpus},
@ -375,7 +376,7 @@ macro_rules! fuzz_with {
LLVMCustomMutator::mutate_unchecked(StdScheduledMutator::new(havoc_mutations_no_crossover().merge(tokens_mutations())))
};
// Safe to unwrap: stack pow is not 0.
let std_mutator_no_mutate = StdScheduledMutator::with_max_stack_pow(havoc_crossover(), 3).unwrap();
let std_mutator_no_mutate = StdScheduledMutator::with_max_stack_pow(havoc_crossover(),3);
let cm_power: StdPowerMutationalStage<_, _, BytesInput, _, _> = StdPowerMutationalStage::new(custom_mutator);
let cm_power = IfStage::new(|_, _, _, _| Ok(mutator_status.custom_mutation.into()), (cm_power, ()));
@ -391,7 +392,7 @@ macro_rules! fuzz_with {
LLVMCustomMutator::crossover_unchecked(StdScheduledMutator::with_max_stack_pow(
havoc_mutations_no_crossover().merge(tokens_mutations()),
3,
).unwrap())
))
};
let std_mutator_no_crossover = StdScheduledMutator::new(havoc_mutations_no_crossover().merge(tokens_mutations()));
@ -412,7 +413,7 @@ macro_rules! fuzz_with {
GrimoireRandomDeleteMutator::new(),
),
3,
).unwrap();
);
let grimoire = IfStage::new(|_, _, _, _| Ok(grimoire.into()), (StdMutationalStage::transforming(grimoire_mutator), ()));
// A minimization+queue policy to get testcasess from the corpus
@ -467,7 +468,7 @@ macro_rules! fuzz_with {
}
if state.corpus().count() < 1 {
// Generator of bytearrays of max size 64
let mut generator = RandBytesGenerator::from(RandBytesGenerator::new(64).unwrap());
let mut generator = RandBytesGenerator::from(RandBytesGenerator::new(nonzero!(64)));
// Generate 1024 initial inputs
state

View File

@ -24,6 +24,7 @@ use libafl::{
};
use libafl_bolts::{
core_affinity::Cores,
nonzero,
rands::StdRand,
shmem::{ShMem, ShMemProvider, UnixShMemProvider},
tuples::{tuple_list, Handled, Merge},
@ -213,7 +214,7 @@ impl ForkserverBytesCoverageSugar<'_> {
if state.must_load_initial_inputs() {
if self.input_dirs.is_empty() {
// Generator of printable bytearrays of max size 32
let mut generator = RandBytesGenerator::new(32).unwrap();
let mut generator = RandBytesGenerator::new(nonzero!(32));
// Generate 8 initial inputs
state

View File

@ -27,6 +27,7 @@ use libafl::{
};
use libafl_bolts::{
core_affinity::Cores,
nonzero,
ownedref::OwnedMutSlice,
rands::StdRand,
shmem::{ShMemProvider, StdShMemProvider},
@ -229,7 +230,7 @@ where
if state.must_load_initial_inputs() {
if self.input_dirs.is_empty() {
// Generator of printable bytearrays of max size 32
let mut generator = RandBytesGenerator::new(32).unwrap();
let mut generator = RandBytesGenerator::new(nonzero!(32));
// Generate 8 initial inputs
state

View File

@ -30,6 +30,7 @@ use libafl::{
};
use libafl_bolts::{
core_affinity::Cores,
nonzero,
ownedref::OwnedMutSlice,
rands::StdRand,
shmem::{ShMemProvider, StdShMemProvider},
@ -259,7 +260,7 @@ where
if state.must_load_initial_inputs() {
if self.input_dirs.is_empty() {
// Generator of printable bytearrays of max size 32
let mut generator = RandBytesGenerator::new(32).unwrap();
let mut generator = RandBytesGenerator::new(nonzero!(32));
// Generate 8 initial inputs
state
@ -375,7 +376,7 @@ where
if state.must_load_initial_inputs() {
if self.input_dirs.is_empty() {
// Generator of printable bytearrays of max size 32
let mut generator = RandBytesGenerator::new(32).unwrap();
let mut generator = RandBytesGenerator::new(nonzero!(32));
// Generate 8 initial inputs
state