Merge branch 'main' into cmplog_instrumentation

This commit is contained in:
Omree 2021-06-09 10:37:43 +03:00
commit 5de4c9305e
30 changed files with 353 additions and 261 deletions

View File

@ -31,7 +31,6 @@ libc = "0.2"
libloading = "0.7.0" libloading = "0.7.0"
num-traits = "0.2.14" num-traits = "0.2.14"
rangemap = "0.1.10" rangemap = "0.1.10"
seahash = "4.1.0"
clap = "2.33" clap = "2.33"
serde = "1.0" serde = "1.0"

View File

@ -275,7 +275,7 @@ fn fuzz(
/// The actual fuzzer /// The actual fuzzer
#[cfg(unix)] #[cfg(unix)]
#[allow(clippy::too_many_lines, clippy::clippy::too_many_arguments)] #[allow(clippy::too_many_lines, clippy::too_many_arguments)]
unsafe fn fuzz( unsafe fn fuzz(
module_name: &str, module_name: &str,
symbol_name: &str, symbol_name: &str,

View File

@ -16,7 +16,7 @@ rustc_version = "0.3.3"
[dev-dependencies] [dev-dependencies]
criterion = "0.3" # Benchmarking criterion = "0.3" # Benchmarking
ahash = "0.6.1" # another hash ahash = "0.7" # another hash
fxhash = "0.2.1" # yet another hash fxhash = "0.2.1" # yet another hash
xxhash-rust = { version = "0.8.2", features = ["xxh3"] } # xxh3 hashing for rust xxhash-rust = { version = "0.8.2", features = ["xxh3"] } # xxh3 hashing for rust
serde_json = "1.0.60" serde_json = "1.0.60"
@ -68,6 +68,7 @@ core_affinity = { version = "0.5", git = "https://github.com/s1341/core_affinity
num_enum = "0.5.1" num_enum = "0.5.1"
hostname = "^0.3" # Is there really no gethostname in the stdlib? hostname = "^0.3" # Is there really no gethostname in the stdlib?
typed-builder = "0.9.0" typed-builder = "0.9.0"
ahash ="0.7"
[target.'cfg(target_os = "android")'.dependencies] [target.'cfg(target_os = "android")'.dependencies]
backtrace = { version = "0.3", optional = true, default-features = false, features = ["std", "libbacktrace"] } # for llmp_debug backtrace = { version = "0.3", optional = true, default-features = false, features = ["std", "libbacktrace"] } # for llmp_debug

View File

@ -31,7 +31,7 @@ fn adder_loop(port: u16) -> ! {
loop { loop {
let mut msg_counter = 0; let mut msg_counter = 0;
loop { loop {
let (_sender, tag, buf) = match client.recv_buf().unwrap() { let (sender, tag, buf) = match client.recv_buf().unwrap() {
None => break, None => break,
Some(msg) => msg, Some(msg) => msg,
}; };
@ -42,8 +42,9 @@ fn adder_loop(port: u16) -> ! {
current_result.wrapping_add(u32::from_le_bytes(buf.try_into().unwrap())); current_result.wrapping_add(u32::from_le_bytes(buf.try_into().unwrap()));
} }
_ => println!( _ => println!(
"Adder Client ignored unknown message {} with {} bytes", "Adder Client ignored unknown message {:#x} from client {} with {} bytes",
tag, tag,
sender,
buf.len() buf.len()
), ),
}; };

View File

@ -32,7 +32,7 @@ impl GzipCompressor {
//compress if the buffer is large enough //compress if the buffer is large enough
let compressed = buf let compressed = buf
.iter() .iter()
.cloned() .copied()
.encode(&mut GZipEncoder::new(), Action::Finish) .encode(&mut GZipEncoder::new(), Action::Finish)
.collect::<Result<Vec<_>, _>>()?; .collect::<Result<Vec<_>, _>>()?;
Ok(Some(compressed)) Ok(Some(compressed))
@ -47,7 +47,7 @@ impl GzipCompressor {
pub fn decompress(&self, buf: &[u8]) -> Result<Vec<u8>, Error> { pub fn decompress(&self, buf: &[u8]) -> Result<Vec<u8>, Error> {
Ok(buf Ok(buf
.iter() .iter()
.cloned() .copied()
.decode(&mut GZipDecoder::new()) .decode(&mut GZipDecoder::new())
.collect::<Result<Vec<_>, _>>()?) .collect::<Result<Vec<_>, _>>()?)
} }

View File

@ -36,6 +36,7 @@ use typed_builder::TypedBuilder;
pub type LauncherClientFnRef<'a, I, OT, S, SP> = pub type LauncherClientFnRef<'a, I, OT, S, SP> =
&'a mut dyn FnMut(Option<S>, LlmpRestartingEventManager<I, OT, S, SP>) -> Result<(), Error>; &'a mut dyn FnMut(Option<S>, LlmpRestartingEventManager<I, OT, S, SP>) -> Result<(), Error>;
const _AFL_LAUNCHER_CLIENT: &str = "AFL_LAUNCHER_CLIENT";
/// Provides a Launcher, which can be used to launch a fuzzing run on a specified list of cores /// Provides a Launcher, which can be used to launch a fuzzing run on a specified list of cores
#[cfg(feature = "std")] #[cfg(feature = "std")]
#[derive(TypedBuilder)] #[derive(TypedBuilder)]
@ -54,7 +55,7 @@ where
stats: ST, stats: ST,
/// The 'main' function to run for each client forked. This probably shouldn't return /// The 'main' function to run for each client forked. This probably shouldn't return
run_client: LauncherClientFnRef<'a, I, OT, S, SP>, run_client: LauncherClientFnRef<'a, I, OT, S, SP>,
/// The broker port to use /// The broker port to use (or to attach to, in case [`Self::with_broker`] is `false`)
#[builder(default = 1337_u16)] #[builder(default = 1337_u16)]
broker_port: u16, broker_port: u16,
/// The list of cores to run on /// The list of cores to run on
@ -66,6 +67,12 @@ where
/// clusters. /// clusters.
#[builder(default = None)] #[builder(default = None)]
remote_broker_addr: Option<SocketAddr>, remote_broker_addr: Option<SocketAddr>,
/// If this launcher should spawn a new `broker` on `[Self::broker_port]` (default).
/// The reason you may not want this is, if you already have a [`Launcher`]
/// with a different configuration (for the same target) running on this machine.
/// Then, clients launched by this [`Launcher`] can connect to the original `broker`.
#[builder(default = true)]
spawn_broker: bool,
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
@ -128,23 +135,37 @@ where
}; };
} }
} }
#[cfg(feature = "std")]
println!("I am broker!!.");
// TODO we don't want always a broker here, thing about using different laucher process to spawn different configurations if self.spawn_broker {
RestartingMgr::<I, OT, S, SP, ST>::builder() #[cfg(feature = "std")]
.shmem_provider(self.shmem_provider.clone()) println!("I am broker!!.");
.stats(Some(self.stats.clone()))
.broker_port(self.broker_port)
.kind(ManagerKind::Broker)
.remote_broker_addr(self.remote_broker_addr)
.build()
.launch()?;
// Broker exited. kill all clients. // TODO we don't want always a broker here, thing about using different laucher process to spawn different configurations
for handle in &handles { RestartingMgr::<I, OT, S, SP, ST>::builder()
unsafe { .shmem_provider(self.shmem_provider.clone())
libc::kill(*handle, libc::SIGINT); .stats(Some(self.stats.clone()))
.broker_port(self.broker_port)
.kind(ManagerKind::Broker)
.remote_broker_addr(self.remote_broker_addr)
.build()
.launch()?;
// Broker exited. kill all clients.
for handle in &handles {
unsafe {
libc::kill(*handle, libc::SIGINT);
}
}
} else {
for handle in &handles {
let mut status = 0;
println!("Not spawning broker (spawn_broker is false). Waiting for fuzzer children to exit...");
unsafe {
libc::waitpid(*handle, &mut status, 0);
if status != 0 {
println!("Client with pid {} exited with status {}", handle, status);
}
}
} }
} }
@ -215,25 +236,33 @@ where
Err(_) => panic!("Env variables are broken, received non-unicode!"), Err(_) => panic!("Env variables are broken, received non-unicode!"),
}; };
#[cfg(feature = "std")] if self.spawn_broker {
println!("I am broker!!."); #[cfg(feature = "std")]
println!("I am broker!!.");
RestartingMgr::<I, OT, S, SP, ST>::builder() RestartingMgr::<I, OT, S, SP, ST>::builder()
.shmem_provider(self.shmem_provider.clone()) .shmem_provider(self.shmem_provider.clone())
.stats(Some(self.stats.clone())) .stats(Some(self.stats.clone()))
.broker_port(self.broker_port) .broker_port(self.broker_port)
.kind(ManagerKind::Broker) .kind(ManagerKind::Broker)
.remote_broker_addr(self.remote_broker_addr) .remote_broker_addr(self.remote_broker_addr)
.build() .build()
.launch()?; .launch()?;
//broker exited. kill all clients. //broker exited. kill all clients.
for handle in &mut handles { for handle in &mut handles {
handle.kill()?; handle.kill()?;
}
} else {
println!("Not spawning broker (spawn_broker is false). Waiting for fuzzer children to exit...");
for handle in &mut handles {
let ecode = handle.wait()?;
if !ecode.success() {
println!("Client with handle {:?} exited with {:?}", handle, ecode);
}
}
} }
Ok(()) Ok(())
} }
} }
const _AFL_LAUNCHER_CLIENT: &str = &"AFL_LAUNCHER_CLIENT";

View File

