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 libafl_bolts::{rands::Rand, AsSlice};
use libafl_bolts::{rands::Rand, AsSlice, HasLen};
use serde::{Deserialize, Serialize};
#[cfg(feature = "std")]
@ -561,9 +561,9 @@ where
'outer: for i in off..len {
let mut size = core::cmp::min(v.0.len(), len - i);
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 {
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;
break 'outer;
@ -572,9 +572,9 @@ where
}
size = core::cmp::min(v.1.len(), len - i);
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 {
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;
break 'outer;
@ -1568,10 +1568,10 @@ where
let mut rtn_found = false;
// Compare v0 against v1
rtn_found |= self.rtn_extend_encoding(
orig_v0,
orig_v1,
new_v0,
new_v1,
orig_v0.as_slice(),
orig_v1.as_slice(),
new_v0.as_slice(),
new_v1.as_slice(),
new_bytes,
orig_bytes,
cmp_buf_idx,
@ -1583,10 +1583,10 @@ where
// Compare v1 against v0
rtn_found |= self.rtn_extend_encoding(
orig_v1,
orig_v0,
new_v1,
new_v0,
orig_v1.as_slice(),
orig_v0.as_slice(),
new_v1.as_slice(),
new_v0.as_slice(),
new_bytes,
orig_bytes,
cmp_buf_idx,
@ -1601,10 +1601,10 @@ where
let mut v1_len = orig_v1.len();
if v0_len > 0
&& (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.
let v = strlen(orig_v0);
let v = strlen(orig_v0.as_slice());
if v > 0 {
v0_len = v;
}
@ -1612,10 +1612,10 @@ where
if v1_len > 0
&& (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.
let v = strlen(orig_v1);
let v = strlen(orig_v1.as_slice());
if v > 0 {
v1_len = v;
}
@ -1623,16 +1623,26 @@ where
if v0_len > 0
&& 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
&& 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 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 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);
}
/// 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
#[derive(Eq, PartialEq, Debug, Serialize, Deserialize, Clone)]
pub enum CmpValues {
@ -47,7 +80,7 @@ pub enum CmpValues {
/// Two u64 values
U64((u64, u64)),
/// Two vecs of u8 values/byte
Bytes((Vec<u8>, Vec<u8>)),
Bytes((CmplogBytes, CmplogBytes)),
}
impl CmpValues {

View File

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