Cmplog bytes without alloc (#2442)

* Cmplog bytes without alloc

* fixes

* clippy

* remove wrong %
This commit is contained in:
Dominik Maier 2024-07-30 13:42:48 +02:00 committed by GitHub
parent c4c0fb6750
commit 211809dddb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 77 additions and 28 deletions

View File

@ -17,7 +17,7 @@ use std::{
}; };
use hashbrown::HashSet; use hashbrown::HashSet;
use libafl_bolts::{rands::Rand, AsSlice}; use libafl_bolts::{rands::Rand, AsSlice, HasLen};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[cfg(feature = "std")] #[cfg(feature = "std")]
@ -561,9 +561,9 @@ where
'outer: for i in off..len { 'outer: for i in off..len {
let mut size = core::cmp::min(v.0.len(), len - i); let mut size = core::cmp::min(v.0.len(), len - i);
while size != 0 { while size != 0 {
if v.0[0..size] == input.bytes()[i..i + size] { if v.0.as_slice()[0..size] == input.bytes()[i..i + size] {
unsafe { unsafe {
buffer_copy(input.bytes_mut(), &v.1, 0, i, size); buffer_copy(input.bytes_mut(), v.1.as_slice(), 0, i, size);
} }
result = MutationResult::Mutated; result = MutationResult::Mutated;
break 'outer; break 'outer;
@ -572,9 +572,9 @@ where
} }
size = core::cmp::min(v.1.len(), len - i); size = core::cmp::min(v.1.len(), len - i);
while size != 0 { while size != 0 {
if v.1[0..size] == input.bytes()[i..i + size] { if v.1.as_slice()[0..size] == input.bytes()[i..i + size] {
unsafe { unsafe {
buffer_copy(input.bytes_mut(), &v.0, 0, i, size); buffer_copy(input.bytes_mut(), v.0.as_slice(), 0, i, size);
} }
result = MutationResult::Mutated; result = MutationResult::Mutated;
break 'outer; break 'outer;
@ -1568,10 +1568,10 @@ where
let mut rtn_found = false; let mut rtn_found = false;
// Compare v0 against v1 // Compare v0 against v1
rtn_found |= self.rtn_extend_encoding( rtn_found |= self.rtn_extend_encoding(
orig_v0, orig_v0.as_slice(),
orig_v1, orig_v1.as_slice(),
new_v0, new_v0.as_slice(),
new_v1, new_v1.as_slice(),
new_bytes, new_bytes,
orig_bytes, orig_bytes,
cmp_buf_idx, cmp_buf_idx,
@ -1583,10 +1583,10 @@ where
// Compare v1 against v0 // Compare v1 against v0
rtn_found |= self.rtn_extend_encoding( rtn_found |= self.rtn_extend_encoding(
orig_v1, orig_v1.as_slice(),
orig_v0, orig_v0.as_slice(),
new_v1, new_v1.as_slice(),
new_v0, new_v0.as_slice(),
new_bytes, new_bytes,
orig_bytes, orig_bytes,
cmp_buf_idx, cmp_buf_idx,
@ -1601,10 +1601,10 @@ where
let mut v1_len = orig_v1.len(); let mut v1_len = orig_v1.len();
if v0_len > 0 if v0_len > 0
&& (is_ascii_or_utf8 && (is_ascii_or_utf8
|| check_if_text(orig_v0, v0_len).size() == hshape) || check_if_text(orig_v0.as_slice(), v0_len).size() == hshape)
{ {
// this is not utf8. // this is not utf8.
let v = strlen(orig_v0); let v = strlen(orig_v0.as_slice());
if v > 0 { if v > 0 {
v0_len = v; v0_len = v;
} }
@ -1612,10 +1612,10 @@ where
if v1_len > 0 if v1_len > 0
&& (is_ascii_or_utf8 && (is_ascii_or_utf8
|| check_if_text(orig_v1, v1_len).size() == hshape) || check_if_text(orig_v1.as_slice(), v1_len).size() == hshape)
{ {
// this is not utf8. // this is not utf8.
let v = strlen(orig_v1); let v = strlen(orig_v1.as_slice());
if v > 0 { if v > 0 {
v1_len = v; v1_len = v;
} }
@ -1623,16 +1623,26 @@ where
if v0_len > 0 if v0_len > 0
&& orig_v0 == new_v0 && orig_v0 == new_v0
&& (!rtn_found || check_if_text(orig_v0, v0_len).size() == v0_len) && (!rtn_found
|| check_if_text(orig_v0.as_slice(), v0_len).size() == v0_len)
{ {
Self::try_add_autotokens(&mut gathered_tokens, orig_v0, v0_len); Self::try_add_autotokens(
&mut gathered_tokens,
orig_v0.as_slice(),
v0_len,
);
} }
if v1_len > 0 if v1_len > 0
&& orig_v1 == new_v1 && orig_v1 == new_v1
&& (!rtn_found || check_if_text(orig_v1, v1_len).size() == v1_len) && (!rtn_found
|| check_if_text(orig_v1.as_slice(), v1_len).size() == v1_len)
{ {
Self::try_add_autotokens(&mut gathered_tokens, orig_v1, v1_len); Self::try_add_autotokens(
&mut gathered_tokens,
orig_v1.as_slice(),
v1_len,
);
} }
} }
(_, _) => { (_, _) => {

View File

@ -9,7 +9,7 @@ use core::{
use c2rust_bitfields::BitfieldStruct; use c2rust_bitfields::BitfieldStruct;
use hashbrown::HashMap; use hashbrown::HashMap;
use libafl_bolts::{ownedref::OwnedRefMut, serdeany::SerdeAny, Named}; use libafl_bolts::{ownedref::OwnedRefMut, serdeany::SerdeAny, AsSlice, HasLen, Named};
use serde::{de::DeserializeOwned, Deserialize, Serialize}; use serde::{de::DeserializeOwned, Deserialize, Serialize};
use crate::{executors::ExitKind, inputs::UsesInput, observers::Observer, Error, HasMetadata}; use crate::{executors::ExitKind, inputs::UsesInput, observers::Observer, Error, HasMetadata};
@ -35,6 +35,39 @@ where
fn add_from(&mut self, usable_count: usize, cmp_map: &mut CM, cmp_observer_data: Self::Data); fn add_from(&mut self, usable_count: usize, cmp_map: &mut CM, cmp_observer_data: Self::Data);
} }
/// A bytes string for cmplog with up to 32 elements.
#[derive(Debug, Copy, Clone, Serialize, Deserialize, Eq, PartialEq)]
pub struct CmplogBytes {
buf: [u8; 32],
len: u8,
}
impl CmplogBytes {
/// Creates a new [`CmplogBytes`] object from the provided buf and length.
/// Lengths above 32 are illegal but will be ignored.
#[must_use]
pub fn from_buf_and_len(buf: [u8; 32], len: u8) -> Self {
debug_assert!(len <= 32, "Len too big: {len}, max: 32");
CmplogBytes { buf, len }
}
}
impl<'a> AsSlice<'a> for CmplogBytes {
type Entry = u8;
type SliceRef = &'a [u8];
fn as_slice(&'a self) -> Self::SliceRef {
&self.buf[0..(self.len as usize)]
}
}
impl HasLen for CmplogBytes {
fn len(&self) -> usize {
self.len as usize
}
}
/// Compare values collected during a run /// Compare values collected during a run
#[derive(Eq, PartialEq, Debug, Serialize, Deserialize, Clone)] #[derive(Eq, PartialEq, Debug, Serialize, Deserialize, Clone)]
pub enum CmpValues { pub enum CmpValues {
@ -47,7 +80,7 @@ pub enum CmpValues {
/// Two u64 values /// Two u64 values
U64((u64, u64)), U64((u64, u64)),
/// Two vecs of u8 values/byte /// Two vecs of u8 values/byte
Bytes((Vec<u8>, Vec<u8>)), Bytes((CmplogBytes, CmplogBytes)),
} }
impl CmpValues { impl CmpValues {

View File

@ -13,7 +13,7 @@ use core::{
}; };
use libafl::{ use libafl::{
observers::{cmp::AFLppCmpLogHeader, CmpMap, CmpValues}, observers::{cmp::AFLppCmpLogHeader, CmpMap, CmpValues, CmplogBytes},
Error, Error,
}; };
use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde::{Deserialize, Deserializer, Serialize, Serializer};
@ -390,8 +390,14 @@ impl CmpMap for CmpLogMap {
} else { } else {
unsafe { unsafe {
Some(CmpValues::Bytes(( Some(CmpValues::Bytes((
self.vals.routines[idx][execution].0.to_vec(), CmplogBytes::from_buf_and_len(
self.vals.routines[idx][execution].1.to_vec(), self.vals.routines[idx][execution].0,
CMPLOG_RTN_LEN as u8,
),
CmplogBytes::from_buf_and_len(
self.vals.routines[idx][execution].1,
CMPLOG_RTN_LEN as u8,
),
))) )))
} }
} }
@ -567,8 +573,8 @@ impl CmpMap for AFLppCmpLogMap {
let v0_len = self.vals.fn_operands[idx][execution].v0_len & (0x80 - 1); let v0_len = self.vals.fn_operands[idx][execution].v0_len & (0x80 - 1);
let v1_len = self.vals.fn_operands[idx][execution].v1_len & (0x80 - 1); let v1_len = self.vals.fn_operands[idx][execution].v1_len & (0x80 - 1);
Some(CmpValues::Bytes(( Some(CmpValues::Bytes((
self.vals.fn_operands[idx][execution].v0[..(v0_len as usize)].to_vec(), CmplogBytes::from_buf_and_len(self.vals.fn_operands[idx][execution].v0, v0_len),
self.vals.fn_operands[idx][execution].v1[..(v1_len as usize)].to_vec(), CmplogBytes::from_buf_and_len(self.vals.fn_operands[idx][execution].v1, v1_len),
))) )))
} }
} }