@ -62,7 +62,7 @@ For broker2broker communication, all messages are forwarded via network sockets.
use alloc::{string::String, vec::Vec}; use alloc::{string::String, vec::Vec};
use core::{ use core::{
cmp::max, cmp::max,
convert::TryFrom, convert::{TryFrom, TryInto},
fmt::Debug, fmt::Debug,
mem::size_of, mem::size_of,
ptr, slice, ptr, slice,
@ -73,7 +73,6 @@ use serde::{Deserialize, Serialize};
#[cfg(feature = "std")] #[cfg(feature = "std")]
use std::{ use std::{
convert::TryInto,
env, env,
io::{ErrorKind, Read, Write}, io::{ErrorKind, Read, Write},
net::{SocketAddr, TcpListener, TcpStream, ToSocketAddrs}, net::{SocketAddr, TcpListener, TcpStream, ToSocketAddrs},
@ -281,12 +280,14 @@ impl Listener {
/// Get sharedmem from a page /// Get sharedmem from a page
#[inline] #[inline]
#[allow(clippy::cast_ptr_alignment)]
unsafe fn shmem2page_mut<SHM: ShMem>(afl_shmem: &mut SHM) -> *mut LlmpPage { unsafe fn shmem2page_mut<SHM: ShMem>(afl_shmem: &mut SHM) -> *mut LlmpPage {
afl_shmem.map_mut().as_mut_ptr() as *mut LlmpPage afl_shmem.map_mut().as_mut_ptr() as *mut LlmpPage
} }
/// Get sharedmem from a page /// Get sharedmem from a page
#[inline] #[inline]
#[allow(clippy::cast_ptr_alignment)]
unsafe fn shmem2page<SHM: ShMem>(afl_shmem: &SHM) -> *const LlmpPage { unsafe fn shmem2page<SHM: ShMem>(afl_shmem: &SHM) -> *const LlmpPage {
afl_shmem.map().as_ptr() as *const LlmpPage afl_shmem.map().as_ptr() as *const LlmpPage
} }
@ -460,7 +461,9 @@ unsafe fn llmp_next_msg_ptr_checked<SHM: ShMem>(
} }
/// Pointer to the message behind the last message /// Pointer to the message behind the last message
/// The messages are padded, so accesses will be aligned properly.
#[inline] #[inline]
#[allow(clippy::cast_ptr_alignment)]
unsafe fn _llmp_next_msg_ptr(last_msg: *const LlmpMsg) -> *mut LlmpMsg { unsafe fn _llmp_next_msg_ptr(last_msg: *const LlmpMsg) -> *mut LlmpMsg {
/* DBG("_llmp_next_msg_ptr %p %lu + %lu\n", last_msg, last_msg->buf_len_padded, sizeof(llmp_message)); */ /* DBG("_llmp_next_msg_ptr %p %lu + %lu\n", last_msg, last_msg->buf_len_padded, sizeof(llmp_message)); */
(last_msg as *mut u8) (last_msg as *mut u8)
@ -489,7 +492,7 @@ pub enum LlmpMsgHookResult {
/// Message sent over the "wire" /// Message sent over the "wire"
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
#[repr(C, packed)] #[repr(C)]
pub struct LlmpMsg { pub struct LlmpMsg {
/// A tag /// A tag
pub tag: Tag, //u32 pub tag: Tag, //u32
@ -621,7 +624,7 @@ where
pub fn describe(&self) -> Result<LlmpClientDescription, Error> { pub fn describe(&self) -> Result<LlmpClientDescription, Error> {
Ok(match self { Ok(match self {
LlmpConnection::IsClient { client } => client.describe()?, LlmpConnection::IsClient { client } => client.describe()?,
_ => todo!("Only client can be described atm."), LlmpConnection::IsBroker { .. } => todo!("Only client can be described atm."),
}) })
} }
@ -654,7 +657,7 @@ where
/// Contents of the share mem pages, used by llmp internally /// Contents of the share mem pages, used by llmp internally
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
#[repr(C, packed)] #[repr(C)]
pub struct LlmpPage { pub struct LlmpPage {
/// to check if this page got initialized properly /// to check if this page got initialized properly
pub magic: u64, pub magic: u64,
@ -683,7 +686,7 @@ pub struct LlmpPage {
/// This is an internal message! /// This is an internal message!
/// [`LLMP_TAG_END_OF_PAGE_V1`] /// [`LLMP_TAG_END_OF_PAGE_V1`]
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
#[repr(C, packed)] #[repr(C)]
struct LlmpPayloadSharedMapInfo { struct LlmpPayloadSharedMapInfo {
/// The map size /// The map size
pub map_size: usize, pub map_size: usize,
@ -697,7 +700,7 @@ pub struct LlmpSender<SP>
where where
SP: ShMemProvider, SP: ShMemProvider,
{ {
/// ID of this sender. Only used in the broker. /// ID of this sender.
pub id: u32, pub id: u32,
/// Ref to the last message this sender sent on the last page. /// Ref to the last message this sender sent on the last page.
/// If null, a new page (just) started. /// If null, a new page (just) started.
@ -709,6 +712,9 @@ where
/// By keeping the message history around, /// By keeping the message history around,
/// new clients may join at any time in the future. /// new clients may join at any time in the future.
pub keep_pages_forever: bool, pub keep_pages_forever: bool,
/// True, if we allocatd a message, but didn't call [`Self::send()`] yet
has_unsent_message: bool,
/// The sharedmem provider to get new sharaed maps if we're full
shmem_provider: SP, shmem_provider: SP,
} }
@ -730,6 +736,7 @@ where
)], )],
// drop pages to the broker if it already read them // drop pages to the broker if it already read them
keep_pages_forever, keep_pages_forever,
has_unsent_message: false,
shmem_provider, shmem_provider,
}) })
} }
@ -804,6 +811,7 @@ where
out_maps: vec![out_map], out_maps: vec![out_map],
// drop pages to the broker if it already read them // drop pages to the broker if it already read them
keep_pages_forever: false, keep_pages_forever: false,
has_unsent_message: false,
shmem_provider, shmem_provider,
}) })
} }
@ -864,111 +872,85 @@ where
/// Never call [`alloc_next`] without either sending or cancelling the last allocated message for this page! /// Never call [`alloc_next`] without either sending or cancelling the last allocated message for this page!
/// There can only ever be up to one message allocated per page at each given time. /// There can only ever be up to one message allocated per page at each given time.
unsafe fn alloc_next_if_space(&mut self, buf_len: usize) -> Option<*mut LlmpMsg> { unsafe fn alloc_next_if_space(&mut self, buf_len: usize) -> Option<*mut LlmpMsg> {
let buf_len_padded;
let mut complete_msg_size = llmp_align(size_of::<LlmpMsg>() + buf_len);
let map = self.out_maps.last_mut().unwrap(); let map = self.out_maps.last_mut().unwrap();
let page = map.page_mut(); let page = map.page_mut();
let last_msg = self.last_msg_sent; let last_msg = self.last_msg_sent;
if self.has_unsent_message {
panic!("Called alloc without callind send inbetween");
}
#[cfg(all(feature = "llmp_debug", feature = "std"))] #[cfg(all(feature = "llmp_debug", feature = "std"))]
println!( println!(
"Allocating {} (>={}) bytes on page {:?} / map {:?} (last msg: {:?})", "Allocating {} bytes on page {:?} / map {:?} (last msg: {:?})",
complete_msg_size, buf_len, page, &map, last_msg buf_len, page, &map, last_msg
); );
/* DBG("XXX complete_msg_size %lu (h: %lu)\n", complete_msg_size, sizeof(llmp_message)); */
/* In case we don't have enough space, make sure the next page will be large
* enough */
// For future allocs, keep track of the maximum (aligned) alloc size we used
(*page).max_alloc_size = max((*page).max_alloc_size, complete_msg_size);
let mut ret: *mut LlmpMsg; let msg_start = (*page).messages.as_mut_ptr() as usize + (*page).size_used;
/* DBG("last_msg %p %d (%d)\n", last_msg, last_msg ? (int)last_msg->tag : -1, (int)LLMP_TAG_END_OF_PAGE_V1); */
if last_msg.is_null() || (*last_msg).tag == LLMP_TAG_END_OF_PAGE {
/* We start fresh, on a new page */
ret = (*page).messages.as_mut_ptr();
/* The initial message may not be alligned, so we at least align the end of
it. Technically, c_ulong can be smaller than a pointer, then who knows what
happens */
let base_addr = ret as usize;
buf_len_padded =
llmp_align(base_addr + complete_msg_size) - base_addr - size_of::<LlmpMsg>();
complete_msg_size = buf_len_padded + size_of::<LlmpMsg>();
/* Still space for the new message plus the additional "we're full" message?
*/
// Make sure the end of our msg is aligned.
let buf_len_padded = llmp_align(msg_start + buf_len + size_of::<LlmpMsg>())
- msg_start
- size_of::<LlmpMsg>();
#[cfg(all(feature = "llmp_debug", feature = "std"))]
dbg!(
page,
*page,
(*page).size_used,
buf_len_padded,
EOP_MSG_SIZE,
(*page).size_total
);
// We need enough space for the current page size_used + payload + padding
if (*page).size_used + size_of::<LlmpMsg>() + buf_len_padded + EOP_MSG_SIZE
> (*page).size_total
{
#[cfg(all(feature = "llmp_debug", feature = "std"))] #[cfg(all(feature = "llmp_debug", feature = "std"))]
dbg!( println!("LLMP: Page full.");
page,
*page,
(*page).size_used,
complete_msg_size,
EOP_MSG_SIZE,
(*page).size_total
);
if (*page).size_used + complete_msg_size + EOP_MSG_SIZE > (*page).size_total {
/* We're full. */
return None;
}
/* We need to start with 1 for ids, as current message id is initialized
* with 0... */
(*ret).message_id = if last_msg.is_null() {
1
} else {
(*last_msg).message_id + 1
}
} else if (*page).current_msg_id == (*last_msg).message_id {
buf_len_padded = complete_msg_size - size_of::<LlmpMsg>();
/* DBG("XXX ret %p id %u buf_len_padded %lu complete_msg_size %lu\n", ret, ret->message_id, buf_len_padded,
* complete_msg_size); */
/* Still space for the new message plus the additional "we're full" message? */ /* We're full. */
if (*page).size_used + complete_msg_size + EOP_MSG_SIZE > (*page).size_total { return None;
/* We're full. */ }
return None;
} let ret = msg_start as *mut LlmpMsg;
ret = match llmp_next_msg_ptr_checked(map, last_msg, complete_msg_size) {
Ok(msg) => msg, /* We need to start with 1 for ids, as current message id is initialized
Err(e) => { * with 0... */
#[cfg(feature = "std")] (*ret).message_id = if last_msg.is_null() {
dbg!("Unexpected error allocing new msg", e); 1
#[cfg(feature = "std")] } else if (*page).current_msg_id == (*last_msg).message_id {
return None; (*last_msg).message_id + 1
#[cfg(not(feature = "std"))]
panic!("Unexpected error allocing new msg {:?}", e);
}
};
(*ret).message_id = (*last_msg).message_id + 1
} else { } else {
/* Oops, wrong usage! */ /* Oops, wrong usage! */
panic!("BUG: The current message never got committed using send! (page->current_msg_id {:?}, last_msg->message_id: {})", ptr::addr_of!((*page).current_msg_id), (*last_msg).message_id); panic!("BUG: The current message never got committed using send! (page->current_msg_id {:?}, last_msg->message_id: {})", ptr::addr_of!((*page).current_msg_id), (*last_msg).message_id);
} };
/* The beginning of our message should be messages + size_used, else nobody
* sent the last msg! */
/* DBG("XXX ret %p - page->messages %p = %lu != %lu, will add %lu -> %p\n", ret, page->messages,
(c_ulong)((u8 *)ret - (u8 *)page->messages), page->size_used, complete_msg_size, ((u8 *)ret) + complete_msg_size);
*/
if last_msg.is_null() && (*page).size_used != 0
|| ((ret as usize) - (*page).messages.as_mut_ptr() as usize) != (*page).size_used
{
panic!("Allocated new message without calling send() inbetween. ret: {:?}, page: {:?}, complete_msg_size: {:?}, size_used: {:?}, last_msg: {:?}", ret, page,
buf_len_padded, ptr::addr_of!((*page).size_used), last_msg);
}
(*page).size_used += complete_msg_size;
(*ret).buf_len_padded = buf_len_padded as u64;
(*ret).buf_len = buf_len as u64; (*ret).buf_len = buf_len as u64;
/* DBG("Returning new message at %p with len %ld, TAG was %x", ret, ret->buf_len_padded, ret->tag); */ (*ret).buf_len_padded = buf_len_padded as u64;
/* Maybe catch some bugs... */ (*page).size_used += size_of::<LlmpMsg>() + buf_len_padded;
(*_llmp_next_msg_ptr(ret)).tag = LLMP_TAG_UNSET; (*_llmp_next_msg_ptr(ret)).tag = LLMP_TAG_UNSET;
(*ret).tag = LLMP_TAG_UNINITIALIZED; (*ret).tag = LLMP_TAG_UNINITIALIZED;
// For future allocs, keep track of the maximum (aligned) alloc size we used
(*page).max_alloc_size = max(
(*page).max_alloc_size,
size_of::<LlmpMsg>() + buf_len_padded,
);
self.has_unsent_message = true;
Some(ret) Some(ret)
} }
/// Commit the message last allocated by [`alloc_next`] to the queue. /// Commit the message last allocated by [`alloc_next`] to the queue.
/// After commiting, the msg shall no longer be altered! /// After commiting, the msg shall no longer be altered!
/// It will be read by the consuming threads (`broker->clients` or `client->broker`) /// It will be read by the consuming threads (`broker->clients` or `client->broker`)
/// If `overwrite_client_id` is `false`, the message's `sender` won't be touched (for broker forwarding)
#[inline(never)] // Not inlined to make cpu-level reodering (hopefully?) improbable #[inline(never)] // Not inlined to make cpu-level reodering (hopefully?) improbable
unsafe fn send(&mut self, msg: *mut LlmpMsg) -> Result<(), Error> { unsafe fn send(&mut self, msg: *mut LlmpMsg, overwrite_client_id: bool) -> Result<(), Error> {
// dbg!("Sending msg {:?}", msg); // dbg!("Sending msg {:?}", msg);
if self.last_msg_sent == msg { if self.last_msg_sent == msg {
@ -977,6 +959,10 @@ where
if (*msg).tag == LLMP_TAG_UNSET { if (*msg).tag == LLMP_TAG_UNSET {
panic!("No tag set on message with id {}", (*msg).message_id); panic!("No tag set on message with id {}", (*msg).message_id);
} }
// A client gets the sender id assigned to by the broker during the initial handshake.
if overwrite_client_id {
(*msg).sender = self.id;
}
let page = self.out_maps.last_mut().unwrap().page_mut(); let page = self.out_maps.last_mut().unwrap().page_mut();
if msg.is_null() || !llmp_msg_in_page(page, msg) { if msg.is_null() || !llmp_msg_in_page(page, msg) {
return Err(Error::Unknown(format!( return Err(Error::Unknown(format!(
@ -989,6 +975,7 @@ where
ptr::write_volatile(ptr::addr_of_mut!((*page).current_msg_id), (*msg).message_id); ptr::write_volatile(ptr::addr_of_mut!((*page).current_msg_id), (*msg).message_id);
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
self.last_msg_sent = msg; self.last_msg_sent = msg;
self.has_unsent_message = false;
Ok(()) Ok(())
} }
@ -1034,17 +1021,19 @@ where
println!("Setting max alloc size: {:?}", (*old_map).max_alloc_size); println!("Setting max alloc size: {:?}", (*old_map).max_alloc_size);
(*new_map).max_alloc_size = (*old_map).max_alloc_size; (*new_map).max_alloc_size = (*old_map).max_alloc_size;
(*new_map).sender = self.id;
/* On the old map, place a last message linking to the new map for the clients /* On the old map, place a last message linking to the new map for the clients
* to consume */ * to consume */
let mut out: *mut LlmpMsg = self.alloc_eop()?; let out = self.alloc_eop()?;
(*out).sender = (*old_map).sender;
#[allow(clippy::cast_ptr_alignment)]
let mut end_of_page_msg = (*out).buf.as_mut_ptr() as *mut LlmpPayloadSharedMapInfo; let mut end_of_page_msg = (*out).buf.as_mut_ptr() as *mut LlmpPayloadSharedMapInfo;
(*end_of_page_msg).map_size = new_map_shmem.shmem.len(); (*end_of_page_msg).map_size = new_map_shmem.shmem.len();
(*end_of_page_msg).shm_str = *new_map_shmem.shmem.id().as_slice(); (*end_of_page_msg).shm_str = *new_map_shmem.shmem.id().as_slice();
/* Send the last msg on the old buf */ /* Send the last msg on the old buf */
self.send(out)?; self.send(out, true)?;
// Set the new page as current page. // Set the new page as current page.
self.out_maps.push(new_map_shmem); self.out_maps.push(new_map_shmem);
@ -1095,6 +1084,51 @@ where
(*page).size_used -= (*msg).buf_len_padded as usize + size_of::<LlmpMsg>(); (*page).size_used -= (*msg).buf_len_padded as usize + size_of::<LlmpMsg>();
} }
/// Shrinks the allocated [`LlmpMsg`] to a given size.
///
/// # Safety
/// The msg pointer will be dereferenced, if it's not `null`.
pub unsafe fn shrink_alloced(
&mut self,
msg: *mut LlmpMsg,
shrinked_len: usize,
) -> Result<(), Error> {
if msg.is_null() {
return Err(Error::IllegalArgument(
"Null msg passed to shrink_alloced".into(),
));
} else if !self.has_unsent_message {
return Err(Error::IllegalState(
"Called shrink_alloced, but the msg was not unsent".into(),
));
}
let old_len_padded = (*msg).buf_len_padded;
let msg_start = msg as usize;
// Make sure the end of our msg is aligned.
let buf_len_padded = llmp_align(msg_start + shrinked_len + size_of::<LlmpMsg>())
- msg_start
- size_of::<LlmpMsg>();
if buf_len_padded > old_len_padded.try_into().unwrap() {
return Err(Error::IllegalArgument(format!("Cannot shrink msg of size {} (paded: {}) to requested larger size of {} (padded: {})!", (*msg).buf_len, old_len_padded, shrinked_len, buf_len_padded)));
}
(*msg).buf_len = shrinked_len as u64;
(*msg).buf_len_padded = buf_len_padded as u64;
let page = self.out_maps.last_mut().unwrap().page_mut();
// Doing this step by step will catch underflows in debug builds :)
(*page).size_used -= old_len_padded as usize;
(*page).size_used += buf_len_padded as usize;
(*_llmp_next_msg_ptr(msg)).tag = LLMP_TAG_UNSET;
Ok(())
}
/// Allocates a message of the given size, tags it, and sends it off. /// Allocates a message of the given size, tags it, and sends it off.
pub fn send_buf(&mut self, tag: Tag, buf: &[u8]) -> Result<(), Error> { pub fn send_buf(&mut self, tag: Tag, buf: &[u8]) -> Result<(), Error> {
// Make sure we don't reuse already allocated tags // Make sure we don't reuse already allocated tags
@ -1115,7 +1149,7 @@ where
(*msg).flags = LLMP_FLAG_INITIALIZED; (*msg).flags = LLMP_FLAG_INITIALIZED;
buf.as_ptr() buf.as_ptr()
.copy_to_nonoverlapping((*msg).buf.as_mut_ptr(), buf.len()); .copy_to_nonoverlapping((*msg).buf.as_mut_ptr(), buf.len());
self.send(msg) self.send(msg, true)
} }
} }
@ -1139,7 +1173,7 @@ where
(*msg).flags = flags; (*msg).flags = flags;
buf.as_ptr() buf.as_ptr()
.copy_to_nonoverlapping((*msg).buf.as_mut_ptr(), buf.len()); .copy_to_nonoverlapping((*msg).buf.as_mut_ptr(), buf.len());
self.send(msg) self.send(msg, true)
} }
} }
@ -1287,6 +1321,7 @@ where
size_of::<LlmpPayloadSharedMapInfo>() size_of::<LlmpPayloadSharedMapInfo>()
); );
} }
#[allow(clippy::cast_ptr_alignment)]
let pageinfo = (*msg).buf.as_mut_ptr() as *mut LlmpPayloadSharedMapInfo; let pageinfo = (*msg).buf.as_mut_ptr() as *mut LlmpPayloadSharedMapInfo;
/* The pageinfo points to the map we're about to unmap. /* The pageinfo points to the map we're about to unmap.
@ -1339,7 +1374,7 @@ where
if (*last_msg).tag == LLMP_TAG_END_OF_PAGE && !llmp_msg_in_page(page, last_msg) { if (*last_msg).tag == LLMP_TAG_END_OF_PAGE && !llmp_msg_in_page(page, last_msg) {
panic!("BUG: full page passed to await_message_blocking or reset failed"); panic!("BUG: full page passed to await_message_blocking or reset failed");
} }
current_msg_id = (*last_msg).message_id current_msg_id = (*last_msg).message_id;
} }
loop { loop {
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
@ -1355,7 +1390,7 @@ where
/// Returns the next message, tag, buf, if avaliable, else None /// Returns the next message, tag, buf, if avaliable, else None
#[allow(clippy::type_complexity)] #[allow(clippy::type_complexity)]
#[inline] #[inline]
pub fn recv_buf(&mut self) -> Result<Option<(u32, Tag, &[u8])>, Error> { pub fn recv_buf(&mut self) -> Result<Option<(ClientId, Tag, &[u8])>, Error> {
if let Some((sender, tag, _flags, buf)) = self.recv_buf_with_flags()? { if let Some((sender, tag, _flags, buf)) = self.recv_buf_with_flags()? {
Ok(Some((sender, tag, buf))) Ok(Some((sender, tag, buf)))
} else { } else {
@ -1541,18 +1576,19 @@ where
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub unsafe fn msg_to_env(&self, msg: *const LlmpMsg, map_env_name: &str) -> Result<(), Error> { pub unsafe fn msg_to_env(&self, msg: *const LlmpMsg, map_env_name: &str) -> Result<(), Error> {
if msg.is_null() { if msg.is_null() {
env::set_var(&format!("{}_OFFSET", map_env_name), _NULL_ENV_STR) env::set_var(&format!("{}_OFFSET", map_env_name), _NULL_ENV_STR);
} else { } else {
env::set_var( env::set_var(
&format!("{}_OFFSET", map_env_name), &format!("{}_OFFSET", map_env_name),
format!("{}", self.msg_to_offset(msg)?), format!("{}", self.msg_to_offset(msg)?),
) );
}; }
Ok(()) Ok(())
} }
/// Gets this message from this page, at the indicated offset. /// Gets this message from this page, at the indicated offset.
/// Will return [`crate::Error::IllegalArgument`] error if the offset is out of bounds. /// Will return [`crate::Error::IllegalArgument`] error if the offset is out of bounds.
#[allow(clippy::cast_ptr_alignment)]
pub fn msg_from_offset(&mut self, offset: u64) -> Result<*mut LlmpMsg, Error> { pub fn msg_from_offset(&mut self, offset: u64) -> Result<*mut LlmpMsg, Error> {
let offset = offset as usize; let offset = offset as usize;
unsafe { unsafe {
@ -1600,7 +1636,9 @@ pub struct LlmpBrokerSignalHandler {
#[cfg(unix)] #[cfg(unix)]
impl Handler for LlmpBrokerSignalHandler { impl Handler for LlmpBrokerSignalHandler {
fn handle(&mut self, _signal: Signal, _info: siginfo_t, _context: &mut ucontext_t) { fn handle(&mut self, _signal: Signal, _info: siginfo_t, _context: &mut ucontext_t) {
unsafe { ptr::write_volatile(&mut self.shutting_down, true) }; unsafe {
ptr::write_volatile(&mut self.shutting_down, true);
}
} }
fn signals(&self) -> Vec<Signal> { fn signals(&self) -> Vec<Signal> {
@ -1627,6 +1665,7 @@ where
// Broker never cleans up the pages so that new // Broker never cleans up the pages so that new
// clients may join at any time // clients may join at any time
keep_pages_forever: true, keep_pages_forever: true,
has_unsent_message: false,
shmem_provider: shmem_provider.clone(), shmem_provider: shmem_provider.clone(),
}, },
llmp_clients: vec![], llmp_clients: vec![],
@ -1744,9 +1783,9 @@ where
(msg as *const u8).copy_to_nonoverlapping(out as *mut u8, complete_size); (msg as *const u8).copy_to_nonoverlapping(out as *mut u8, complete_size);
(*out).buf_len_padded = actual_size; (*out).buf_len_padded = actual_size;
/* We need to replace the message ID with our own */ /* We need to replace the message ID with our own */
if let Err(e) = self.llmp_out.send(out) { if let Err(e) = self.llmp_out.send(out, false) {
panic!("Error sending msg: {:?}", e) panic!("Error sending msg: {:?}", e);
}; }
self.llmp_out.last_msg_sent = out; self.llmp_out.last_msg_sent = out;
Ok(()) Ok(())
} }
@ -1803,8 +1842,8 @@ where
#[cfg(feature = "std")] #[cfg(feature = "std")]
if let Some(time) = sleep_time { if let Some(time) = sleep_time {
thread::sleep(time) thread::sleep(time);
}; }
#[cfg(not(feature = "std"))] #[cfg(not(feature = "std"))]
match sleep_time { match sleep_time {
@ -1852,10 +1891,11 @@ where
.alloc_next(size_of::<LlmpPayloadSharedMapInfo>()) .alloc_next(size_of::<LlmpPayloadSharedMapInfo>())
.expect("Could not allocate a new message in shared map."); .expect("Could not allocate a new message in shared map.");
(*msg).tag = LLMP_TAG_NEW_SHM_CLIENT; (*msg).tag = LLMP_TAG_NEW_SHM_CLIENT;
#[allow(clippy::cast_ptr_alignment)]
let pageinfo = (*msg).buf.as_mut_ptr() as *mut LlmpPayloadSharedMapInfo; let pageinfo = (*msg).buf.as_mut_ptr() as *mut LlmpPayloadSharedMapInfo;
(*pageinfo).shm_str = *shmem_description.id.as_slice(); (*pageinfo).shm_str = *shmem_description.id.as_slice();
(*pageinfo).map_size = shmem_description.size; (*pageinfo).map_size = shmem_description.size;
sender.send(msg) sender.send(msg, true)
} }
} }
@ -2034,7 +2074,7 @@ where
stream, stream,
shmem_provider, shmem_provider,
*current_client_id, *current_client_id,
&broker_map_description, broker_map_description,
) { ) {
if Self::announce_new_client(sender, &shmem_description).is_err() { if Self::announce_new_client(sender, &shmem_description).is_err() {
println!("B2B: Error announcing client {:?}", shmem_description); println!("B2B: Error announcing client {:?}", shmem_description);
@ -2093,6 +2133,7 @@ where
)], )],
// drop pages to the broker, if it already read them. // drop pages to the broker, if it already read them.
keep_pages_forever: false, keep_pages_forever: false,
has_unsent_message: false,
shmem_provider: shmem_provider_clone.clone(), shmem_provider: shmem_provider_clone.clone(),
}; };
@ -2148,6 +2189,7 @@ where
/// broker broadcast to its own page for all others to read */ /// broker broadcast to its own page for all others to read */
#[inline] #[inline]
#[allow(clippy::cast_ptr_alignment)]
unsafe fn handle_new_msgs<F>(&mut self, client_id: u32, on_new_msg: &mut F) -> Result<(), Error> unsafe fn handle_new_msgs<F>(&mut self, client_id: u32, on_new_msg: &mut F) -> Result<(), Error>
where where
F: FnMut(ClientId, Tag, Flags, &[u8]) -> Result<LlmpMsgHookResult, Error>, F: FnMut(ClientId, Tag, Flags, &[u8]) -> Result<LlmpMsgHookResult, Error>,
@ -2221,8 +2263,8 @@ where
if let LlmpMsgHookResult::Handled = if let LlmpMsgHookResult::Handled =
(on_new_msg)(client_id, (*msg).tag, (*msg).flags, msg_buf)? (on_new_msg)(client_id, (*msg).tag, (*msg).flags, msg_buf)?
{ {
should_forward_msg = false should_forward_msg = false;
}; }
if should_forward_msg { if should_forward_msg {
self.forward_msg(msg)?; self.forward_msg(msg)?;
} }
@ -2360,6 +2402,7 @@ where
})], })],
// drop pages to the broker if it already read them // drop pages to the broker if it already read them
keep_pages_forever: false, keep_pages_forever: false,
has_unsent_message: false,
shmem_provider: shmem_provider.clone(), shmem_provider: shmem_provider.clone(),
}, },
@ -2377,7 +2420,7 @@ where
/// # Safety /// # Safety
/// Needs to be called with a proper msg pointer /// Needs to be called with a proper msg pointer
pub unsafe fn send(&mut self, msg: *mut LlmpMsg) -> Result<(), Error> { pub unsafe fn send(&mut self, msg: *mut LlmpMsg) -> Result<(), Error> {
self.sender.send(msg) self.sender.send(msg, true)
} }
/// Allocates a message of the given size, tags it, and sends it off. /// Allocates a message of the given size, tags it, and sends it off.
@ -2402,6 +2445,7 @@ where
.alloc_next(size_of::<LlmpPayloadSharedMapInfo>()) .alloc_next(size_of::<LlmpPayloadSharedMapInfo>())
.expect("Could not allocate a new message in shared map."); .expect("Could not allocate a new message in shared map.");
(*msg).tag = LLMP_TAG_NEW_SHM_CLIENT; (*msg).tag = LLMP_TAG_NEW_SHM_CLIENT;
#[allow(clippy::cast_ptr_alignment)]
let pageinfo = (*msg).buf.as_mut_ptr() as *mut LlmpPayloadSharedMapInfo; let pageinfo = (*msg).buf.as_mut_ptr() as *mut LlmpPayloadSharedMapInfo;
(*pageinfo).shm_str = *shm_str; (*pageinfo).shm_str = *shm_str;
(*pageinfo).map_size = shm_id; (*pageinfo).map_size = shm_id;
@ -2439,13 +2483,13 @@ where
/// Returns the next message, tag, buf, if avaliable, else None /// Returns the next message, tag, buf, if avaliable, else None
#[allow(clippy::type_complexity)] #[allow(clippy::type_complexity)]
#[inline] #[inline]
pub fn recv_buf(&mut self) -> Result<Option<(u32, Tag, &[u8])>, Error> { pub fn recv_buf(&mut self) -> Result<Option<(ClientId, Tag, &[u8])>, Error> {
self.receiver.recv_buf() self.receiver.recv_buf()
} }
/// Receives a buf from the broker, looping until a messages becomes avaliable /// Receives a buf from the broker, looping until a messages becomes avaliable
#[inline] #[inline]
pub fn recv_buf_blocking(&mut self) -> Result<(u32, Tag, &[u8]), Error> { pub fn recv_buf_blocking(&mut self) -> Result<(ClientId, Tag, &[u8]), Error> {
self.receiver.recv_buf_blocking() self.receiver.recv_buf_blocking()
} }

