Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix unsoundness for misaligned map observers #1530

Merged
merged 4 commits into from
Sep 20, 2023
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 28 additions & 7 deletions libafl/src/observers/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ use core::{
hash::{BuildHasher, Hasher},
iter::Flatten,
marker::PhantomData,
slice::{from_raw_parts, Iter, IterMut},
mem::size_of,
slice::{self, Iter, IterMut},
};

use ahash::RandomState;
Expand Down Expand Up @@ -72,9 +73,9 @@ fn init_count_class_16() {
fn hash_slice<T>(slice: &[T]) -> u64 {
let mut hasher = RandomState::with_seeds(0, 0, 0, 0).build_hasher();
let ptr = slice.as_ptr() as *const u8;
let map_size = slice.len() / core::mem::size_of::<T>();
let map_size = slice.len() / size_of::<T>();
unsafe {
hasher.write(from_raw_parts(ptr, map_size));
hasher.write(slice::from_raw_parts(ptr, map_size));
}
hasher.finish()
}
Expand Down Expand Up @@ -1234,7 +1235,23 @@ where
exit_kind: &ExitKind,
) -> Result<(), Error> {
let map = self.as_mut_slice();
let len = map.len();
let mut len = map.len();
let align_offset = map.as_ptr().align_offset(size_of::<u16>());

// if len == 1, the next branch will already do this lookup
tokatoka marked this conversation as resolved.
Show resolved Hide resolved
if len > 1 && align_offset != 0 {
debug_assert_eq!(
align_offset, 1,
"Aligning u8 to u16 should always be offset of 1?"
);
unsafe {
*map.get_unchecked_mut(0) =
*COUNT_CLASS_LOOKUP.get_unchecked(*map.get_unchecked(0) as usize);
}
len -= 1;
}

// Fix the last element
if (len & 1) != 0 {
unsafe {
*map.get_unchecked_mut(len - 1) =
Expand All @@ -1243,13 +1260,17 @@ where
}

let cnt = len / 2;
let map16 = unsafe { core::slice::from_raw_parts_mut(map.as_mut_ptr() as *mut u16, cnt) };

let map16 = unsafe {
slice::from_raw_parts_mut(map.as_mut_ptr().add(align_offset) as *mut u16, cnt)
};
// 2022-07: Adding `enumerate` here increases execution speed/register allocation on x86_64.
for (_i, item) in map16[0..cnt].iter_mut().enumerate() {
unsafe {
*item = *COUNT_CLASS_LOOKUP_16.get_unchecked(*item as usize);
}
}

self.base.post_exec(state, input, exit_kind)
}
}
Expand Down Expand Up @@ -1776,9 +1797,9 @@ where
for map in &self.maps {
let slice = map.as_slice();
let ptr = slice.as_ptr() as *const u8;
let map_size = slice.len() / core::mem::size_of::<T>();
let map_size = slice.len() / size_of::<T>();
unsafe {
hasher.write(from_raw_parts(ptr, map_size));
hasher.write(slice::from_raw_parts(ptr, map_size));
}
}
hasher.finish()
Expand Down