Merge branch 'main' into cmplog_instrumentation
This commit is contained in:
commit
5de4c9305e
@ -31,7 +31,6 @@ libc = "0.2"
|
||||
libloading = "0.7.0"
|
||||
num-traits = "0.2.14"
|
||||
rangemap = "0.1.10"
|
||||
seahash = "4.1.0"
|
||||
clap = "2.33"
|
||||
serde = "1.0"
|
||||
|
||||
|
@ -275,7 +275,7 @@ fn fuzz(
|
||||
|
||||
/// The actual fuzzer
|
||||
#[cfg(unix)]
|
||||
#[allow(clippy::too_many_lines, clippy::clippy::too_many_arguments)]
|
||||
#[allow(clippy::too_many_lines, clippy::too_many_arguments)]
|
||||
unsafe fn fuzz(
|
||||
module_name: &str,
|
||||
symbol_name: &str,
|
||||
|
@ -16,7 +16,7 @@ rustc_version = "0.3.3"
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = "0.3" # Benchmarking
|
||||
ahash = "0.6.1" # another hash
|
||||
ahash = "0.7" # another hash
|
||||
fxhash = "0.2.1" # yet another hash
|
||||
xxhash-rust = { version = "0.8.2", features = ["xxh3"] } # xxh3 hashing for rust
|
||||
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"
|
||||
hostname = "^0.3" # Is there really no gethostname in the stdlib?
|
||||
typed-builder = "0.9.0"
|
||||
ahash ="0.7"
|
||||
|
||||
[target.'cfg(target_os = "android")'.dependencies]
|
||||
backtrace = { version = "0.3", optional = true, default-features = false, features = ["std", "libbacktrace"] } # for llmp_debug
|
||||
|
@ -31,7 +31,7 @@ fn adder_loop(port: u16) -> ! {
|
||||
loop {
|
||||
let mut msg_counter = 0;
|
||||
loop {
|
||||
let (_sender, tag, buf) = match client.recv_buf().unwrap() {
|
||||
let (sender, tag, buf) = match client.recv_buf().unwrap() {
|
||||
None => break,
|
||||
Some(msg) => msg,
|
||||
};
|
||||
@ -42,8 +42,9 @@ fn adder_loop(port: u16) -> ! {
|
||||
current_result.wrapping_add(u32::from_le_bytes(buf.try_into().unwrap()));
|
||||
}
|
||||
_ => println!(
|
||||
"Adder Client ignored unknown message {} with {} bytes",
|
||||
"Adder Client ignored unknown message {:#x} from client {} with {} bytes",
|
||||
tag,
|
||||
sender,
|
||||
buf.len()
|
||||
),
|
||||
};
|
||||
|
@ -32,7 +32,7 @@ impl GzipCompressor {
|
||||
//compress if the buffer is large enough
|
||||
let compressed = buf
|
||||
.iter()
|
||||
.cloned()
|
||||
.copied()
|
||||
.encode(&mut GZipEncoder::new(), Action::Finish)
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
Ok(Some(compressed))
|
||||
@ -47,7 +47,7 @@ impl GzipCompressor {
|
||||
pub fn decompress(&self, buf: &[u8]) -> Result<Vec<u8>, Error> {
|
||||
Ok(buf
|
||||
.iter()
|
||||
.cloned()
|
||||
.copied()
|
||||
.decode(&mut GZipDecoder::new())
|
||||
.collect::<Result<Vec<_>, _>>()?)
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ use typed_builder::TypedBuilder;
|
||||
pub type LauncherClientFnRef<'a, I, OT, S, SP> =
|
||||
&'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
|
||||
#[cfg(feature = "std")]
|
||||
#[derive(TypedBuilder)]
|
||||
@ -54,7 +55,7 @@ where
|
||||
stats: ST,
|
||||
/// The 'main' function to run for each client forked. This probably shouldn't return
|
||||
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)]
|
||||
broker_port: u16,
|
||||
/// The list of cores to run on
|
||||
@ -66,6 +67,12 @@ where
|
||||
/// clusters.
|
||||
#[builder(default = None)]
|
||||
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")]
|
||||
@ -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
|
||||
RestartingMgr::<I, OT, S, SP, ST>::builder()
|
||||
.shmem_provider(self.shmem_provider.clone())
|
||||
.stats(Some(self.stats.clone()))
|
||||
.broker_port(self.broker_port)
|
||||
.kind(ManagerKind::Broker)
|
||||
.remote_broker_addr(self.remote_broker_addr)
|
||||
.build()
|
||||
.launch()?;
|
||||
if self.spawn_broker {
|
||||
#[cfg(feature = "std")]
|
||||
println!("I am broker!!.");
|
||||
|
||||
// Broker exited. kill all clients.
|
||||
for handle in &handles {
|
||||
unsafe {
|
||||
libc::kill(*handle, libc::SIGINT);
|
||||
// TODO we don't want always a broker here, thing about using different laucher process to spawn different configurations
|
||||
RestartingMgr::<I, OT, S, SP, ST>::builder()
|
||||
.shmem_provider(self.shmem_provider.clone())
|
||||
.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!"),
|
||||
};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
println!("I am broker!!.");
|
||||
if self.spawn_broker {
|
||||
#[cfg(feature = "std")]
|
||||
println!("I am broker!!.");
|
||||
|
||||
RestartingMgr::<I, OT, S, SP, ST>::builder()
|
||||
.shmem_provider(self.shmem_provider.clone())
|
||||
.stats(Some(self.stats.clone()))
|
||||
.broker_port(self.broker_port)
|
||||
.kind(ManagerKind::Broker)
|
||||
.remote_broker_addr(self.remote_broker_addr)
|
||||
.build()
|
||||
.launch()?;
|
||||
RestartingMgr::<I, OT, S, SP, ST>::builder()
|
||||
.shmem_provider(self.shmem_provider.clone())
|
||||
.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 &mut handles {
|
||||
handle.kill()?;
|
||||
//broker exited. kill all clients.
|
||||
for handle in &mut handles {
|
||||
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(())
|
||||
}
|
||||
}
|
||||
|
||||
const _AFL_LAUNCHER_CLIENT: &str = &"AFL_LAUNCHER_CLIENT";
|
||||
|
@ -62,7 +62,7 @@ For broker2broker communication, all messages are forwarded via network sockets.
|
||||
use alloc::{string::String, vec::Vec};
|
||||
use core::{
|
||||
cmp::max,
|
||||
convert::TryFrom,
|
||||
convert::{TryFrom, TryInto},
|
||||
fmt::Debug,
|
||||
mem::size_of,
|
||||
ptr, slice,
|
||||
@ -73,7 +73,6 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use std::{
|
||||
convert::TryInto,
|
||||
env,
|
||||
io::{ErrorKind, Read, Write},
|
||||
net::{SocketAddr, TcpListener, TcpStream, ToSocketAddrs},
|
||||
@ -281,12 +280,14 @@ impl Listener {
|
||||
|
||||
/// Get sharedmem from a page
|
||||
#[inline]
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
unsafe fn shmem2page_mut<SHM: ShMem>(afl_shmem: &mut SHM) -> *mut LlmpPage {
|
||||
afl_shmem.map_mut().as_mut_ptr() as *mut LlmpPage
|
||||
}
|
||||
|
||||
/// Get sharedmem from a page
|
||||
#[inline]
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
unsafe fn shmem2page<SHM: ShMem>(afl_shmem: &SHM) -> *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
|
||||
/// The messages are padded, so accesses will be aligned properly.
|
||||
#[inline]
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
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)); */
|
||||
(last_msg as *mut u8)
|
||||
@ -489,7 +492,7 @@ pub enum LlmpMsgHookResult {
|
||||
|
||||
/// Message sent over the "wire"
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[repr(C, packed)]
|
||||
#[repr(C)]
|
||||
pub struct LlmpMsg {
|
||||
/// A tag
|
||||
pub tag: Tag, //u32
|
||||
@ -621,7 +624,7 @@ where
|
||||
pub fn describe(&self) -> Result<LlmpClientDescription, Error> {
|
||||
Ok(match self {
|
||||
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
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[repr(C, packed)]
|
||||
#[repr(C)]
|
||||
pub struct LlmpPage {
|
||||
/// to check if this page got initialized properly
|
||||
pub magic: u64,
|
||||
@ -683,7 +686,7 @@ pub struct LlmpPage {
|
||||
/// This is an internal message!
|
||||
/// [`LLMP_TAG_END_OF_PAGE_V1`]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[repr(C, packed)]
|
||||
#[repr(C)]
|
||||
struct LlmpPayloadSharedMapInfo {
|
||||
/// The map size
|
||||
pub map_size: usize,
|
||||
@ -697,7 +700,7 @@ pub struct LlmpSender<SP>
|
||||
where
|
||||
SP: ShMemProvider,
|
||||
{
|
||||
/// ID of this sender. Only used in the broker.
|
||||
/// ID of this sender.
|
||||
pub id: u32,
|
||||
/// Ref to the last message this sender sent on the last page.
|
||||
/// If null, a new page (just) started.
|
||||
@ -709,6 +712,9 @@ where
|
||||
/// By keeping the message history around,
|
||||
/// new clients may join at any time in the future.
|
||||
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,
|
||||
}
|
||||
|
||||
@ -730,6 +736,7 @@ where
|
||||
)],
|
||||
// drop pages to the broker if it already read them
|
||||
keep_pages_forever,
|
||||
has_unsent_message: false,
|
||||
shmem_provider,
|
||||
})
|
||||
}
|
||||
@ -804,6 +811,7 @@ where
|
||||
out_maps: vec![out_map],
|
||||
// drop pages to the broker if it already read them
|
||||
keep_pages_forever: false,
|
||||
has_unsent_message: false,
|
||||
shmem_provider,
|
||||
})
|
||||
}
|
||||
@ -864,111 +872,85 @@ where
|
||||
/// 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.
|
||||
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 page = map.page_mut();
|
||||
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"))]
|
||||
println!(
|
||||
"Allocating {} (>={}) bytes on page {:?} / map {:?} (last msg: {:?})",
|
||||
complete_msg_size, buf_len, page, &map, last_msg
|
||||
"Allocating {} bytes on 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;
|
||||
/* 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?
|
||||
*/
|
||||
let msg_start = (*page).messages.as_mut_ptr() as usize + (*page).size_used;
|
||||
|
||||
// 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"))]
|
||||
dbg!(
|
||||
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); */
|
||||
println!("LLMP: Page full.");
|
||||
|
||||
/* Still space for the new message plus the additional "we're full" message? */
|
||||
if (*page).size_used + complete_msg_size + EOP_MSG_SIZE > (*page).size_total {
|
||||
/* We're full. */
|
||||
return None;
|
||||
}
|
||||
ret = match llmp_next_msg_ptr_checked(map, last_msg, complete_msg_size) {
|
||||
Ok(msg) => msg,
|
||||
Err(e) => {
|
||||
#[cfg(feature = "std")]
|
||||
dbg!("Unexpected error allocing new msg", e);
|
||||
#[cfg(feature = "std")]
|
||||
return None;
|
||||
#[cfg(not(feature = "std"))]
|
||||
panic!("Unexpected error allocing new msg {:?}", e);
|
||||
}
|
||||
};
|
||||
(*ret).message_id = (*last_msg).message_id + 1
|
||||
/* We're full. */
|
||||
return None;
|
||||
}
|
||||
|
||||
let ret = msg_start as *mut LlmpMsg;
|
||||
|
||||
/* 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 if (*page).current_msg_id == (*last_msg).message_id {
|
||||
(*last_msg).message_id + 1
|
||||
} else {
|
||||
/* 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);
|
||||
}
|
||||
};
|
||||
|
||||
/* 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;
|
||||
/* DBG("Returning new message at %p with len %ld, TAG was %x", ret, ret->buf_len_padded, ret->tag); */
|
||||
/* Maybe catch some bugs... */
|
||||
(*ret).buf_len_padded = buf_len_padded as u64;
|
||||
(*page).size_used += size_of::<LlmpMsg>() + buf_len_padded;
|
||||
|
||||
(*_llmp_next_msg_ptr(ret)).tag = LLMP_TAG_UNSET;
|
||||
(*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)
|
||||
}
|
||||
|
||||
/// Commit the message last allocated by [`alloc_next`] to the queue.
|
||||
/// After commiting, the msg shall no longer be altered!
|
||||
/// 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
|
||||
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);
|
||||
|
||||
if self.last_msg_sent == msg {
|
||||
@ -977,6 +959,10 @@ where
|
||||
if (*msg).tag == LLMP_TAG_UNSET {
|
||||
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();
|
||||
if msg.is_null() || !llmp_msg_in_page(page, msg) {
|
||||
return Err(Error::Unknown(format!(
|
||||
@ -989,6 +975,7 @@ where
|
||||
ptr::write_volatile(ptr::addr_of_mut!((*page).current_msg_id), (*msg).message_id);
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
self.last_msg_sent = msg;
|
||||
self.has_unsent_message = false;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -1034,17 +1021,19 @@ where
|
||||
println!("Setting 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
|
||||
* to consume */
|
||||
let mut out: *mut LlmpMsg = self.alloc_eop()?;
|
||||
(*out).sender = (*old_map).sender;
|
||||
let out = self.alloc_eop()?;
|
||||
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
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).shm_str = *new_map_shmem.shmem.id().as_slice();
|
||||
|
||||
/* Send the last msg on the old buf */
|
||||
self.send(out)?;
|
||||
self.send(out, true)?;
|
||||
|
||||
// Set the new page as current page.
|
||||
self.out_maps.push(new_map_shmem);
|
||||
@ -1095,6 +1084,51 @@ where
|
||||
(*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.
|
||||
pub fn send_buf(&mut self, tag: Tag, buf: &[u8]) -> Result<(), Error> {
|
||||
// Make sure we don't reuse already allocated tags
|
||||
@ -1115,7 +1149,7 @@ where
|
||||
(*msg).flags = LLMP_FLAG_INITIALIZED;
|
||||
buf.as_ptr()
|
||||
.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;
|
||||
buf.as_ptr()
|
||||
.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>()
|
||||
);
|
||||
}
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
let pageinfo = (*msg).buf.as_mut_ptr() as *mut LlmpPayloadSharedMapInfo;
|
||||
|
||||
/* 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) {
|
||||
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 {
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
@ -1355,7 +1390,7 @@ where
|
||||
/// Returns the next message, tag, buf, if avaliable, else None
|
||||
#[allow(clippy::type_complexity)]
|
||||
#[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()? {
|
||||
Ok(Some((sender, tag, buf)))
|
||||
} else {
|
||||
@ -1541,18 +1576,19 @@ where
|
||||
#[cfg(feature = "std")]
|
||||
pub unsafe fn msg_to_env(&self, msg: *const LlmpMsg, map_env_name: &str) -> Result<(), Error> {
|
||||
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 {
|
||||
env::set_var(
|
||||
&format!("{}_OFFSET", map_env_name),
|
||||
format!("{}", self.msg_to_offset(msg)?),
|
||||
)
|
||||
};
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Gets this message from this page, at the indicated offset.
|
||||
/// 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> {
|
||||
let offset = offset as usize;
|
||||
unsafe {
|
||||
@ -1600,7 +1636,9 @@ pub struct LlmpBrokerSignalHandler {
|
||||
#[cfg(unix)]
|
||||
impl Handler for LlmpBrokerSignalHandler {
|
||||
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> {
|
||||
@ -1627,6 +1665,7 @@ where
|
||||
// Broker never cleans up the pages so that new
|
||||
// clients may join at any time
|
||||
keep_pages_forever: true,
|
||||
has_unsent_message: false,
|
||||
shmem_provider: shmem_provider.clone(),
|
||||
},
|
||||
llmp_clients: vec![],
|
||||
@ -1744,9 +1783,9 @@ where
|
||||
(msg as *const u8).copy_to_nonoverlapping(out as *mut u8, complete_size);
|
||||
(*out).buf_len_padded = actual_size;
|
||||
/* We need to replace the message ID with our own */
|
||||
if let Err(e) = self.llmp_out.send(out) {
|
||||
panic!("Error sending msg: {:?}", e)
|
||||
};
|
||||
if let Err(e) = self.llmp_out.send(out, false) {
|
||||
panic!("Error sending msg: {:?}", e);
|
||||
}
|
||||
self.llmp_out.last_msg_sent = out;
|
||||
Ok(())
|
||||
}
|
||||
@ -1803,8 +1842,8 @@ where
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
if let Some(time) = sleep_time {
|
||||
thread::sleep(time)
|
||||
};
|
||||
thread::sleep(time);
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
match sleep_time {
|
||||
@ -1852,10 +1891,11 @@ where
|
||||
.alloc_next(size_of::<LlmpPayloadSharedMapInfo>())
|
||||
.expect("Could not allocate a new message in shared map.");
|
||||
(*msg).tag = LLMP_TAG_NEW_SHM_CLIENT;
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
let pageinfo = (*msg).buf.as_mut_ptr() as *mut LlmpPayloadSharedMapInfo;
|
||||
(*pageinfo).shm_str = *shmem_description.id.as_slice();
|
||||
(*pageinfo).map_size = shmem_description.size;
|
||||
sender.send(msg)
|
||||
sender.send(msg, true)
|
||||
}
|
||||
}
|
||||
|
||||
@ -2034,7 +2074,7 @@ where
|
||||
stream,
|
||||
shmem_provider,
|
||||
*current_client_id,
|
||||
&broker_map_description,
|
||||
broker_map_description,
|
||||
) {
|
||||
if Self::announce_new_client(sender, &shmem_description).is_err() {
|
||||
println!("B2B: Error announcing client {:?}", shmem_description);
|
||||
@ -2093,6 +2133,7 @@ where
|
||||
)],
|
||||
// drop pages to the broker, if it already read them.
|
||||
keep_pages_forever: false,
|
||||
has_unsent_message: false,
|
||||
shmem_provider: shmem_provider_clone.clone(),
|
||||
};
|
||||
|
||||
@ -2148,6 +2189,7 @@ where
|
||||
|
||||
/// broker broadcast to its own page for all others to read */
|
||||
#[inline]
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
unsafe fn handle_new_msgs<F>(&mut self, client_id: u32, on_new_msg: &mut F) -> Result<(), Error>
|
||||
where
|
||||
F: FnMut(ClientId, Tag, Flags, &[u8]) -> Result<LlmpMsgHookResult, Error>,
|
||||
@ -2221,8 +2263,8 @@ where
|
||||
if let LlmpMsgHookResult::Handled =
|
||||
(on_new_msg)(client_id, (*msg).tag, (*msg).flags, msg_buf)?
|
||||
{
|
||||
should_forward_msg = false
|
||||
};
|
||||
should_forward_msg = false;
|
||||
}
|
||||
if should_forward_msg {
|
||||
self.forward_msg(msg)?;
|
||||
}
|
||||
@ -2360,6 +2402,7 @@ where
|
||||
})],
|
||||
// drop pages to the broker if it already read them
|
||||
keep_pages_forever: false,
|
||||
has_unsent_message: false,
|
||||
shmem_provider: shmem_provider.clone(),
|
||||
},
|
||||
|
||||
@ -2377,7 +2420,7 @@ where
|
||||
/// # Safety
|
||||
/// Needs to be called with a proper msg pointer
|
||||
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.
|
||||
@ -2402,6 +2445,7 @@ where
|
||||
.alloc_next(size_of::<LlmpPayloadSharedMapInfo>())
|
||||
.expect("Could not allocate a new message in shared map.");
|
||||
(*msg).tag = LLMP_TAG_NEW_SHM_CLIENT;
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
let pageinfo = (*msg).buf.as_mut_ptr() as *mut LlmpPayloadSharedMapInfo;
|
||||
(*pageinfo).shm_str = *shm_str;
|
||||
(*pageinfo).map_size = shm_id;
|
||||
@ -2439,13 +2483,13 @@ where
|
||||
/// Returns the next message, tag, buf, if avaliable, else None
|
||||
#[allow(clippy::type_complexity)]
|
||||
#[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()
|
||||
}
|
||||
|
||||
/// Receives a buf from the broker, looping until a messages becomes avaliable
|
||||
#[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()
|
||||
}
|
||||
|
||||
|
@ -329,18 +329,18 @@ impl AshmemService {
|
||||
let client = self.clients.get_mut(&client_id).unwrap();
|
||||
client
|
||||
.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);
|
||||
}
|
||||
AshmemResponse::Id(id) => {
|
||||
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) => {
|
||||
let client = self.clients.get_mut(&client_id).unwrap();
|
||||
client
|
||||
.stream
|
||||
.send_fds(&refcount.to_string().as_bytes(), &[])?;
|
||||
.send_fds(refcount.to_string().as_bytes(), &[])?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
@ -327,7 +327,7 @@ pub struct XkcdRand {
|
||||
#[cfg(test)]
|
||||
impl Rand for XkcdRand {
|
||||
fn set_seed(&mut self, val: u64) {
|
||||
self.val = val
|
||||
self.val = val;
|
||||
}
|
||||
|
||||
fn next(&mut self) -> u64 {
|
||||
|
@ -248,7 +248,7 @@ where
|
||||
|
||||
impl<T: ShMemProvider> Drop for RcShMem<T> {
|
||||
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) {
|
||||
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> {
|
||||
|
@ -50,7 +50,13 @@ where
|
||||
fn add(&mut self, mut testcase: Testcase<I>) -> Result<usize, Error> {
|
||||
if testcase.filename().is_none() {
|
||||
// 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");
|
||||
testcase.set_filename(filename_str.into());
|
||||
};
|
||||
|
@ -10,7 +10,7 @@ use core::ptr::{addr_of, read_volatile};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use crate::bolts::{
|
||||
llmp::{LlmpClient, LlmpReceiver},
|
||||
llmp::{LlmpClient, LlmpConnection, LlmpReceiver},
|
||||
shmem::StdShMemProvider,
|
||||
};
|
||||
|
||||
@ -19,7 +19,7 @@ use std::net::{SocketAddr, ToSocketAddrs};
|
||||
|
||||
use crate::{
|
||||
bolts::{
|
||||
llmp::{self, Flags, LlmpClientDescription, LlmpConnection, LlmpSender, Tag},
|
||||
llmp::{self, Flags, LlmpClientDescription, LlmpSender, Tag},
|
||||
shmem::ShMemProvider,
|
||||
},
|
||||
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.
|
||||
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()`].
|
||||
#[cfg(feature = "std")]
|
||||
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
|
||||
@ -510,7 +510,7 @@ where
|
||||
S: DeserializeOwned,
|
||||
SP: ShMemProvider,
|
||||
{
|
||||
let tuple: (S, _) = postcard::from_bytes(&state_corpus_serialized)?;
|
||||
let tuple: (S, _) = postcard::from_bytes(state_corpus_serialized)?;
|
||||
Ok((
|
||||
tuple.0,
|
||||
LlmpEventManager::existing_client_from_description(shmem_provider, &tuple.1)?,
|
||||
@ -558,13 +558,15 @@ where
|
||||
/// Otherwise, the OS may already have removed the shared maps,
|
||||
#[inline]
|
||||
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.
|
||||
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
|
||||
unsafe { self.sender.reset() };
|
||||
unsafe {
|
||||
self.sender.reset();
|
||||
}
|
||||
let state_corpus_serialized = serialize_state_mgr(state, &self.llmp_mgr)?;
|
||||
self.sender
|
||||
.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
|
||||
const _ENV_FUZZER_SENDER: &str = &"_AFL_ENV_FUZZER_SENDER";
|
||||
const _ENV_FUZZER_RECEIVER: &str = &"_AFL_ENV_FUZZER_RECEIVER";
|
||||
const _ENV_FUZZER_SENDER: &str = "_AFL_ENV_FUZZER_SENDER";
|
||||
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)
|
||||
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>
|
||||
where
|
||||
@ -881,13 +883,15 @@ where
|
||||
Some((_sender, _tag, msg)) => {
|
||||
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>) =
|
||||
deserialize_state_mgr(new_shmem_provider, &msg)?;
|
||||
deserialize_state_mgr(new_shmem_provider, msg)?;
|
||||
|
||||
(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.
|
||||
unsafe { mgr.sender_mut().reset() };
|
||||
unsafe {
|
||||
mgr.sender_mut().reset();
|
||||
}
|
||||
/* TODO: Not sure if this is needed
|
||||
// We commit an empty NO_RESTART message to this buf, against infinite loops,
|
||||
// in case something crashes in the fuzzer.
|
||||
|
@ -346,7 +346,7 @@ where
|
||||
|
||||
self.executor
|
||||
.out_file_mut()
|
||||
.write_buf(&input.target_bytes().as_slice());
|
||||
.write_buf(input.target_bytes().as_slice());
|
||||
|
||||
let send_len = self
|
||||
.executor
|
||||
@ -505,7 +505,7 @@ where
|
||||
let mut exit_kind = ExitKind::Ok;
|
||||
|
||||
// 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
|
||||
.forkserver
|
||||
|
@ -208,7 +208,7 @@ where
|
||||
/// Retrieve the harness function.
|
||||
#[inline]
|
||||
pub fn harness(&self) -> &H {
|
||||
&self.harness_fn
|
||||
self.harness_fn
|
||||
}
|
||||
|
||||
/// Retrieve the harness function for a mutable reference.
|
||||
@ -286,7 +286,7 @@ mod unix_signal_handler {
|
||||
let data = &mut GLOBAL_STATE;
|
||||
match signal {
|
||||
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),
|
||||
}
|
||||
@ -342,7 +342,7 @@ mod unix_signal_handler {
|
||||
|
||||
let interesting = fuzzer
|
||||
.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.");
|
||||
|
||||
if interesting {
|
||||
@ -433,7 +433,6 @@ mod unix_signal_handler {
|
||||
}
|
||||
|
||||
// TODO tell the parent to not restart
|
||||
libc::_exit(1);
|
||||
} else {
|
||||
let state = (data.state_ptr as *mut S).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
|
||||
.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.");
|
||||
|
||||
if interesting {
|
||||
@ -512,9 +511,9 @@ mod unix_signal_handler {
|
||||
event_mgr.await_restart_safe();
|
||||
#[cfg(feature = "std")]
|
||||
println!("Bye!");
|
||||
|
||||
libc::_exit(1);
|
||||
}
|
||||
|
||||
libc::_exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,7 +62,7 @@ where
|
||||
let start_time = crate::cpu::read_time_counter();
|
||||
|
||||
// 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
|
||||
let elapsed = crate::cpu::read_time_counter() - start_time;
|
||||
@ -316,7 +316,7 @@ where
|
||||
manager,
|
||||
input,
|
||||
observers,
|
||||
&exit_kind,
|
||||
exit_kind,
|
||||
feedback_stats,
|
||||
feedback_index,
|
||||
)?;
|
||||
@ -326,7 +326,7 @@ where
|
||||
manager,
|
||||
input,
|
||||
observers,
|
||||
&exit_kind,
|
||||
exit_kind,
|
||||
feedback_stats,
|
||||
feedback_index + 1,
|
||||
)?;
|
||||
@ -387,7 +387,7 @@ where
|
||||
manager,
|
||||
input,
|
||||
observers,
|
||||
&exit_kind,
|
||||
exit_kind,
|
||||
feedback_stats,
|
||||
feedback_index,
|
||||
)?;
|
||||
@ -401,7 +401,7 @@ where
|
||||
manager,
|
||||
input,
|
||||
observers,
|
||||
&exit_kind,
|
||||
exit_kind,
|
||||
feedback_stats,
|
||||
feedback_index + 1,
|
||||
)
|
||||
@ -458,7 +458,7 @@ where
|
||||
manager,
|
||||
input,
|
||||
observers,
|
||||
&exit_kind,
|
||||
exit_kind,
|
||||
feedback_stats,
|
||||
feedback_index,
|
||||
)?;
|
||||
@ -468,7 +468,7 @@ where
|
||||
manager,
|
||||
input,
|
||||
observers,
|
||||
&exit_kind,
|
||||
exit_kind,
|
||||
feedback_stats,
|
||||
feedback_index + 1,
|
||||
)?;
|
||||
@ -529,7 +529,7 @@ where
|
||||
manager,
|
||||
input,
|
||||
observers,
|
||||
&exit_kind,
|
||||
exit_kind,
|
||||
feedback_stats,
|
||||
feedback_index,
|
||||
)?;
|
||||
@ -543,7 +543,7 @@ where
|
||||
manager,
|
||||
input,
|
||||
observers,
|
||||
&exit_kind,
|
||||
exit_kind,
|
||||
feedback_stats,
|
||||
feedback_index + 1,
|
||||
)
|
||||
|
@ -541,7 +541,7 @@ where
|
||||
start_timer!(state);
|
||||
let is_solution = self
|
||||
.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);
|
||||
|
||||
if is_solution {
|
||||
@ -564,7 +564,7 @@ where
|
||||
let is_interesting = self.feedback_mut().is_interesting_with_perf(
|
||||
state,
|
||||
event_mgr,
|
||||
&input,
|
||||
input,
|
||||
observers,
|
||||
&exit_kind,
|
||||
&mut feedback_stats,
|
||||
|
@ -1,7 +1,10 @@
|
||||
//! 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)
|
||||
|
||||
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 serde::{Deserialize, Serialize};
|
||||
#[cfg(feature = "std")]
|
||||
@ -48,6 +51,13 @@ impl Input for BytesInput {
|
||||
file.read_to_end(&mut 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
|
||||
|
@ -3,7 +3,10 @@
|
||||
pub mod bytes;
|
||||
pub use bytes::BytesInput;
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use alloc::{
|
||||
string::{String, ToString},
|
||||
vec::Vec,
|
||||
};
|
||||
use core::{clone::Clone, fmt::Debug};
|
||||
#[cfg(feature = "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> {
|
||||
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.
|
||||
#[derive(Copy, Clone, Serialize, Deserialize, Debug)]
|
||||
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 {
|
||||
fn target_bytes(&self) -> OwnedSlice<u8> {
|
||||
OwnedSlice::Owned(vec![0])
|
||||
|
@ -25,7 +25,9 @@ pub fn buffer_self_copy(data: &mut [u8], from: usize, to: usize, len: usize) {
|
||||
debug_assert!(to + len <= data.len());
|
||||
if len != 0 && from != to {
|
||||
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 src_ptr = src.as_ptr();
|
||||
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) {
|
||||
debug_assert!(from + len <= data.len());
|
||||
for p in &mut data[from..(from + len)] {
|
||||
*p = val
|
||||
*p = val;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1406,7 +1410,7 @@ where
|
||||
let other = other_testcase.load_input()?;
|
||||
input
|
||||
.bytes_mut()
|
||||
.splice(split_at.., other.bytes()[split_at..].iter().cloned());
|
||||
.splice(split_at.., other.bytes()[split_at..].iter().copied());
|
||||
|
||||
Ok(MutationResult::Mutated)
|
||||
}
|
||||
|
@ -338,7 +338,7 @@ where
|
||||
let mut log = Vec::<String>::new();
|
||||
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
|
||||
log.push(name)
|
||||
log.push(name);
|
||||
}
|
||||
let meta = LogMutationMetadata::new(log);
|
||||
testcase.add_metadata(meta);
|
||||
@ -471,7 +471,7 @@ mod tests {
|
||||
|
||||
// The pre-seeded rand should have spliced at position 2.
|
||||
// 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]
|
||||
|
@ -40,7 +40,7 @@ impl CmpValues {
|
||||
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::U64(t) => Some(*t),
|
||||
_ => None,
|
||||
CmpValues::Bytes(_) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ where
|
||||
|
||||
#[inline]
|
||||
fn set_initial(&mut self, initial: T) {
|
||||
self.initial = initial
|
||||
self.initial = initial;
|
||||
}
|
||||
}
|
||||
|
||||
@ -249,7 +249,7 @@ where
|
||||
|
||||
#[inline]
|
||||
fn set_initial(&mut self, initial: T) {
|
||||
self.initial = initial
|
||||
self.initial = initial;
|
||||
}
|
||||
}
|
||||
|
||||
@ -371,7 +371,7 @@ where
|
||||
|
||||
#[inline]
|
||||
fn set_initial(&mut self, initial: T) {
|
||||
self.initial = initial
|
||||
self.initial = initial;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -320,7 +320,7 @@ where
|
||||
}
|
||||
|
||||
fn set_max_size(&mut self, max_size: usize) {
|
||||
self.max_size = max_size
|
||||
self.max_size = max_size;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -190,7 +190,7 @@ pub trait Stats {
|
||||
self.client_stats_mut().push(ClientStats {
|
||||
last_window_time: current_time(),
|
||||
..ClientStats::default()
|
||||
})
|
||||
});
|
||||
}
|
||||
&mut self.client_stats_mut()[client_id as usize]
|
||||
}
|
||||
@ -512,7 +512,7 @@ impl ClientPerfStats {
|
||||
let elapsed = self.mark_time();
|
||||
|
||||
// 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
|
||||
|
@ -86,7 +86,7 @@ impl AsanErrors {
|
||||
|
||||
/// Clears this `AsanErrors` struct
|
||||
pub fn clear(&mut self) {
|
||||
self.errors.clear()
|
||||
self.errors.clear();
|
||||
}
|
||||
|
||||
/// Gets the amount of `AsanErrors` in this struct
|
||||
@ -122,7 +122,7 @@ impl AsanErrors {
|
||||
.add_frame_filter(Box::new(|frames| {
|
||||
frames.retain(
|
||||
|x| matches!(&x.name, Some(n) if !n.starts_with("libafl_frida::asan_rt::")),
|
||||
)
|
||||
);
|
||||
}));
|
||||
|
||||
#[allow(clippy::non_ascii_literal)]
|
||||
|
@ -148,7 +148,7 @@ impl AsanRuntime {
|
||||
|
||||
/// Check if the test leaked any memory and report it if so.
|
||||
pub fn check_for_leaks(&mut self) {
|
||||
self.allocator.check_for_leaks()
|
||||
self.allocator.check_for_leaks();
|
||||
}
|
||||
|
||||
/// 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.
|
||||
#[allow(clippy::unused_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
|
||||
@ -212,7 +212,7 @@ impl AsanRuntime {
|
||||
};
|
||||
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
|
||||
@ -225,7 +225,7 @@ impl AsanRuntime {
|
||||
};
|
||||
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
|
||||
@ -238,7 +238,9 @@ impl AsanRuntime {
|
||||
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();
|
||||
// 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 end = start + range_details.memory_range().size();
|
||||
@ -1871,7 +1873,7 @@ impl AsanRuntime {
|
||||
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 (mut base_reg, mut index_reg, displacement) =
|
||||
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;
|
||||
}
|
||||
|
||||
#[allow(clippy::clippy::cast_possible_wrap)]
|
||||
#[allow(clippy::cast_possible_wrap)]
|
||||
let mut fault_address =
|
||||
(self.regs[base_reg as usize] as isize + displacement as isize) as usize;
|
||||
|
||||
if index_reg == 0 {
|
||||
index_reg = 0xffff
|
||||
index_reg = 0xffff;
|
||||
} else {
|
||||
if capstone::arch::arm64::Arm64Reg::ARM64_REG_X0 as u16 <= index_reg
|
||||
&& index_reg <= capstone::arch::arm64::Arm64Reg::ARM64_REG_X28 as u16
|
||||
@ -1996,7 +1998,7 @@ impl AsanRuntime {
|
||||
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) {
|
||||
let shadow_bit = self.allocator.shadow_bit();
|
||||
let mut ops = dynasmrt::VecAssembler::<dynasmrt::aarch64::Aarch64Relocation>::new(0);
|
||||
|
@ -224,7 +224,7 @@ fn pc(context: &CpuContext) -> usize {
|
||||
/// The implementation of the [`FridaInstrumentationHelper`]
|
||||
impl<'a> FridaInstrumentationHelper<'a> {
|
||||
/// Constructor function to create a new [`FridaInstrumentationHelper`], given a `module_name`.
|
||||
#[allow(clippy::clippy::too_many_lines)]
|
||||
#[allow(clippy::too_many_lines)]
|
||||
#[must_use]
|
||||
pub fn new(
|
||||
gum: &'a Gum,
|
||||
@ -325,7 +325,7 @@ impl<'a> FridaInstrumentationHelper<'a> {
|
||||
helper
|
||||
.drcov_basic_blocks
|
||||
.push(DrCovBasicBlock::new(real_address, real_address + 4));
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -370,7 +370,7 @@ impl<'a> FridaInstrumentationHelper<'a> {
|
||||
);
|
||||
}
|
||||
}
|
||||
instruction.keep()
|
||||
instruction.keep();
|
||||
}
|
||||
});
|
||||
helper.transformer = Some(transformer);
|
||||
@ -386,7 +386,7 @@ impl<'a> FridaInstrumentationHelper<'a> {
|
||||
|
||||
#[inline]
|
||||
fn options(&self) -> &FridaOptions {
|
||||
&self.options
|
||||
self.options
|
||||
}
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
#[inline]
|
||||
@ -1118,7 +1118,6 @@ impl<'a> FridaInstrumentationHelper<'a> {
|
||||
}
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
{
|
||||
println!("here");
|
||||
writer.put_lea_reg_reg_offset(X86Register::Rsp, X86Register::Rsp, -(redzone_size));
|
||||
writer.put_push_reg(X86Register::Rdi);
|
||||
writer.put_mov_reg_address(
|
||||
|
@ -19,10 +19,16 @@ fn main() {
|
||||
let mut sancov_cmp = cc::Build::new();
|
||||
|
||||
#[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")]
|
||||
sancov_cmp.define("SANCOV_CMPLOG", "1");
|
||||
{
|
||||
sancov_cmp.define("SANCOV_CMPLOG", "1");
|
||||
println!("cargo:rerun-if-changed=src/cmplog.h");
|
||||
}
|
||||
|
||||
sancov_cmp
|
||||
.file(_src_dir.join("sancov_cmp.c"))
|
||||
|
@ -15,7 +15,7 @@ extern "C" {
|
||||
/// # Safety
|
||||
/// Calls the libfuzzer-style init function which is native code.
|
||||
#[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 {
|
||||
let argv: Vec<*const u8> = args.iter().map(|x| x.as_bytes().as_ptr()).collect();
|
||||
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
|
||||
/// # Safety
|
||||
/// 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 {
|
||||
unsafe { LLVMFuzzerTestOneInput(buf.as_ptr(), buf.len()) }
|
||||
}
|
||||
|
@ -8,43 +8,6 @@
|
||||
#include "cmplog.h"
|
||||
#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) {
|
||||
|
||||
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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user