View File

@ -329,18 +329,18 @@ impl AshmemService {
let client = self.clients.get_mut(&client_id).unwrap(); let client = self.clients.get_mut(&client_id).unwrap();
client client
.stream .stream
.send_fds(&id.to_string().as_bytes(), &[server_fd])?; .send_fds(id.to_string().as_bytes(), &[server_fd])?;
client.maps.entry(server_fd).or_default().push(mapping); client.maps.entry(server_fd).or_default().push(mapping);
} }
AshmemResponse::Id(id) => { AshmemResponse::Id(id) => {
let client = self.clients.get_mut(&client_id).unwrap(); let client = self.clients.get_mut(&client_id).unwrap();
client.stream.send_fds(&id.to_string().as_bytes(), &[])?; client.stream.send_fds(id.to_string().as_bytes(), &[])?;
} }
AshmemResponse::RefCount(refcount) => { AshmemResponse::RefCount(refcount) => {
let client = self.clients.get_mut(&client_id).unwrap(); let client = self.clients.get_mut(&client_id).unwrap();
client client
.stream .stream
.send_fds(&refcount.to_string().as_bytes(), &[])?; .send_fds(refcount.to_string().as_bytes(), &[])?;
} }
} }
Ok(()) Ok(())

View File

@ -327,7 +327,7 @@ pub struct XkcdRand {
#[cfg(test)] #[cfg(test)]
impl Rand for XkcdRand { impl Rand for XkcdRand {
fn set_seed(&mut self, val: u64) { fn set_seed(&mut self, val: u64) {
self.val = val self.val = val;
} }
fn next(&mut self) -> u64 { fn next(&mut self) -> u64 {

View File

@ -248,7 +248,7 @@ where
impl<T: ShMemProvider> Drop for RcShMem<T> { impl<T: ShMemProvider> Drop for RcShMem<T> {
fn drop(&mut self) { fn drop(&mut self) {
self.provider.borrow_mut().release_map(&mut self.internal) self.provider.borrow_mut().release_map(&mut self.internal);
} }
} }
@ -303,7 +303,7 @@ where
} }
fn release_map(&mut self, map: &mut Self::Mem) { fn release_map(&mut self, map: &mut Self::Mem) {
self.internal.borrow_mut().release_map(&mut map.internal) self.internal.borrow_mut().release_map(&mut map.internal);
} }
fn clone_ref(&mut self, mapping: &Self::Mem) -> Result<Self::Mem, Error> { fn clone_ref(&mut self, mapping: &Self::Mem) -> Result<Self::Mem, Error> {

View File

@ -50,7 +50,13 @@ where
fn add(&mut self, mut testcase: Testcase<I>) -> Result<usize, Error> { fn add(&mut self, mut testcase: Testcase<I>) -> Result<usize, Error> {
if testcase.filename().is_none() { if testcase.filename().is_none() {
// TODO walk entry metadata to ask for pices of filename (e.g. :havoc in AFL) // TODO walk entry metadata to ask for pices of filename (e.g. :havoc in AFL)
let filename = self.dir_path.join(format!("id_{}", &self.entries.len())); let filename = self.dir_path.join(
testcase
.input()
.as_ref()
.unwrap()
.generate_name(self.entries.len()),
);
let filename_str = filename.to_str().expect("Invalid Path"); let filename_str = filename.to_str().expect("Invalid Path");
testcase.set_filename(filename_str.into()); testcase.set_filename(filename_str.into());
}; };

View File

@ -10,7 +10,7 @@ use core::ptr::{addr_of, read_volatile};
#[cfg(feature = "std")] #[cfg(feature = "std")]
use crate::bolts::{ use crate::bolts::{
llmp::{LlmpClient, LlmpReceiver}, llmp::{LlmpClient, LlmpConnection, LlmpReceiver},
shmem::StdShMemProvider, shmem::StdShMemProvider,
}; };
@ -19,7 +19,7 @@ use std::net::{SocketAddr, ToSocketAddrs};
use crate::{ use crate::{
bolts::{ bolts::{
llmp::{self, Flags, LlmpClientDescription, LlmpConnection, LlmpSender, Tag}, llmp::{self, Flags, LlmpClientDescription, LlmpSender, Tag},
shmem::ShMemProvider, shmem::ShMemProvider,
}, },
events::{BrokerEventResult, Event, EventFirer, EventManager, EventProcessor, EventRestarter}, events::{BrokerEventResult, Event, EventFirer, EventManager, EventProcessor, EventRestarter},
@ -263,7 +263,7 @@ where
{ {
/// LLMP clients will have to wait until their pages are mapped by somebody. /// LLMP clients will have to wait until their pages are mapped by somebody.
fn drop(&mut self) { fn drop(&mut self) {
self.await_restart_safe() self.await_restart_safe();
} }
} }
@ -332,7 +332,7 @@ where
/// Write the config for a client [`EventManager`] to env vars, a new client can reattach using [`LlmpEventManager::existing_client_from_env()`]. /// Write the config for a client [`EventManager`] to env vars, a new client can reattach using [`LlmpEventManager::existing_client_from_env()`].
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub fn to_env(&self, env_name: &str) { pub fn to_env(&self, env_name: &str) {
self.llmp.to_env(env_name).unwrap() self.llmp.to_env(env_name).unwrap();
} }
// Handle arriving events in the client // Handle arriving events in the client
@ -510,7 +510,7 @@ where
S: DeserializeOwned, S: DeserializeOwned,
SP: ShMemProvider, SP: ShMemProvider,
{ {
let tuple: (S, _) = postcard::from_bytes(&state_corpus_serialized)?; let tuple: (S, _) = postcard::from_bytes(state_corpus_serialized)?;
Ok(( Ok((
tuple.0, tuple.0,
LlmpEventManager::existing_client_from_description(shmem_provider, &tuple.1)?, LlmpEventManager::existing_client_from_description(shmem_provider, &tuple.1)?,
@ -558,13 +558,15 @@ where
/// Otherwise, the OS may already have removed the shared maps, /// Otherwise, the OS may already have removed the shared maps,
#[inline] #[inline]
fn await_restart_safe(&mut self) { fn await_restart_safe(&mut self) {
self.llmp_mgr.await_restart_safe() self.llmp_mgr.await_restart_safe();
} }
/// Reset the single page (we reuse it over and over from pos 0), then send the current state to the next runner. /// Reset the single page (we reuse it over and over from pos 0), then send the current state to the next runner.
fn on_restart(&mut self, state: &mut S) -> Result<(), Error> { fn on_restart(&mut self, state: &mut S) -> Result<(), Error> {
// First, reset the page to 0 so the next iteration can read read from the beginning of this page // First, reset the page to 0 so the next iteration can read read from the beginning of this page
unsafe { self.sender.reset() }; unsafe {
self.sender.reset();
}
let state_corpus_serialized = serialize_state_mgr(state, &self.llmp_mgr)?; let state_corpus_serialized = serialize_state_mgr(state, &self.llmp_mgr)?;
self.sender self.sender
.send_buf(_LLMP_TAG_RESTART, &state_corpus_serialized) .send_buf(_LLMP_TAG_RESTART, &state_corpus_serialized)
@ -598,10 +600,10 @@ where
} }
/// The llmp connection from the actual fuzzer to the process supervising it /// The llmp connection from the actual fuzzer to the process supervising it
const _ENV_FUZZER_SENDER: &str = &"_AFL_ENV_FUZZER_SENDER"; const _ENV_FUZZER_SENDER: &str = "_AFL_ENV_FUZZER_SENDER";
const _ENV_FUZZER_RECEIVER: &str = &"_AFL_ENV_FUZZER_RECEIVER"; const _ENV_FUZZER_RECEIVER: &str = "_AFL_ENV_FUZZER_RECEIVER";
/// The llmp (2 way) connection from a fuzzer to the broker (broadcasting all other fuzzer messages) /// The llmp (2 way) connection from a fuzzer to the broker (broadcasting all other fuzzer messages)
const _ENV_FUZZER_BROKER_CLIENT_INITIAL: &str = &"_AFL_ENV_FUZZER_BROKER_CLIENT"; const _ENV_FUZZER_BROKER_CLIENT_INITIAL: &str = "_AFL_ENV_FUZZER_BROKER_CLIENT";
impl<I, OT, S, SP> LlmpRestartingEventManager<I, OT, S, SP> impl<I, OT, S, SP> LlmpRestartingEventManager<I, OT, S, SP>
where where
@ -881,13 +883,15 @@ where
Some((_sender, _tag, msg)) => { Some((_sender, _tag, msg)) => {
println!("Subsequent run. Let's load all data from shmem (received {} bytes from previous instance)", msg.len()); println!("Subsequent run. Let's load all data from shmem (received {} bytes from previous instance)", msg.len());
let (state, mgr): (S, LlmpEventManager<I, OT, S, SP>) = let (state, mgr): (S, LlmpEventManager<I, OT, S, SP>) =
deserialize_state_mgr(new_shmem_provider, &msg)?; deserialize_state_mgr(new_shmem_provider, msg)?;
(Some(state), LlmpRestartingEventManager::new(mgr, sender)) (Some(state), LlmpRestartingEventManager::new(mgr, sender))
} }
}; };
// We reset the sender, the next sender and receiver (after crash) will reuse the page from the initial message. // We reset the sender, the next sender and receiver (after crash) will reuse the page from the initial message.
unsafe { mgr.sender_mut().reset() }; unsafe {
mgr.sender_mut().reset();
}
/* TODO: Not sure if this is needed /* TODO: Not sure if this is needed
// We commit an empty NO_RESTART message to this buf, against infinite loops, // We commit an empty NO_RESTART message to this buf, against infinite loops,
// in case something crashes in the fuzzer. // in case something crashes in the fuzzer.

View File

@ -346,7 +346,7 @@ where
self.executor self.executor
.out_file_mut() .out_file_mut()
.write_buf(&input.target_bytes().as_slice()); .write_buf(input.target_bytes().as_slice());
let send_len = self let send_len = self
.executor .executor
@ -505,7 +505,7 @@ where
let mut exit_kind = ExitKind::Ok; let mut exit_kind = ExitKind::Ok;
// Write to testcase // Write to testcase
self.out_file.write_buf(&input.target_bytes().as_slice()); self.out_file.write_buf(input.target_bytes().as_slice());
let send_len = self let send_len = self
.forkserver .forkserver

View File

@ -208,7 +208,7 @@ where
/// Retrieve the harness function. /// Retrieve the harness function.
#[inline] #[inline]
pub fn harness(&self) -> &H { pub fn harness(&self) -> &H {
&self.harness_fn self.harness_fn
} }
/// Retrieve the harness function for a mutable reference. /// Retrieve the harness function for a mutable reference.
@ -286,7 +286,7 @@ mod unix_signal_handler {
let data = &mut GLOBAL_STATE; let data = &mut GLOBAL_STATE;
match signal { match signal {
Signal::SigUser2 | Signal::SigAlarm => { Signal::SigUser2 | Signal::SigAlarm => {
(data.timeout_handler)(signal, info, context, data) (data.timeout_handler)(signal, info, context, data);
} }
_ => (data.crash_handler)(signal, info, context, data), _ => (data.crash_handler)(signal, info, context, data),
} }
@ -342,7 +342,7 @@ mod unix_signal_handler {
let interesting = fuzzer let interesting = fuzzer
.objective_mut() .objective_mut()
.is_interesting(state, event_mgr, &input, observers, &ExitKind::Timeout) .is_interesting(state, event_mgr, input, observers, &ExitKind::Timeout)
.expect("In timeout handler objective failure."); .expect("In timeout handler objective failure.");
if interesting { if interesting {
@ -433,7 +433,6 @@ mod unix_signal_handler {
} }
// TODO tell the parent to not restart // TODO tell the parent to not restart
libc::_exit(1);
} else { } else {
let state = (data.state_ptr as *mut S).as_mut().unwrap(); let state = (data.state_ptr as *mut S).as_mut().unwrap();
let event_mgr = (data.event_mgr_ptr as *mut EM).as_mut().unwrap(); let event_mgr = (data.event_mgr_ptr as *mut EM).as_mut().unwrap();
@ -481,7 +480,7 @@ mod unix_signal_handler {
let interesting = fuzzer let interesting = fuzzer
.objective_mut() .objective_mut()
.is_interesting(state, event_mgr, &input, observers, &ExitKind::Crash) .is_interesting(state, event_mgr, input, observers, &ExitKind::Crash)
.expect("In crash handler objective failure."); .expect("In crash handler objective failure.");
if interesting { if interesting {
@ -512,9 +511,9 @@ mod unix_signal_handler {
event_mgr.await_restart_safe(); event_mgr.await_restart_safe();
#[cfg(feature = "std")] #[cfg(feature = "std")]
println!("Bye!"); println!("Bye!");
libc::_exit(1);
} }
libc::_exit(1);
} }
} }

View File

@ -62,7 +62,7 @@ where
let start_time = crate::cpu::read_time_counter(); let start_time = crate::cpu::read_time_counter();
// Execute this feedback // Execute this feedback
let ret = self.is_interesting(state, manager, input, observers, &exit_kind); let ret = self.is_interesting(state, manager, input, observers, exit_kind);
// Get the elapsed time for checking this feedback // Get the elapsed time for checking this feedback
let elapsed = crate::cpu::read_time_counter() - start_time; let elapsed = crate::cpu::read_time_counter() - start_time;
@ -316,7 +316,7 @@ where
manager, manager,
input, input,
observers, observers,
&exit_kind, exit_kind,
feedback_stats, feedback_stats,
feedback_index, feedback_index,
)?; )?;
@ -326,7 +326,7 @@ where
manager, manager,
input, input,
observers, observers,
&exit_kind, exit_kind,
feedback_stats, feedback_stats,
feedback_index + 1, feedback_index + 1,
)?; )?;
@ -387,7 +387,7 @@ where
manager, manager,
input, input,
observers, observers,
&exit_kind, exit_kind,
feedback_stats, feedback_stats,
feedback_index, feedback_index,
)?; )?;
@ -401,7 +401,7 @@ where
manager, manager,
input, input,
observers, observers,
&exit_kind, exit_kind,
feedback_stats, feedback_stats,
feedback_index + 1, feedback_index + 1,
) )
@ -458,7 +458,7 @@ where
manager, manager,
input, input,
observers, observers,
&exit_kind, exit_kind,
feedback_stats, feedback_stats,
feedback_index, feedback_index,
)?; )?;
@ -468,7 +468,7 @@ where
manager, manager,
input, input,
observers, observers,
&exit_kind, exit_kind,
feedback_stats, feedback_stats,
feedback_index + 1, feedback_index + 1,
)?; )?;
@ -529,7 +529,7 @@ where
manager, manager,
input, input,
observers, observers,
&exit_kind, exit_kind,
feedback_stats, feedback_stats,
feedback_index, feedback_index,
)?; )?;
@ -543,7 +543,7 @@ where
manager, manager,
input, input,
observers, observers,
&exit_kind, exit_kind,
feedback_stats, feedback_stats,
feedback_index + 1, feedback_index + 1,
) )

View File

@ -541,7 +541,7 @@ where
start_timer!(state); start_timer!(state);
let is_solution = self let is_solution = self
.objective_mut() .objective_mut()
.is_interesting(state, event_mgr, &input, observers, &exit_kind)?; .is_interesting(state, event_mgr, input, observers, &exit_kind)?;
mark_feature_time!(state, PerfFeature::GetObjectivesInterestingAll); mark_feature_time!(state, PerfFeature::GetObjectivesInterestingAll);
if is_solution { if is_solution {
@ -564,7 +564,7 @@ where
let is_interesting = self.feedback_mut().is_interesting_with_perf( let is_interesting = self.feedback_mut().is_interesting_with_perf(
state, state,
event_mgr, event_mgr,
&input, input,
observers, observers,
&exit_kind, &exit_kind,
&mut feedback_stats, &mut feedback_stats,

View File

@ -1,7 +1,10 @@
//! The `BytesInput` is the "normal" input, a map of bytes, that can be sent directly to the client //! The `BytesInput` is the "normal" input, a map of bytes, that can be sent directly to the client
//! (As opposed to other, more abstract, imputs, like an Grammar-Based AST Input) //! (As opposed to other, more abstract, imputs, like an Grammar-Based AST Input)
use alloc::{borrow::ToOwned, rc::Rc, vec::Vec}; use ahash::AHasher;
use core::hash::Hasher;
use alloc::{borrow::ToOwned, rc::Rc, string::String, vec::Vec};
use core::{cell::RefCell, convert::From}; use core::{cell::RefCell, convert::From};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[cfg(feature = "std")] #[cfg(feature = "std")]
@ -48,6 +51,13 @@ impl Input for BytesInput {
file.read_to_end(&mut bytes)?; file.read_to_end(&mut bytes)?;
Ok(BytesInput::new(bytes)) Ok(BytesInput::new(bytes))
} }
/// Generate a name for this input
fn generate_name(&self, _idx: usize) -> String {
let mut hasher = AHasher::new_with_keys(0, 0);
hasher.write(self.bytes());
format!("{:016x}", hasher.finish())
}
} }
/// Rc Ref-cell from Input /// Rc Ref-cell from Input

View File

@ -3,7 +3,10 @@
pub mod bytes; pub mod bytes;
pub use bytes::BytesInput; pub use bytes::BytesInput;
use alloc::vec::Vec; use alloc::{
string::{String, ToString},
vec::Vec,
};
use core::{clone::Clone, fmt::Debug}; use core::{clone::Clone, fmt::Debug};
#[cfg(feature = "std")] #[cfg(feature = "std")]
use std::{ use std::{
@ -53,12 +56,19 @@ pub trait Input: Clone + serde::Serialize + serde::de::DeserializeOwned + Debug
fn from_file<P>(_path: P) -> Result<Self, Error> { fn from_file<P>(_path: P) -> Result<Self, Error> {
Err(Error::NotImplemented("Not supprted in no_std".into())) Err(Error::NotImplemented("Not supprted in no_std".into()))
} }
/// Generate a name for this input
fn generate_name(&self, idx: usize) -> String;
} }
/// An input for tests, mainly. There is no real use much else. /// An input for tests, mainly. There is no real use much else.
#[derive(Copy, Clone, Serialize, Deserialize, Debug)] #[derive(Copy, Clone, Serialize, Deserialize, Debug)]
pub struct NopInput {} pub struct NopInput {}
impl Input for NopInput {} impl Input for NopInput {
fn generate_name(&self, _idx: usize) -> String {
"nop-input".to_string()
}
}
impl HasTargetBytes for NopInput { impl HasTargetBytes for NopInput {
fn target_bytes(&self) -> OwnedSlice<u8> { fn target_bytes(&self) -> OwnedSlice<u8> {
OwnedSlice::Owned(vec![0]) OwnedSlice::Owned(vec![0])

View File

@ -25,7 +25,9 @@ pub fn buffer_self_copy(data: &mut [u8], from: usize, to: usize, len: usize) {
debug_assert!(to + len <= data.len()); debug_assert!(to + len <= data.len());
if len != 0 && from != to { if len != 0 && from != to {
let ptr = data.as_mut_ptr(); let ptr = data.as_mut_ptr();
unsafe { core::ptr::copy(ptr.add(from), ptr.add(to), len) } unsafe {
core::ptr::copy(ptr.add(from), ptr.add(to), len);
}
} }
} }
@ -39,7 +41,9 @@ pub fn buffer_copy(dst: &mut [u8], src: &[u8], from: usize, to: usize, len: usiz
let dst_ptr = dst.as_mut_ptr(); let dst_ptr = dst.as_mut_ptr();
let src_ptr = src.as_ptr(); let src_ptr = src.as_ptr();
if len != 0 { if len != 0 {
unsafe { core::ptr::copy(src_ptr.add(from), dst_ptr.add(to), len) } unsafe {
core::ptr::copy(src_ptr.add(from), dst_ptr.add(to), len);
}
} }
} }
@ -50,7 +54,7 @@ pub fn buffer_copy(dst: &mut [u8], src: &[u8], from: usize, to: usize, len: usiz
fn buffer_set(data: &mut [u8], from: usize, len: usize, val: u8) { fn buffer_set(data: &mut [u8], from: usize, len: usize, val: u8) {
debug_assert!(from + len <= data.len()); debug_assert!(from + len <= data.len());
for p in &mut data[from..(from + len)] { for p in &mut data[from..(from + len)] {
*p = val *p = val;
} }
} }
@ -1406,7 +1410,7 @@ where
let other = other_testcase.load_input()?; let other = other_testcase.load_input()?;
input input
.bytes_mut() .bytes_mut()
.splice(split_at.., other.bytes()[split_at..].iter().cloned()); .splice(split_at.., other.bytes()[split_at..].iter().copied());
Ok(MutationResult::Mutated) Ok(MutationResult::Mutated)
} }

View File

@ -338,7 +338,7 @@ where
let mut log = Vec::<String>::new(); let mut log = Vec::<String>::new();
while let Some(idx) = self.mutation_log.pop() { while let Some(idx) = self.mutation_log.pop() {
let name = String::from(self.scheduled.mutations().name(idx).unwrap()); // TODO maybe return an Error on None let name = String::from(self.scheduled.mutations().name(idx).unwrap()); // TODO maybe return an Error on None
log.push(name) log.push(name);
} }
let meta = LogMutationMetadata::new(log); let meta = LogMutationMetadata::new(log);
testcase.add_metadata(meta); testcase.add_metadata(meta);
@ -471,7 +471,7 @@ mod tests {
// The pre-seeded rand should have spliced at position 2. // The pre-seeded rand should have spliced at position 2.
// TODO: Maybe have a fixed rand for this purpose? // TODO: Maybe have a fixed rand for this purpose?
assert_eq!(input.bytes(), &[b'a', b'b', b'f']) assert_eq!(input.bytes(), &[b'a', b'b', b'f']);
} }
#[test] #[test]

View File

@ -40,7 +40,7 @@ impl CmpValues {
CmpValues::U16(t) => Some((u64::from(t.0), u64::from(t.1))), CmpValues::U16(t) => Some((u64::from(t.0), u64::from(t.1))),
CmpValues::U32(t) => Some((u64::from(t.0), u64::from(t.1))), CmpValues::U32(t) => Some((u64::from(t.0), u64::from(t.1))),
CmpValues::U64(t) => Some(*t), CmpValues::U64(t) => Some(*t),
_ => None, CmpValues::Bytes(_) => None,
} }
} }
} }

View File

@ -128,7 +128,7 @@ where
#[inline] #[inline]
fn set_initial(&mut self, initial: T) { fn set_initial(&mut self, initial: T) {
self.initial = initial self.initial = initial;
} }
} }
@ -249,7 +249,7 @@ where
#[inline] #[inline]
fn set_initial(&mut self, initial: T) { fn set_initial(&mut self, initial: T) {
self.initial = initial self.initial = initial;
} }
} }
@ -371,7 +371,7 @@ where
#[inline] #[inline]
fn set_initial(&mut self, initial: T) { fn set_initial(&mut self, initial: T) {
self.initial = initial self.initial = initial;
} }
} }

View File

@ -320,7 +320,7 @@ where
} }
fn set_max_size(&mut self, max_size: usize) { fn set_max_size(&mut self, max_size: usize) {
self.max_size = max_size self.max_size = max_size;
} }
} }

View File

@ -190,7 +190,7 @@ pub trait Stats {
self.client_stats_mut().push(ClientStats { self.client_stats_mut().push(ClientStats {
last_window_time: current_time(), last_window_time: current_time(),
..ClientStats::default() ..ClientStats::default()
}) });
} }
&mut self.client_stats_mut()[client_id as usize] &mut self.client_stats_mut()[client_id as usize]
} }
@ -512,7 +512,7 @@ impl ClientPerfStats {
let elapsed = self.mark_time(); let elapsed = self.mark_time();
// Add the time to the scheduler stat // Add the time to the scheduler stat
self.update_scheduler(elapsed) self.update_scheduler(elapsed);
} }
/// Update the time spent in the scheduler with the elapsed time that we have seen /// Update the time spent in the scheduler with the elapsed time that we have seen

View File

@ -86,7 +86,7 @@ impl AsanErrors {
/// Clears this `AsanErrors` struct /// Clears this `AsanErrors` struct
pub fn clear(&mut self) { pub fn clear(&mut self) {
self.errors.clear() self.errors.clear();
} }
/// Gets the amount of `AsanErrors` in this struct /// Gets the amount of `AsanErrors` in this struct
@ -122,7 +122,7 @@ impl AsanErrors {
.add_frame_filter(Box::new(|frames| { .add_frame_filter(Box::new(|frames| {
frames.retain( frames.retain(
|x| matches!(&x.name, Some(n) if !n.starts_with("libafl_frida::asan_rt::")), |x| matches!(&x.name, Some(n) if !n.starts_with("libafl_frida::asan_rt::")),
) );
})); }));
#[allow(clippy::non_ascii_literal)] #[allow(clippy::non_ascii_literal)]

View File

@ -148,7 +148,7 @@ impl AsanRuntime {
/// Check if the test leaked any memory and report it if so. /// Check if the test leaked any memory and report it if so.
pub fn check_for_leaks(&mut self) { pub fn check_for_leaks(&mut self) {
self.allocator.check_for_leaks() self.allocator.check_for_leaks();
} }
/// Returns the `AsanErrors` from the recent run /// Returns the `AsanErrors` from the recent run
@ -182,7 +182,7 @@ impl AsanRuntime {
/// Unpoison all the memory that is currently mapped with read/write permissions. /// Unpoison all the memory that is currently mapped with read/write permissions.
#[allow(clippy::unused_self)] #[allow(clippy::unused_self)]
fn unpoison_all_existing_memory(&mut self) { fn unpoison_all_existing_memory(&mut self) {
self.allocator.unpoison_all_existing_memory() self.allocator.unpoison_all_existing_memory();
} }
/// Register the current thread with the runtime, implementing shadow memory for its stack and /// Register the current thread with the runtime, implementing shadow memory for its stack and
@ -212,7 +212,7 @@ impl AsanRuntime {
}; };
assert!(unsafe { getrlimit(RLIMIT_STACK, &mut stack_rlimit as *mut rlimit) } == 0); assert!(unsafe { getrlimit(RLIMIT_STACK, &mut stack_rlimit as *mut rlimit) } == 0);
stack_rlimit.rlim_max as usize stack_rlimit.rlim_cur as usize
} }
/// Get the maximum stack size for the current stack /// Get the maximum stack size for the current stack
@ -225,7 +225,7 @@ impl AsanRuntime {
}; };
assert!(unsafe { getrlimit64(RLIMIT_STACK, &mut stack_rlimit as *mut rlimit64) } == 0); assert!(unsafe { getrlimit64(RLIMIT_STACK, &mut stack_rlimit as *mut rlimit64) } == 0);
stack_rlimit.rlim_max as usize stack_rlimit.rlim_cur as usize
} }
/// Determine the stack start, end for the currently running thread /// Determine the stack start, end for the currently running thread
@ -238,7 +238,9 @@ impl AsanRuntime {
let stack_address = &mut stack_var as *mut _ as *mut c_void as usize; let stack_address = &mut stack_var as *mut _ as *mut c_void as usize;
let range_details = RangeDetails::with_address(stack_address as u64).unwrap(); let range_details = RangeDetails::with_address(stack_address as u64).unwrap();
// Write something to (hopefully) make sure the val isn't optimized out // Write something to (hopefully) make sure the val isn't optimized out
unsafe { write_volatile(&mut stack_var, 0xfadbeef) }; unsafe {
write_volatile(&mut stack_var, 0xfadbeef);
}
let start = range_details.memory_range().base_address().0 as usize; let start = range_details.memory_range().base_address().0 as usize;
let end = start + range_details.memory_range().size(); let end = start + range_details.memory_range().size();
@ -1871,7 +1873,7 @@ impl AsanRuntime {
actual_pc = insn.address() as usize; actual_pc = insn.address() as usize;
} }
let detail = cs.insn_detail(&insn).unwrap(); let detail = cs.insn_detail(insn).unwrap();
let arch_detail = detail.arch_detail(); let arch_detail = detail.arch_detail();
let (mut base_reg, mut index_reg, displacement) = let (mut base_reg, mut index_reg, displacement) =
if let Arm64Operand(arm64operand) = arch_detail.operands().last().unwrap() { if let Arm64Operand(arm64operand) = arch_detail.operands().last().unwrap() {
@ -1908,12 +1910,12 @@ impl AsanRuntime {
base_reg -= capstone::arch::arm64::Arm64Reg::ARM64_REG_S0 as u16; base_reg -= capstone::arch::arm64::Arm64Reg::ARM64_REG_S0 as u16;
} }
#[allow(clippy::clippy::cast_possible_wrap)] #[allow(clippy::cast_possible_wrap)]
let mut fault_address = let mut fault_address =
(self.regs[base_reg as usize] as isize + displacement as isize) as usize; (self.regs[base_reg as usize] as isize + displacement as isize) as usize;
if index_reg == 0 { if index_reg == 0 {
index_reg = 0xffff index_reg = 0xffff;
} else { } else {
if capstone::arch::arm64::Arm64Reg::ARM64_REG_X0 as u16 <= index_reg if capstone::arch::arm64::Arm64Reg::ARM64_REG_X0 as u16 <= index_reg
&& index_reg <= capstone::arch::arm64::Arm64Reg::ARM64_REG_X28 as u16 && index_reg <= capstone::arch::arm64::Arm64Reg::ARM64_REG_X28 as u16
@ -1996,7 +1998,7 @@ impl AsanRuntime {
AsanErrors::get_mut().report_error(error); AsanErrors::get_mut().report_error(error);
} }
#[allow(clippy::unused_self)] #[allow(clippy::unused_self, clippy::identity_op)] // identity_op appears to be a false positive in ubfx
fn generate_shadow_check_function(&mut self) { fn generate_shadow_check_function(&mut self) {
let shadow_bit = self.allocator.shadow_bit(); let shadow_bit = self.allocator.shadow_bit();
let mut ops = dynasmrt::VecAssembler::<dynasmrt::aarch64::Aarch64Relocation>::new(0); let mut ops = dynasmrt::VecAssembler::<dynasmrt::aarch64::Aarch64Relocation>::new(0);

View File

@ -224,7 +224,7 @@ fn pc(context: &CpuContext) -> usize {
/// The implementation of the [`FridaInstrumentationHelper`] /// The implementation of the [`FridaInstrumentationHelper`]
impl<'a> FridaInstrumentationHelper<'a> { impl<'a> FridaInstrumentationHelper<'a> {
/// Constructor function to create a new [`FridaInstrumentationHelper`], given a `module_name`. /// Constructor function to create a new [`FridaInstrumentationHelper`], given a `module_name`.
#[allow(clippy::clippy::too_many_lines)] #[allow(clippy::too_many_lines)]
#[must_use] #[must_use]
pub fn new( pub fn new(
gum: &'a Gum, gum: &'a Gum,
@ -325,7 +325,7 @@ impl<'a> FridaInstrumentationHelper<'a> {
helper helper
.drcov_basic_blocks .drcov_basic_blocks
.push(DrCovBasicBlock::new(real_address, real_address + 4)); .push(DrCovBasicBlock::new(real_address, real_address + 4));
}) });
} }
} }
@ -370,7 +370,7 @@ impl<'a> FridaInstrumentationHelper<'a> {
); );
} }
} }
instruction.keep() instruction.keep();
} }
}); });
helper.transformer = Some(transformer); helper.transformer = Some(transformer);
@ -386,7 +386,7 @@ impl<'a> FridaInstrumentationHelper<'a> {
#[inline] #[inline]
fn options(&self) -> &FridaOptions { fn options(&self) -> &FridaOptions {
&self.options self.options
} }
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
#[inline] #[inline]
@ -1118,7 +1118,6 @@ impl<'a> FridaInstrumentationHelper<'a> {
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
{ {
println!("here");
writer.put_lea_reg_reg_offset(X86Register::Rsp, X86Register::Rsp, -(redzone_size)); writer.put_lea_reg_reg_offset(X86Register::Rsp, X86Register::Rsp, -(redzone_size));
writer.put_push_reg(X86Register::Rdi); writer.put_push_reg(X86Register::Rdi);
writer.put_mov_reg_address( writer.put_mov_reg_address(

View File

@ -19,10 +19,16 @@ fn main() {
let mut sancov_cmp = cc::Build::new(); let mut sancov_cmp = cc::Build::new();
#[cfg(feature = "sancov_value_profile")] #[cfg(feature = "sancov_value_profile")]
sancov_cmp.define("SANCOV_VALUE_PROFILE", "1"); {
sancov_cmp.define("SANCOV_VALUE_PROFILE", "1");
println!("cargo:rerun-if-changed=src/value_profile.h");
}
#[cfg(feature = "sancov_cmplog")] #[cfg(feature = "sancov_cmplog")]
sancov_cmp.define("SANCOV_CMPLOG", "1"); {
sancov_cmp.define("SANCOV_CMPLOG", "1");
println!("cargo:rerun-if-changed=src/cmplog.h");
}
sancov_cmp sancov_cmp
.file(_src_dir.join("sancov_cmp.c")) .file(_src_dir.join("sancov_cmp.c"))

View File

@ -15,7 +15,7 @@ extern "C" {
/// # Safety /// # Safety
/// Calls the libfuzzer-style init function which is native code. /// Calls the libfuzzer-style init function which is native code.
#[allow(clippy::similar_names)] #[allow(clippy::similar_names)]
#[allow(clippy::clippy::must_use_candidate)] // nobody uses that return code... #[allow(clippy::must_use_candidate)] // nobody uses that return code...
pub fn libfuzzer_initialize(args: &[String]) -> i32 { pub fn libfuzzer_initialize(args: &[String]) -> i32 {
let argv: Vec<*const u8> = args.iter().map(|x| x.as_bytes().as_ptr()).collect(); let argv: Vec<*const u8> = args.iter().map(|x| x.as_bytes().as_ptr()).collect();
assert!(argv.len() < i32::MAX as usize); assert!(argv.len() < i32::MAX as usize);
@ -32,7 +32,7 @@ pub fn libfuzzer_initialize(args: &[String]) -> i32 {
/// Call a single input of a libfuzzer-style cpp-harness /// Call a single input of a libfuzzer-style cpp-harness
/// # Safety /// # Safety
/// Calls the libfuzzer harness. We actually think the target is unsafe and crashes eventually, that's why we do all this fuzzing. /// Calls the libfuzzer harness. We actually think the target is unsafe and crashes eventually, that's why we do all this fuzzing.
#[allow(clippy::clippy::must_use_candidate)] #[allow(clippy::must_use_candidate)]
pub fn libfuzzer_test_one_input(buf: &[u8]) -> i32 { pub fn libfuzzer_test_one_input(buf: &[u8]) -> i32 {
unsafe { LLVMFuzzerTestOneInput(buf.as_ptr(), buf.len()) } unsafe { LLVMFuzzerTestOneInput(buf.as_ptr(), buf.len()) }
} }

View File

@ -8,43 +8,6 @@
#include "cmplog.h" #include "cmplog.h"
#endif #endif
#if defined(__APPLE__)
void __sanitizer_cov_trace_cmp1(uint8_t arg1, uint8_t arg2);
void __sanitizer_cov_trace_const_cmp1(uint8_t arg1, uint8_t arg2) {
__sanitizer_cov_trace_cmp1(arg1, arg2);
}
void __sanitizer_cov_trace_cmp2(uint16_t arg1, uint16_t arg2);
void __sanitizer_cov_trace_const_cmp2(uint16_t arg1, uint16_t arg2) {
__sanitizer_cov_trace_cmp2(arg1, arg2);
}
void __sanitizer_cov_trace_cmp4(uint32_t arg1, uint32_t arg2);
void __sanitizer_cov_trace_const_cmp4(uint32_t arg1, uint32_t arg2) {
__sanitizer_cov_trace_cmp4(arg1, arg2);
}
void __sanitizer_cov_trace_cmp8(uint64_t arg1, uint64_t arg2);
void __sanitizer_cov_trace_const_cmp8(uint64_t arg1, uint64_t arg2) {
__sanitizer_cov_trace_cmp8(arg1, arg2);
}
#elif defined(_MSC_VER)
#pragma comment(linker, "/alternatename:__sanitizer_cov_trace_const_cmp1=__sanitizer_cov_trace_cmp1")
#pragma comment(linker, "/alternatename:__sanitizer_cov_trace_const_cmp2=__sanitizer_cov_trace_cmp2")
#pragma comment(linker, "/alternatename:__sanitizer_cov_trace_const_cmp4=__sanitizer_cov_trace_cmp4")
#pragma comment(linker, "/alternatename:__sanitizer_cov_trace_const_cmp8=__sanitizer_cov_trace_cmp8")
#else
void __sanitizer_cov_trace_const_cmp1(uint8_t arg1, uint8_t arg2) __attribute__((alias("__sanitizer_cov_trace_cmp1")));
void __sanitizer_cov_trace_const_cmp2(uint16_t arg1, uint16_t arg2)
__attribute__((alias("__sanitizer_cov_trace_cmp2")));
void __sanitizer_cov_trace_const_cmp4(uint32_t arg1, uint32_t arg2)
__attribute__((alias("__sanitizer_cov_trace_cmp4")));
void __sanitizer_cov_trace_const_cmp8(uint64_t arg1, uint64_t arg2)
__attribute__((alias("__sanitizer_cov_trace_cmp8")));
#endif
void __sanitizer_cov_trace_cmp1(uint8_t arg1, uint8_t arg2) { void __sanitizer_cov_trace_cmp1(uint8_t arg1, uint8_t arg2) {
uintptr_t k = RETADDR; uintptr_t k = RETADDR;
@ -158,3 +121,18 @@ void __sanitizer_cov_trace_switch(uint64_t val, uint64_t *cases) {
} }
void __sanitizer_cov_trace_const_cmp1(uint8_t arg1, uint8_t arg2) {
__sanitizer_cov_trace_cmp1(arg1, arg2);
}
void __sanitizer_cov_trace_const_cmp2(uint16_t arg1, uint16_t arg2) {
__sanitizer_cov_trace_cmp2(arg1, arg2);
}
void __sanitizer_cov_trace_const_cmp4(uint32_t arg1, uint32_t arg2) {
__sanitizer_cov_trace_cmp4(arg1, arg2);
}
void __sanitizer_cov_trace_const_cmp8(uint64_t arg1, uint64_t arg2) {
__sanitizer_cov_trace_cmp8(arg1, arg2);
}