From cf23695773344803f067d4bb75e770c8078328a5 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Thu, 6 May 2021 15:01:39 +0200 Subject: [PATCH] Fix misaligned ptr accesses and other clippy issues (#94) * more docs * more docs: * more docu * more docu * finished docs * cleaned up markup * must_use tags added * more docs * swapped if/else, as per clippy * more docu, less clippy * more fixes * removed misaligned ptrs * fixed testcases * fixed arith mutators --- libafl/src/mutators/mutations.rs | 119 ++++++++++++++++--------------- 1 file changed, 63 insertions(+), 56 deletions(-) diff --git a/libafl/src/mutators/mutations.rs b/libafl/src/mutators/mutations.rs index 71ca670077..9710472682 100644 --- a/libafl/src/mutators/mutations.rs +++ b/libafl/src/mutators/mutations.rs @@ -13,7 +13,9 @@ use crate::{ use alloc::{borrow::ToOwned, vec::Vec}; use core::{ cmp::{max, min}, + convert::TryInto, marker::PhantomData, + mem::size_of, }; /// Mem move in the own vec @@ -53,6 +55,7 @@ fn buffer_set(data: &mut [u8], from: usize, len: usize, val: u8) { } } +/// The max value that will be added or subtracted during add mutations const ARITH_MAX: u64 = 35; const INTERESTING_8: [i8; 9] = [-128, -1, 0, 1, 16, 32, 64, 100, 127]; @@ -531,6 +534,7 @@ where } /// Word add mutation for inputs with a bytes vector +/// adds or subtracts a random value up to [`ARITH_MAX`] to a [`u16`] at a random place in the [`Vec`]. #[derive(Default)] pub struct WordAddMutator where @@ -553,21 +557,23 @@ where input: &mut I, _stage_idx: i32, ) -> Result { - if input.bytes().len() < 2 { + if input.bytes().len() < size_of::() { Ok(MutationResult::Skipped) } else { - let idx = state.rand_mut().below(input.bytes().len() as u64 - 1) as usize; - unsafe { - // Moar speed, no bounds checks - let ptr = input.bytes_mut().get_unchecked_mut(idx) as *mut _ as *mut u16; - let num = 1 + state.rand_mut().below(ARITH_MAX) as u16; - match state.rand_mut().below(4) { - 0 => *ptr = (*ptr).wrapping_add(num), - 1 => *ptr = (*ptr).wrapping_sub(num), - 2 => *ptr = ((*ptr).swap_bytes().wrapping_add(num)).swap_bytes(), - _ => *ptr = ((*ptr).swap_bytes().wrapping_sub(num)).swap_bytes(), - }; + let bytes = input.bytes_mut(); + let idx = state + .rand_mut() + .below((bytes.len() - size_of::() + 1) as u64) as usize; + let val = u16::from_ne_bytes(bytes[idx..idx + size_of::()].try_into().unwrap()); + let num = 1 + state.rand_mut().below(ARITH_MAX) as u16; + let new_bytes = match state.rand_mut().below(4) { + 0 => val.wrapping_add(num), + 1 => val.wrapping_sub(num), + 2 => val.swap_bytes().wrapping_add(num).swap_bytes(), + _ => val.swap_bytes().wrapping_sub(num).swap_bytes(), } + .to_ne_bytes(); + bytes[idx..idx + size_of::()].copy_from_slice(&new_bytes); Ok(MutationResult::Mutated) } } @@ -599,7 +605,8 @@ where } } -/// Dword add mutation for inputs with a bytes vector +/// Dword add mutation for inputs with a bytes vector. +/// Adds a random value up to `ARITH_MAX` to a [`u32`] at a random place in the [`Vec`], in random byte order. #[derive(Default)] pub struct DwordAddMutator where @@ -622,21 +629,23 @@ where input: &mut I, _stage_idx: i32, ) -> Result { - if input.bytes().len() < 4 { + if input.bytes().len() < size_of::() { Ok(MutationResult::Skipped) } else { - let idx = state.rand_mut().below(input.bytes().len() as u64 - 3) as usize; - unsafe { - // Moar speed, no bound check - let ptr = input.bytes_mut().get_unchecked_mut(idx) as *mut _ as *mut u32; - let num = 1 + state.rand_mut().below(ARITH_MAX) as u32; - match state.rand_mut().below(4) { - 0 => *ptr = (*ptr).wrapping_add(num), - 1 => *ptr = (*ptr).wrapping_sub(num), - 2 => *ptr = ((*ptr).swap_bytes().wrapping_add(num)).swap_bytes(), - _ => *ptr = ((*ptr).swap_bytes().wrapping_sub(num)).swap_bytes(), - }; + let bytes = input.bytes_mut(); + let idx = state + .rand_mut() + .below((bytes.len() - size_of::() + 1) as u64) as usize; + let val = u32::from_ne_bytes(bytes[idx..idx + size_of::()].try_into().unwrap()); + let num = 1 + state.rand_mut().below(ARITH_MAX) as u32; + let new_bytes = match state.rand_mut().below(4) { + 0 => val.wrapping_add(num), + 1 => val.wrapping_sub(num), + 2 => val.swap_bytes().wrapping_add(num).swap_bytes(), + _ => val.swap_bytes().wrapping_sub(num).swap_bytes(), } + .to_ne_bytes(); + bytes[idx..idx + size_of::()].copy_from_slice(&new_bytes); Ok(MutationResult::Mutated) } } @@ -694,18 +703,20 @@ where if input.bytes().len() < 8 { Ok(MutationResult::Skipped) } else { - let idx = state.rand_mut().below(input.bytes().len() as u64 - 7) as usize; - unsafe { - // Moar speed, no bounds checks - let ptr = input.bytes_mut().get_unchecked_mut(idx) as *mut _ as *mut u64; - let num = 1 + state.rand_mut().below(ARITH_MAX) as u64; - match state.rand_mut().below(4) { - 0 => *ptr = (*ptr).wrapping_add(num), - 1 => *ptr = (*ptr).wrapping_sub(num), - 2 => *ptr = ((*ptr).swap_bytes().wrapping_add(num)).swap_bytes(), - _ => *ptr = ((*ptr).swap_bytes().wrapping_sub(num)).swap_bytes(), - }; + let bytes = input.bytes_mut(); + let idx = state + .rand_mut() + .below((bytes.len() - size_of::() + 1) as u64) as usize; + let val = u64::from_ne_bytes(bytes[idx..idx + size_of::()].try_into().unwrap()); + let num = 1 + state.rand_mut().below(ARITH_MAX) as u64; + let new_bytes = match state.rand_mut().below(4) { + 0 => val.wrapping_add(num), + 1 => val.wrapping_sub(num), + 2 => val.swap_bytes().wrapping_add(num).swap_bytes(), + _ => val.swap_bytes().wrapping_sub(num).swap_bytes(), } + .to_ne_bytes(); + bytes[idx..idx + size_of::()].copy_from_slice(&new_bytes); Ok(MutationResult::Mutated) } } @@ -829,18 +840,16 @@ where if input.bytes().len() < 2 { Ok(MutationResult::Skipped) } else { - let idx = state.rand_mut().below(input.bytes().len() as u64 - 1) as usize; + let bytes = input.bytes_mut(); + let idx = state.rand_mut().below(bytes.len() as u64 - 1) as usize; let val = INTERESTING_16[state.rand_mut().below(INTERESTING_8.len() as u64) as usize] as u16; - unsafe { - // Moar speed, no bounds checks - let ptr = input.bytes_mut().get_unchecked_mut(idx) as *mut _ as *mut u16; - if state.rand_mut().below(2) == 0 { - *ptr = val; - } else { - *ptr = val.swap_bytes(); - } - } + let new_bytes = if state.rand_mut().below(2) == 0 { + val.to_be_bytes() + } else { + val.to_le_bytes() + }; + bytes[idx..idx + size_of::()].copy_from_slice(&new_bytes); Ok(MutationResult::Mutated) } } @@ -899,18 +908,16 @@ where if input.bytes().len() < 4 { Ok(MutationResult::Skipped) } else { - let idx = state.rand_mut().below(input.bytes().len() as u64 - 3) as usize; + let bytes = input.bytes_mut(); + let idx = state.rand_mut().below(bytes.len() as u64 - 3) as usize; let val = INTERESTING_32[state.rand_mut().below(INTERESTING_8.len() as u64) as usize] as u32; - unsafe { - // Moar speed, no bounds checks - let ptr = input.bytes_mut().get_unchecked_mut(idx) as *mut _ as *mut u32; - if state.rand_mut().below(2) == 0 { - *ptr = val; - } else { - *ptr = val.swap_bytes(); - } - } + let new_bytes = if state.rand_mut().below(2) == 0 { + val.to_be_bytes() + } else { + val.to_le_bytes() + }; + bytes[idx..idx + new_bytes.len()].copy_from_slice(&new_bytes); Ok(MutationResult::Mutated) } }