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; extern crate libafl_bolts;
use std::path::PathBuf; use std::path::PathBuf;
use libafl::{ use libafl::{
corpus::{InMemoryCorpus, OnDiskCorpus}, corpus::{InMemoryCorpus, OnDiskCorpus},
events::SimpleEventManager, events::SimpleEventManager,
@ -15,7 +14,7 @@ use libafl::{
schedulers::QueueScheduler, schedulers::QueueScheduler,
state::StdState, state::StdState,
}; };
use libafl_bolts::{rands::StdRand, tuples::tuple_list, AsSlice}; use libafl_bolts::{rands::StdRand, tuples::tuple_list, AsSlice, nonzero};
/* ANCHOR_END: use */ /* ANCHOR_END: use */
fn main() { fn main() {
@ -77,7 +76,7 @@ fn main() {
/* ANCHOR: generator */ /* ANCHOR: generator */
// Generator of printable bytearrays of max size 32 // 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 // Generate 8 initial inputs
state state

View File

@ -15,7 +15,7 @@ use libafl::{
schedulers::QueueScheduler, schedulers::QueueScheduler,
state::StdState, 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; use std::path::PathBuf;
/* ANCHOR_END: use */ /* ANCHOR_END: use */
@ -105,7 +105,7 @@ fn main() {
/* ANCHOR_END: executor_with_observer */ /* ANCHOR_END: executor_with_observer */
// Generator of printable bytearrays of max size 32 // 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 // Generate 8 initial inputs
state state

View File

@ -1,6 +1,7 @@
/* ANCHOR: use */ /* ANCHOR: use */
extern crate libafl; extern crate libafl;
extern crate libafl_bolts; extern crate libafl_bolts;
use std::num::NonZeroUsize;
use libafl::{ use libafl::{
corpus::{InMemoryCorpus, OnDiskCorpus}, corpus::{InMemoryCorpus, OnDiskCorpus},
@ -17,7 +18,7 @@ use libafl::{
stages::mutational::StdMutationalStage, stages::mutational::StdMutationalStage,
state::StdState, 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; use std::path::PathBuf;
/* ANCHOR_END: use */ /* ANCHOR_END: use */
@ -97,7 +98,7 @@ fn main() {
.expect("Failed to create the Executor"); .expect("Failed to create the Executor");
// Generator of printable bytearrays of max size 32 // 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 // Generate 8 initial inputs
state state

View File

@ -20,7 +20,7 @@ use libafl::{
stages::mutational::StdMutationalStage, stages::mutational::StdMutationalStage,
state::StdState, 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 /// Coverage map with explicit assignments due to the lack of instrumentation
static mut SIGNALS: [u8; 16] = [0; 16]; static mut SIGNALS: [u8; 16] = [0; 16];
@ -116,7 +116,7 @@ pub fn main() {
.expect("Failed to create the Executor"); .expect("Failed to create the Executor");
// Generator of printable bytearrays of max size 32 // 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 // Generate 8 initial inputs
state state

View File

@ -86,7 +86,7 @@ pub fn main() -> Result<(), Error> {
.expect("Failed to create the Executor"); .expect("Failed to create the Executor");
// Generator of printable bytearrays of max size 32 // 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 // Generate 8 initial inputs
state state

View File

@ -23,7 +23,7 @@ use libafl::{
stages::mutational::StdMutationalStage, stages::mutational::StdMutationalStage,
state::{HasSolutions, StdState}, 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}; use libafl_targets::{edges_max_num, DifferentialAFLMapSwapObserver};
#[cfg(not(miri))] #[cfg(not(miri))]
use mimalloc::MiMalloc; use mimalloc::MiMalloc;
@ -247,7 +247,7 @@ pub fn main() {
); );
// Generator of printable bytearrays of max size 32 // 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 // Generate 8 initial inputs
state state

View File

@ -17,6 +17,7 @@ use libafl::{
state::StdState, state::StdState,
}; };
use libafl_bolts::{ use libafl_bolts::{
nonzero,
ownedref::OwnedRefMut, ownedref::OwnedRefMut,
rands::StdRand, rands::StdRand,
shmem::{ShMemProvider, StdShMemProvider}, shmem::{ShMemProvider, StdShMemProvider},
@ -103,7 +104,7 @@ pub fn main() {
.expect("Failed to create the Executor"); .expect("Failed to create the Executor");
// Generator of printable bytearrays of max size 32 // 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 // Generate 8 initial inputs
state state

View File

@ -16,7 +16,7 @@ use libafl::{
stages::mutational::StdMutationalStage, stages::mutational::StdMutationalStage,
state::StdState, 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; use libc::c_uchar;
extern crate libc; extern crate libc;
@ -89,7 +89,7 @@ pub fn main() {
.expect("Failed to create the Executor"); .expect("Failed to create the Executor");
// Generator of printable bytearrays of max size 32 // 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 // Generate 8 initial inputs
state state

View File

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

View File

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

View File

@ -19,6 +19,7 @@ use libafl::{
state::StdState, state::StdState,
}; };
use libafl_bolts::{ use libafl_bolts::{
nonzero,
ownedref::OwnedRefMut, ownedref::OwnedRefMut,
rands::StdRand, rands::StdRand,
shmem::{unix_shmem, ShMem, ShMemProvider}, shmem::{unix_shmem, ShMem, ShMemProvider},
@ -122,7 +123,7 @@ pub fn main() {
.expect("Failed to create the Executor"); .expect("Failed to create the Executor");
// Generator of printable bytearrays of max size 32 // 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 // Generate 8 initial inputs
state state

View File

@ -18,7 +18,7 @@ use libafl::{
stages::mutational::StdMutationalStage, stages::mutational::StdMutationalStage,
state::StdState, 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 /// Coverage map with explicit assignments due to the lack of instrumentation
static mut SIGNALS: [u8; 16] = [0; 16]; static mut SIGNALS: [u8; 16] = [0; 16];
@ -113,7 +113,7 @@ pub fn main() {
.expect("Failed to create the Executor"); .expect("Failed to create the Executor");
// Generator of printable bytearrays of max size 32 // 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 // Generate 8 initial inputs
state state

View File

@ -18,6 +18,7 @@ use libafl::{
state::StdState, state::StdState,
}; };
use libafl_bolts::{ use libafl_bolts::{
nonzero,
rands::StdRand, rands::StdRand,
shmem::{unix_shmem, ShMemProvider}, shmem::{unix_shmem, ShMemProvider},
tuples::tuple_list, tuples::tuple_list,
@ -115,7 +116,7 @@ pub fn main() {
.expect("Failed to create the Executor"); .expect("Failed to create the Executor");
// Generator of printable bytearrays of max size 32 // 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 // Generate 8 initial inputs
state state

View File

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

View File

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

View File

@ -15,7 +15,9 @@ use libafl::{
state::{HasSolutions, StdState}, state::{HasSolutions, StdState},
Fuzzer, StdFuzzer, 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 wasm_bindgen::prelude::*;
use web_sys::{Performance, Window}; use web_sys::{Performance, Window};
@ -126,7 +128,7 @@ pub fn fuzz() {
.expect("Failed to create the Executor"); .expect("Failed to create the Executor");
// Generator of printable bytearrays of max size 32 // 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 // Generate 8 initial inputs
state state

View File

@ -25,7 +25,7 @@ use libafl::{
stages::mutational::StdMutationalStage, stages::mutational::StdMutationalStage,
state::StdState, 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))] #[cfg(any(windows, unix))]
use libc::{abort, printf}; use libc::{abort, printf};
use static_alloc::Bump; 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"); .expect("Failed to create the Executor");
// Generator of printable bytearrays of max size 32 // 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 // Generate 8 initial inputs
state state

View File

@ -34,6 +34,7 @@ use libafl::{
}; };
use libafl_bolts::{ use libafl_bolts::{
core_affinity::Cores, core_affinity::Cores,
nonzero,
rands::StdRand, rands::StdRand,
shmem::{ShMemProvider, StdShMemProvider}, shmem::{ShMemProvider, StdShMemProvider},
tuples::{tuple_list, Merge}, tuples::{tuple_list, Merge},
@ -240,7 +241,7 @@ pub extern "C" fn LLVMFuzzerRunDriver(
if state.must_load_initial_inputs() { if state.must_load_initial_inputs() {
if input_dirs.is_empty() { if input_dirs.is_empty() {
// Generator of printable bytearrays of max size 32 // 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 // Generate 8 initial inputs
state state

View File

@ -18,7 +18,7 @@ use libafl::{
stages::mutational::StdMutationalStage, stages::mutational::StdMutationalStage,
state::StdState, 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 /// Coverage map with explicit assignments due to the lack of instrumentation
static mut SIGNALS: [u8; 16] = [0; 16]; static mut SIGNALS: [u8; 16] = [0; 16];
@ -93,7 +93,7 @@ fn input_generator() {
.expect("Failed to create the Executor"); .expect("Failed to create the Executor");
// Generator of printable bytearrays of max size 32 // 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 // Generate 8 initial inputs
state state

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,7 +2,10 @@ use alloc::{borrow::ToOwned, string::String, vec::Vec};
use core::num::NonZero; use core::num::NonZero;
use hashbrown::HashMap; use hashbrown::HashMap;
use libafl_bolts::rands::{Rand, RomuDuoJrRand}; use libafl_bolts::{
nonzero,
rands::{Rand, RomuDuoJrRand},
};
use pyo3::prelude::PyObject; use pyo3::prelude::PyObject;
use super::{ use super::{
@ -265,7 +268,7 @@ impl Context {
.take_while(move |r| self.rules_to_min_size[*r] <= max_len) .take_while(move |r| self.rules_to_min_size[*r] <= max_len)
.filter(move |r| { .filter(move |r| {
self.rules_to_num_options[*r] > 1 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. //! Generators may generate bytes or, in general, data, for inputs.
use alloc::vec::Vec; use alloc::vec::Vec;
use core::{ use core::{marker::PhantomData, num::NonZeroUsize};
marker::PhantomData,
num::{NonZero, NonZeroUsize},
};
use libafl_bolts::rands::Rand; 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; pub mod gramatron;
use core::cmp::min;
pub use gramatron::*; pub use gramatron::*;
#[cfg(feature = "nautilus")] #[cfg(feature = "nautilus")]
@ -74,64 +73,45 @@ where
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
/// Generates random bytes /// Generates random bytes
pub struct RandBytesGenerator<S> { pub struct RandBytesGenerator {
max_size: NonZeroUsize, max_size: NonZeroUsize,
phantom: PhantomData<S>,
} }
impl<S> Generator<BytesInput, S> for RandBytesGenerator<S> impl<S> Generator<BytesInput, S> for RandBytesGenerator
where 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); let mut size = state.rand_mut().below(self.max_size);
if size == 0 { size = min(size, 1);
size = 1;
}
let random_bytes: Vec<u8> = (0..size) 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(); .collect();
Ok(BytesInput::new(random_bytes)) Ok(BytesInput::new(random_bytes))
} }
} }
impl<S> RandBytesGenerator<S> { impl RandBytesGenerator {
/// 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))
}
/// Returns a new [`RandBytesGenerator`], generating up to `max_size` random bytes. /// Returns a new [`RandBytesGenerator`], generating up to `max_size` random bytes.
#[must_use] #[must_use]
pub fn from_nonzero(max_size: NonZeroUsize) -> Self { pub fn new(max_size: NonZeroUsize) -> Self {
Self { Self { max_size }
max_size,
phantom: PhantomData,
}
} }
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
/// Generates random printable characters /// Generates random printable characters
pub struct RandPrintablesGenerator<S> { pub struct RandPrintablesGenerator {
max_size: NonZeroUsize, max_size: NonZeroUsize,
phantom: PhantomData<S>,
} }
impl<S> Generator<BytesInput, S> for RandPrintablesGenerator<S> impl<S> Generator<BytesInput, S> for RandPrintablesGenerator
where 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); let mut size = state.rand_mut().below(self.max_size);
if size == 0 { size = min(size, 1);
size = 1;
}
let printables = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz \t\n!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~".as_bytes(); let printables = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz \t\n!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~".as_bytes();
let random_bytes: Vec<u8> = (0..size) let random_bytes: Vec<u8> = (0..size)
.map(|_| *state.rand_mut().choose(printables).unwrap()) .map(|_| *state.rand_mut().choose(printables).unwrap())
@ -140,23 +120,10 @@ where
} }
} }
impl<S> RandPrintablesGenerator<S> { impl RandPrintablesGenerator {
/// 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))
}
/// Returns a new [`RandBytesGenerator`], generating up to `max_size` random bytes. /// Returns a new [`RandBytesGenerator`], generating up to `max_size` random bytes.
#[must_use] #[must_use]
pub fn from_nonzero(max_size: NonZeroUsize) -> Self { pub fn new(max_size: NonZeroUsize) -> Self {
Self { Self { max_size }
max_size,
phantom: PhantomData,
}
} }
} }

View File

@ -83,7 +83,7 @@ pub mod stages;
pub mod state; pub mod state;
pub use fuzzer::*; 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. /// The purpose of this module is to alleviate imports of many components by adding a glob import.
#[cfg(feature = "prelude")] #[cfg(feature = "prelude")]

View File

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

View File

@ -16,7 +16,7 @@ use crate::{
generators::GramatronGenerator, generators::GramatronGenerator,
inputs::{GramatronInput, Terminal}, inputs::{GramatronInput, Terminal},
mutators::{MutationResult, Mutator}, mutators::{MutationResult, Mutator},
random_corpus_id, nonzero, random_corpus_id,
state::{HasCorpus, HasRand}, state::{HasCorpus, HasRand},
Error, HasMetadata, Error, HasMetadata,
}; };
@ -222,12 +222,12 @@ where
let chosen = *state.rand_mut().choose(&self.states).unwrap(); let chosen = *state.rand_mut().choose(&self.states).unwrap();
let chosen_nums = self.counters.get(&chosen).unwrap().0; 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); return Ok(MutationResult::Skipped);
}; };
#[allow(clippy::cast_sign_loss, clippy::pedantic)] #[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)] #[allow(clippy::cast_sign_loss, clippy::pedantic)]
let mut second = state let mut second = state
.rand_mut() .rand_mut()
@ -259,10 +259,7 @@ where
input.terminals_mut().truncate(idx_1); input.terminals_mut().truncate(idx_1);
for _ in 0..state for _ in 0..state.rand_mut().below(nonzero!(RECUR_THRESHOLD)) {
.rand_mut()
.below(NonZero::new(RECUR_THRESHOLD).unwrap())
{
input.terminals_mut().extend_from_slice(&self.feature); 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 token_find = state.rand_mut().below(tokens_len);
let mut token_replace = state.rand_mut().below(tokens_len); let mut token_replace = state.rand_mut().below(tokens_len);
if token_find == token_replace { if token_find == token_replace {
@ -274,11 +279,11 @@ where
let mut mutated = MutationResult::Skipped; let mut mutated = MutationResult::Skipped;
let gen = generalised_meta.generalized_mut(); // # Safety
let rand_idx = fast_bound( // gen.len() is positive.
rand_idx, let rand_idx = fast_bound(rand_idx, unsafe {
NonZero::new(gen.len()).ok_or_else(|| Error::empty("No Generalized Metadata found"))?, NonZero::new(gen.len()).unwrap_unchecked()
); });
'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 {

View File

@ -3,10 +3,7 @@
//! It uses a modified Particle Swarm Optimization algorithm to determine an optimal distribution of mutators. //! 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> //! 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 alloc::{borrow::Cow, string::ToString, vec::Vec};
use core::{ use core::fmt::{self, Debug};
fmt::{self, Debug},
num::{NonZero, NonZeroUsize},
};
use libafl_bolts::{ use libafl_bolts::{
rands::{Rand, StdRand}, rands::{Rand, StdRand},
@ -370,7 +367,7 @@ pub struct StdMOptMutator<MT> {
mode: MOptMode, mode: MOptMode,
finds_before: usize, finds_before: usize,
mutations: MT, mutations: MT,
max_stack_pow: NonZeroUsize, max_stack_pow: usize,
} }
impl<I, MT, S> Mutator<I, S> for StdMOptMutator<MT> 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(); let rand_seed = state.rand_mut().next();
state.add_metadata::<MOpt>(MOpt::new(MT::LEN, swarm_num, rand_seed)?); 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 { Ok(Self {
name: Cow::from(format!("StdMOptMutator[{}]", mutations.names().join(","))), name: Cow::from(format!("StdMOptMutator[{}]", mutations.names().join(","))),
mode: MOptMode::Pilotfuzzing, mode: MOptMode::Pilotfuzzing,
@ -618,7 +611,7 @@ where
{ {
/// Compute the number of iterations used to apply stacked mutations /// Compute the number of iterations used to apply stacked mutations
fn iterations(&self, state: &mut S, _: &I) -> u64 { 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 /// Get the next mutation to apply

View File

@ -156,10 +156,10 @@ where
.map(|(id, part)| (id, part.bytes().len())); .map(|(id, part)| (id, part.bytes().len()));
if let Some((part_idx, size)) = maybe_size { 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); return Ok(MutationResult::Skipped);
}; };
let target = state.rand_mut().below(nonzero_size); let target = state.rand_mut().below(nz);
// # Safety // # Safety
// size is nonzero here (checked above), target is smaller than size // size is nonzero here (checked above), target is smaller than size
// -> the subtraction result is greater than 0. // -> the subtraction result is greater than 0.
@ -212,11 +212,11 @@ where
.unwrap(); .unwrap();
drop(other_testcase); drop(other_testcase);
let size = part.bytes().len(); let size = part.bytes().len();
let Some(nonzero_size) = NonZero::new(size) else { let Some(nz) = NonZero::new(size) else {
return Ok(MutationResult::Skipped); return Ok(MutationResult::Skipped);
}; };
let target = state.rand_mut().below(nonzero_size); let target = state.rand_mut().below(nz);
// # Safety // # Safety
// other_size is larger than 0, checked above. // other_size is larger than 0, checked above.
// size is larger than 0. // size is larger than 0.
@ -285,11 +285,11 @@ where
.map(|(id, part)| (id, part.bytes().len())); .map(|(id, part)| (id, part.bytes().len()));
if let Some((part_idx, size)) = maybe_size { 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); return Ok(MutationResult::Skipped);
}; };
let target = state.rand_mut().below(nonzero_size); let target = state.rand_mut().below(nz);
// # Safety // # Safety
// other_size is checked above. // other_size is checked above.
// size is larger than than target and larger than 1. The subtraction result will always be positive. // size is larger than than target and larger than 1. The subtraction result will always be positive.
@ -335,11 +335,11 @@ where
.unwrap(); .unwrap();
drop(other_testcase); drop(other_testcase);
let size = part.bytes().len(); let size = part.bytes().len();
let Some(nonzero_size) = NonZero::new(size) else { let Some(nz) = NonZero::new(size) else {
return Ok(MutationResult::Skipped); return Ok(MutationResult::Skipped);
}; };
let target = state.rand_mut().below(nonzero_size); let target = state.rand_mut().below(nz);
// # Safety // # Safety
// other_size is checked above. // other_size is checked above.
// size is larger than than target and larger than 1. The subtraction result will always be positive. // 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, corpus::Corpus,
inputs::HasMutatorBytes, inputs::HasMutatorBytes,
mutators::{MutationResult, Mutator}, mutators::{MutationResult, Mutator},
random_corpus_id_with_disabled, nonzero, random_corpus_id_with_disabled,
state::{HasCorpus, HasMaxSize, HasRand}, state::{HasCorpus, HasMaxSize, HasRand},
Error, 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> { 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); let len = 1 + state.rand_mut().below(max_len);
// sample from [1..upper + len] // sample from [1..upper + len]
let Some(upper_len_minus1) = NonZero::new(upper + len - 1) else { let mut offset2 = 1 + state.rand_mut().zero_upto(upper + len - 1);
return 0..0;
};
let mut offset2 = 1 + state.rand_mut().below(upper_len_minus1);
let offset1 = offset2.saturating_sub(len); let offset1 = offset2.saturating_sub(len);
if offset2 > upper { if offset2 > upper {
offset2 = upper; offset2 = upper;
@ -314,7 +311,7 @@ where
Ok(MutationResult::Skipped) Ok(MutationResult::Skipped)
} else { } else {
let byte = state.rand_mut().choose(input.bytes_mut()).unwrap(); 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) Ok(MutationResult::Mutated)
} }
} }
@ -365,8 +362,8 @@ macro_rules! add_mutator_impl {
let val = <$size>::from_ne_bytes(bytes.try_into().unwrap()); let val = <$size>::from_ne_bytes(bytes.try_into().unwrap());
// mutate // mutate
let num = 1 + state.rand_mut().below(NonZero::new(ARITH_MAX).unwrap()) as $size; let num = 1 + state.rand_mut().below(nonzero!(ARITH_MAX)) as $size;
let new_val = match state.rand_mut().below(NonZero::new(4).unwrap()) { let new_val = match state.rand_mut().below(nonzero!(4)) {
0 => val.wrapping_add(num), 0 => val.wrapping_add(num),
1 => val.wrapping_sub(num), 1 => val.wrapping_sub(num),
2 => val.swap_bytes().wrapping_add(num).swap_bytes(), 2 => val.swap_bytes().wrapping_add(num).swap_bytes(),
@ -569,7 +566,7 @@ where
return Ok(MutationResult::Skipped); 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 // # Safety
// It's a safe assumption that size + 1 is never 0. // 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. // 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); 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 // # Safety
// size + 1 can never be 0 // size + 1 can never be 0
let offset = state let offset = state
@ -835,9 +832,9 @@ where
let max_insert_len = min(size - target, state.max_size() - size); let max_insert_len = min(size - target, state.max_size() - size);
let max_insert_len = min(16, max_insert_len); let max_insert_len = min(16, max_insert_len);
let Some(max_insert_len) = NonZero::new(max_insert_len) else { // # Safety
return Ok(MutationResult::Skipped); // 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); let range = rand_range(state, size, max_insert_len);
@ -989,13 +986,6 @@ where
} }
Ok(MutationResult::Mutated) Ok(MutationResult::Mutated)
} else if first.end != size { } 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 // # Safety
// first.end is not equal to size, so subtracting them can never be 0. // first.end is not equal to size, so subtracting them can never be 0.
let mut second = rand_range(state, size - first.end, unsafe { let mut second = rand_range(state, size - first.end, unsafe {

View File

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

View File

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

View File

@ -4,10 +4,7 @@
//! a specific mutator for a specified amount of iterations //! a specific mutator for a specified amount of iterations
use alloc::{borrow::Cow, vec::Vec}; use alloc::{borrow::Cow, vec::Vec};
use core::{ use core::{fmt::Debug, num::NonZero};
fmt::Debug,
num::{NonZero, NonZeroUsize},
};
use libafl_bolts::{ use libafl_bolts::{
impl_serdeany, math::calculate_cumulative_distribution_in_place, rands::Rand, impl_serdeany, math::calculate_cumulative_distribution_in_place, rands::Rand,
@ -86,7 +83,7 @@ impl TuneableScheduledMutatorMetadata {
pub struct TuneableScheduledMutator<MT> { pub struct TuneableScheduledMutator<MT> {
name: Cow<'static, str>, name: Cow<'static, str>,
mutations: MT, mutations: MT,
max_stack_pow: NonZeroUsize, max_stack_pow: usize,
} }
impl<I, MT, S> Mutator<I, S> for TuneableScheduledMutator<MT> impl<I, MT, S> Mutator<I, S> for TuneableScheduledMutator<MT>
@ -135,7 +132,7 @@ where
iters iters
} else { } else {
// fall back to random // 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 { } else {
// We will sample using the mutation probabilities. // We will sample using the mutation probabilities.
@ -218,7 +215,7 @@ impl<MT> TuneableScheduledMutator<MT> {
TuneableScheduledMutator { TuneableScheduledMutator {
name: Cow::from(format!("TuneableMutator[{}]", mutations.names().join(", "))), name: Cow::from(format!("TuneableMutator[{}]", mutations.names().join(", "))),
mutations, 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}, corpus::{Corpus, CorpusId, HasTestcase, Testcase},
inputs::{BytesInput, HasMutatorBytes}, inputs::{BytesInput, HasMutatorBytes},
mutators::{rand_range, MutationResult, Mutator, Tokens}, mutators::{rand_range, MutationResult, Mutator, Tokens},
nonzero,
stages::{ stages::{
extract_metadata, extract_metadata,
mutational::{MutatedTransform, MutatedTransformPost}, mutational::{MutatedTransform, MutatedTransformPost},
@ -233,11 +234,7 @@ fn rand_replace_range<S: HasRand + HasMaxSize, F: Fn(&mut S) -> char>(
range: Range<usize>, range: Range<usize>,
char_gen: F, char_gen: F,
) -> MutationResult { ) -> MutationResult {
let temp_range = rand_range( let temp_range = rand_range(state, range.end - range.start, nonzero!(MAX_CHARS));
state,
range.end - range.start,
NonZero::new(MAX_CHARS).unwrap(),
);
let range = (range.start + temp_range.start)..(range.start + temp_range.end); let range = (range.start + temp_range.start)..(range.start + temp_range.end);
let range = match core::str::from_utf8(&input.0.bytes()[range.clone()]) { let range = match core::str::from_utf8(&input.0.bytes()[range.clone()]) {
Ok(_) => range, Ok(_) => range,
@ -254,7 +251,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(NonZero::new(MAX_CHARS).unwrap()); let replace_len = state.rand_mut().below(nonzero!(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;

View File

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

View File

@ -5,10 +5,7 @@ use alloc::{
borrow::{Cow, ToOwned}, borrow::{Cow, ToOwned},
string::ToString, string::ToString,
}; };
use core::{ use core::{marker::PhantomData, num::NonZeroUsize};
marker::PhantomData,
num::{NonZero, NonZeroUsize},
};
use libafl_bolts::{rands::Rand, Named}; use libafl_bolts::{rands::Rand, Named};
@ -18,6 +15,7 @@ use crate::{
inputs::Input, inputs::Input,
mark_feature_time, mark_feature_time,
mutators::{MultiMutator, MutationResult, Mutator}, mutators::{MultiMutator, MutationResult, Mutator},
nonzero,
stages::{RetryCountRestartHelper, Stage}, stages::{RetryCountRestartHelper, Stage},
start_timer, start_timer,
state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasRand, UsesState}, state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasRand, UsesState},
@ -155,7 +153,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: usize = 128; pub const DEFAULT_MUTATIONAL_MAX_ITERATIONS: usize = 128;
/// The default mutational stage /// The default mutational stage
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -263,12 +261,12 @@ where
/// Creates a new default mutational stage /// Creates a new default mutational stage
pub fn new(mutator: M) -> Self { pub fn new(mutator: M) -> Self {
// Safe to unwrap: DEFAULT_MUTATIONAL_MAX_ITERATIONS is never 0. // 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 /// Creates a new mutational stage with the given max iterations
#[inline] #[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) Self::transforming_with_max_iterations(mutator, max_iterations)
} }
} }
@ -284,7 +282,7 @@ where
/// Creates a new transforming mutational stage with the default max iterations /// Creates a new transforming mutational stage with the default max iterations
pub fn transforming(mutator: M) -> Self { pub fn transforming(mutator: M) -> Self {
// Safe to unwrap: DEFAULT_MUTATIONAL_MAX_ITERATIONS is never 0. // 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 /// Creates a new transforming mutational stage with the given max iterations
@ -292,14 +290,7 @@ where
/// # Errors /// # Errors
/// Will return [`Error::IllegalArgument`] for `max_iterations` of 0. /// Will return [`Error::IllegalArgument`] for `max_iterations` of 0.
#[inline] #[inline]
pub fn transforming_with_max_iterations( pub fn transforming_with_max_iterations(mutator: M, max_iterations: NonZeroUsize) -> Self {
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.."));
};
let stage_id = unsafe { let stage_id = unsafe {
let ret = MUTATIONAL_STAGE_ID; let ret = MUTATIONAL_STAGE_ID;
MUTATIONAL_STAGE_ID += 1; MUTATIONAL_STAGE_ID += 1;
@ -307,12 +298,12 @@ where
}; };
let name = let name =
Cow::Owned(MUTATIONAL_STAGE_NAME.to_owned() + ":" + stage_id.to_string().as_str()); Cow::Owned(MUTATIONAL_STAGE_NAME.to_owned() + ":" + stage_id.to_string().as_str());
Ok(Self { Self {
name, name,
mutator, mutator,
max_iterations, max_iterations,
phantom: PhantomData, phantom: PhantomData,
}) }
} }
} }

View File

@ -5,7 +5,6 @@ use alloc::rc::Rc;
use core::{ use core::{
cell::{Cell, RefCell}, cell::{Cell, RefCell},
fmt::Debug, fmt::Debug,
num::NonZero,
}; };
use libafl_bolts::rands::Rand; use libafl_bolts::rands::Rand;
@ -19,6 +18,7 @@ use crate::{
inputs::UsesInput, inputs::UsesInput,
mark_feature_time, mark_feature_time,
mutators::Mutator, mutators::Mutator,
nonzero,
observers::ObserversTuple, observers::ObserversTuple,
schedulers::Scheduler, schedulers::Scheduler,
start_timer, start_timer,
@ -29,7 +29,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: usize = 128; pub const 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.
/// ///
@ -74,7 +74,7 @@ where
fn iterations(&self, state: &mut Z::State, _corpus_id: CorpusId) -> Result<usize, Error> { fn iterations(&self, state: &mut Z::State, _corpus_id: CorpusId) -> Result<usize, Error> {
Ok(1 + state Ok(1 + state
.rand_mut() .rand_mut()
.below(NonZero::new(DEFAULT_MUTATIONAL_MAX_ITERATIONS).unwrap())) .below(nonzero!(DEFAULT_MUTATIONAL_MAX_ITERATIONS)))
} }
/// Sets the current corpus index /// Sets the current corpus index

View File

@ -1,7 +1,7 @@
//! A [`crate::stages::MutationalStage`] where the mutator iteration can be tuned at runtime //! A [`crate::stages::MutationalStage`] where the mutator iteration can be tuned at runtime
use alloc::string::{String, ToString}; 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 libafl_bolts::{current_time, impl_serdeany, rands::Rand};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -10,6 +10,7 @@ use crate::{
corpus::Corpus, corpus::Corpus,
mark_feature_time, mark_feature_time,
mutators::{MutationResult, Mutator}, mutators::{MutationResult, Mutator},
nonzero,
stages::{ stages::{
mutational::{MutatedTransform, MutatedTransformPost, DEFAULT_MUTATIONAL_MAX_ITERATIONS}, mutational::{MutatedTransform, MutatedTransformPost, DEFAULT_MUTATIONAL_MAX_ITERATIONS},
ExecutionCountRestartHelper, MutationalStage, Stage, ExecutionCountRestartHelper, MutationalStage, Stage,
@ -250,7 +251,7 @@ where
// fall back to random // fall back to random
1 + state 1 + state
.rand_mut() .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")] #[cfg(feature = "python")]
#[allow(missing_docs)] #[allow(missing_docs)]
pub mod pybind { pub mod pybind {

View File

@ -96,6 +96,13 @@ pub fn fast_bound(rand: u64, n: NonZeroUsize) -> usize {
(mul >> 64) as 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. /// Ways to get random around here.
/// Please note that these are not cryptographically secure. /// 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. /// 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) fast_bound(self.next(), upper_bound_excl)
} }
/// Gets a value below the given bound (inclusive) /// Gets a value between [0, n]
#[inline] fn zero_upto(&mut self, n: usize) -> usize {
fn below_incl(&mut self, upper_bound_incl: usize) -> usize { fast_bound_usize(self.next(), n)
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 the given lower bound (inclusive) and upper bound (inclusive) /// Gets a value between the given lower bound (inclusive) and upper bound (inclusive)
@ -548,17 +550,18 @@ impl XkcdRand {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use core::num::NonZero; use crate::{
nonzero,
use crate::rands::{ rands::{
Rand, RomuDuoJrRand, RomuTrioRand, Sfc64Rand, StdRand, XorShift64Rand, Rand, RomuDuoJrRand, RomuTrioRand, Sfc64Rand, StdRand, XorShift64Rand,
Xoshiro256PlusPlusRand, Xoshiro256PlusPlusRand,
},
}; };
fn test_single_rand<R: Rand>(rand: &mut R) { fn test_single_rand<R: Rand>(rand: &mut R) {
assert_ne!(rand.next(), rand.next()); assert_ne!(rand.next(), rand.next());
assert!(rand.below(NonZero::new(100).unwrap()) < 100); assert!(rand.below(nonzero!(100)) < 100);
assert_eq!(rand.below(NonZero::new(1).unwrap()), 0); assert_eq!(rand.below(nonzero!(1)), 0);
assert_eq!(rand.between(10, 10), 10); assert_eq!(rand.between(10, 10), 10);
assert!(rand.between(11, 20) > 10); assert!(rand.between(11, 20) > 10);
} }

View File

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

View File

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

View File

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

View File

@ -27,6 +27,7 @@ use libafl::{
}; };
use libafl_bolts::{ use libafl_bolts::{
core_affinity::Cores, core_affinity::Cores,
nonzero,
ownedref::OwnedMutSlice, ownedref::OwnedMutSlice,
rands::StdRand, rands::StdRand,
shmem::{ShMemProvider, StdShMemProvider}, shmem::{ShMemProvider, StdShMemProvider},
@ -229,7 +230,7 @@ where
if state.must_load_initial_inputs() { if state.must_load_initial_inputs() {
if self.input_dirs.is_empty() { if self.input_dirs.is_empty() {
// Generator of printable bytearrays of max size 32 // 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 // Generate 8 initial inputs
state state

View File

@ -30,6 +30,7 @@ use libafl::{
}; };
use libafl_bolts::{ use libafl_bolts::{
core_affinity::Cores, core_affinity::Cores,
nonzero,
ownedref::OwnedMutSlice, ownedref::OwnedMutSlice,
rands::StdRand, rands::StdRand,
shmem::{ShMemProvider, StdShMemProvider}, shmem::{ShMemProvider, StdShMemProvider},
@ -259,7 +260,7 @@ where
if state.must_load_initial_inputs() { if state.must_load_initial_inputs() {
if self.input_dirs.is_empty() { if self.input_dirs.is_empty() {
// Generator of printable bytearrays of max size 32 // 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 // Generate 8 initial inputs
state state
@ -375,7 +376,7 @@ where
if state.must_load_initial_inputs() { if state.must_load_initial_inputs() {
if self.input_dirs.is_empty() { if self.input_dirs.is_empty() {
// Generator of printable bytearrays of max size 32 // 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 // Generate 8 initial inputs
state state