Merge branch 'main' of github.com:AFLplusplus/libAFLrs into main

This commit is contained in:
Andrea Fioraldi 2020-12-10 09:13:24 +01:00
commit 6dfe253bb9
9 changed files with 291 additions and 148 deletions

View File

@ -33,4 +33,4 @@ num = "*"
xxhash-rust = { version = "0.8.0", features = ["xxh3"] } # xxh3 hashing for rust xxhash-rust = { version = "0.8.0", features = ["xxh3"] } # xxh3 hashing for rust
serde = { version = "1.0", default-features = false, features = ["alloc"] } # serialization lib serde = { version = "1.0", default-features = false, features = ["alloc"] } # serialization lib
erased-serde = "0.3.12" erased-serde = "0.3.12"
postcard = "0.5.1" # no_std compatible serde serialization fromat postcard = { version = "0.5.1", features = ["alloc"] } # no_std compatible serde serialization fromat

View File

@ -1,14 +1,22 @@
//! Compare the speed of rand implementations //! Compare the speed of rand implementations
use afl::utils::{Rand, XorShift64Rand, Xoshiro256StarRand}; use afl::utils::{
Lehmer64Rand, Rand, RomuDuoJrRand, RomuTrioRand, XorShift64Rand, Xoshiro256StarRand,
};
use criterion::{black_box, criterion_group, criterion_main, Criterion}; use criterion::{black_box, criterion_group, criterion_main, Criterion};
fn criterion_benchmark(c: &mut Criterion) { fn criterion_benchmark(c: &mut Criterion) {
let mut xorshift = XorShift64Rand::new(0); let mut xorshift = XorShift64Rand::new(1);
let mut xoshiro = Xoshiro256StarRand::new(0); let mut xoshiro = Xoshiro256StarRand::new(1);
let mut romu = RomuDuoJrRand::new(1);
let mut lehmer = Lehmer64Rand::new(1);
let mut romu_trio = RomuTrioRand::new(1);
c.bench_function("xorshift", |b| b.iter(|| black_box(xorshift.next()))); c.bench_function("xorshift", |b| b.iter(|| black_box(xorshift.next())));
c.bench_function("xoshiro", |b| b.iter(|| black_box(xoshiro.next()))); c.bench_function("xoshiro", |b| b.iter(|| black_box(xoshiro.next())));
c.bench_function("romu", |b| b.iter(|| black_box(romu.next())));
c.bench_function("romu_trio", |b| b.iter(|| black_box(romu_trio.next())));
c.bench_function("lehmer", |b| b.iter(|| black_box(lehmer.next())));
} }
criterion_group!(benches, criterion_benchmark); criterion_group!(benches, criterion_benchmark);

View File

@ -301,7 +301,8 @@ where
let cur = current_milliseconds(); let cur = current_milliseconds();
if cur - last > 60 * 100 { if cur - last > 60 * 100 {
last = cur; last = cur;
manager.fire(Event::update_stats(state.executions(), state.executions_over_seconds()), manager.fire(
Event::update_stats(state.executions(), state.executions_over_seconds()),
state, state,
corpus, corpus,
)?; // TODO self.new_execs}); )?; // TODO self.new_execs});

View File

@ -865,6 +865,11 @@ impl LlmpBroker {
} }
})) }))
} }
/// Broadcasts the given buf to all lients
fn send_buf(&mut self, tag: u32, buf: &[u8]) -> Result<(), AflError> {
self.llmp_out.send_buf(tag, buf)
}
} }
/// `n` clients connect to a broker. They share an outgoing map with the broker, /// `n` clients connect to a broker. They share an outgoing map with the broker,

View File

@ -1,89 +0,0 @@
use core::marker::PhantomData;
use core::ptr;
use std::{ffi::c_void, io::Read, io::Write, net::TcpListener};
use crate::{
corpus::Corpus, engines::State, executors::Executor, inputs::Input, utils::Rand, AflError,
};
use super::{
llmp_translated::{LlmpBroker, LlmpClient, LlmpClientloopFn, LlmpMsgHookFn},
Event, EventManager,
};
/// Eventmanager for multi-processed application
#[cfg(feature = "std")]
pub struct LLMPEventManager<C, E, I, R>
where
C: Corpus<I, R>,
I: Input,
E: Executor<I>,
R: Rand,
//CE: CustomEvent<C, E, I, R>,
{
// TODO...
phantom: PhantomData<(C, E, I, R)>,
is_broker: bool,
}
#[cfg(feature = "std")]
impl<C, E, I, R> EventManager<C, E, I, R> for LLMPEventManager<C, E, I, R>
where
C: Corpus<I, R>,
E: Executor<I>,
I: Input,
R: Rand,
//CE: CustomEvent<C, E, I, R>,
{
fn enabled(&self) -> bool {
true
}
fn fire(&mut self, _event: Event<C, E, I, R>) -> Result<(), AflError> {
//self.events.push(event);
// TODO: Serde serialize, llmp send
Ok(())
}
fn process(&mut self, _state: &mut State<I, R>, _corpus: &mut C) -> Result<usize, AflError> {
// TODO: iterators
/*
let mut handled = vec![];
for x in self.events.iter() {
handled.push(x.handle_in_broker(state, corpus)?);
}
handled
.iter()
.zip(self.events.iter())
.map(|(x, event)| match x {
BrokerEventResult::Forward => event.handle_in_client(state, corpus),
// Ignore broker-only events
BrokerEventResult::Handled => Ok(()),
})
.for_each(drop);
let count = self.events.len();
dbg!("Handled {} events", count);
self.events.clear();
let num = self.events.len();
for event in &self.events {}
self.events.clear();
*/
Ok(0)
}
}
#[cfg(feature = "std")]
impl<C, E, I, R> LLMPEventManager<C, E, I, R>
where
C: Corpus<I, R>,
I: Input,
E: Executor<I>,
R: Rand,
{
}

View File

@ -1,19 +1,16 @@
//#[cfg(feature = "std")] #[cfg(feature = "std")]
//pub mod llmp; mod llmp;
#[cfg(feature = "std")]
pub mod shmem_translated;
use alloc::string::String; use alloc::string::String;
use core::marker::PhantomData; use core::marker::PhantomData;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
//#[cfg(feature = "std")]
//pub mod llmp_translated; // TODO: Abstract away.
//#[cfg(feature = "std")] //#[cfg(feature = "std")]
//pub mod shmem_translated; //pub mod shmem_translated;
//#[cfg(feature = "std")]
//pub use crate::events::llmp::LLMPEventManager;
#[cfg(feature = "std")] #[cfg(feature = "std")]
use std::io::Write; use std::io::Write;
@ -33,9 +30,7 @@ pub enum BrokerEventResult {
Forward, Forward,
} }
pub trait ShowStats { pub trait ShowStats {}
}
/* /*
@ -192,10 +187,6 @@ where
I: Input, I: Input,
R: Rand, R: Rand,
{ {
/// Check if this EventaManager support a given Event type
/// To compare events, use Event::name().as_ptr()
fn enabled(&self) -> bool;
/// Fire an Event /// Fire an Event
fn fire<'a>( fn fire<'a>(
&mut self, &mut self,
@ -330,10 +321,6 @@ where
W: Write, W: Write,
//CE: CustomEvent<C, E, I, R>, //CE: CustomEvent<C, E, I, R>,
{ {
fn enabled(&self) -> bool {
true
}
fn fire<'a>( fn fire<'a>(
&mut self, &mut self,
event: Event<'a, C, E, I, R>, event: Event<'a, C, E, I, R>,
@ -373,3 +360,169 @@ where
} }
} }
} }
/// Eventmanager for multi-processed application
#[cfg(feature = "std")]
pub struct LlmpBrokerEventManager<C, E, I, R>
where
C: Corpus<I, R>,
I: Input,
E: Executor<I>,
R: Rand,
//CE: CustomEvent<C, E, I, R>,
{
llmp_broker: llmp::LlmpBroker,
phantom: PhantomData<(C, E, I, R)>,
}
/// Eventmanager for multi-processed application
#[cfg(feature = "std")]
pub struct LlmpClientEventManager<C, E, I, R>
where
C: Corpus<I, R>,
I: Input,
E: Executor<I>,
R: Rand,
//CE: CustomEvent<C, E, I, R>,
{
llmp_client: llmp::LlmpClient,
phantom: PhantomData<(C, E, I, R)>,
}
#[cfg(feature = "std")]
impl<C, E, I, R> EventManager<C, E, I, R> for LlmpBrokerEventManager<C, E, I, R>
where
C: Corpus<I, R>,
E: Executor<I>,
I: Input,
R: Rand,
//CE: CustomEvent<C, E, I, R>,
{
/// Fire an Event
fn fire<'a>(
&mut self,
event: Event<'a, C, E, I, R>,
state: &mut State<I, R>,
corpus: &mut C,
) -> Result<(), AflError> {
// TODO let serialized = postcard::to_vec(&event)?;
// self.llmp_broker.send_buf(&serialized)?;
Ok(())
}
fn process(&mut self, _state: &mut State<I, R>, _corpus: &mut C) -> Result<usize, AflError> {
// TODO: iterators
/*
let mut handled = vec![];
for x in self.events.iter() {
handled.push(x.handle_in_broker(state, corpus)?);
}
handled
.iter()
.zip(self.events.iter())
.map(|(x, event)| match x {
BrokerEventResult::Forward => event.handle_in_client(state, corpus),
// Ignore broker-only events
BrokerEventResult::Handled => Ok(()),
})
.for_each(drop);
let count = self.events.len();
dbg!("Handled {} events", count);
self.events.clear();
let num = self.events.len();
for event in &self.events {}
self.events.clear();
*/
Ok(0)
}
fn on_recv(&self, _state: &mut State<I, R>, _corpus: &mut C) -> Result<(), AflError> {
// TODO: Better way to move out of testcase, or get ref
//Ok(corpus.add(self.testcase.take().unwrap()))
Ok(())
}
fn handle_in_broker(
&self,
event: &Event<C, E, I, R>,
/*broker: &dyn EventManager<C, E, I, R>,*/ _state: &mut State<I, R>,
_corpus: &mut C,
) -> Result<BrokerEventResult, AflError> {
match event {
Event::LoadInitial {
sender_id: _,
phantom: _,
} => Ok(BrokerEventResult::Handled),
Event::NewTestcase {
sender_id: _,
input: _,
observers: _,
} => Ok(BrokerEventResult::Forward),
Event::UpdateStats {
sender_id: _,
executions: _,
execs_over_sec: _,
phantom: _,
} => {
// TODO
Ok(BrokerEventResult::Handled)
}
Event::Crash {
sender_id: _,
input: _,
phantom: _,
} => Ok(BrokerEventResult::Handled),
Event::Timeout {
sender_id: _,
input: _,
phantom: _,
} => {
// TODO
Ok(BrokerEventResult::Handled)
}
Event::Log {
sender_id,
severity_level,
message,
phantom: _,
} => {
//TODO: broker.log()
#[cfg(feature = "std")]
println!("{}[{}]: {}", sender_id, severity_level, message);
Ok(BrokerEventResult::Handled)
},
Event::None {
phantom: _,
} => Ok(BrokerEventResult::Handled)
//Event::Custom {sender_id, custom_event} => custom_event.handle_in_broker(state, corpus),
//_ => Ok(BrokerEventResult::Forward),
}
}
fn handle_in_client(
&self,
event: Event<C, E, I, R>,
/*client: &dyn EventManager<C, E, I, R>,*/ _state: &mut State<I, R>,
corpus: &mut C,
) -> Result<(), AflError> {
match event {
Event::NewTestcase {
sender_id: _,
input: _,
observers: _,
} => {
// here u should match sender_id, if equal to the current one do not re-execute
// we need to pass engine to process() too, TODO
#[cfg(feature = "std")]
println!("PLACEHOLDER: received NewTestcase");
Ok(())
}
_ => Err(AflError::Unknown(
"Received illegal message that message should not have arrived.".into(),
)),
}
}
}

View File

@ -180,11 +180,7 @@ unsafe fn afl_shmem_init(shm: *mut AflShmem, map_size: usize) -> *mut c_uchar {
} }
/// Uses a shmap id string to open a shared map /// Uses a shmap id string to open a shared map
unsafe fn afl_shmem_by_str( unsafe fn afl_shmem_by_str(shm: *mut AflShmem, shm_str: &CStr, map_size: usize) -> *mut c_uchar {
shm: *mut AflShmem,
shm_str: &CStr,
map_size: usize,
) -> *mut c_uchar {
if shm.is_null() || shm_str.to_bytes().len() == 0 || map_size == 0 { if shm.is_null() || shm_str.to_bytes().len() == 0 || map_size == 0 {
return 0 as *mut c_uchar; return 0 as *mut c_uchar;
} }

View File

@ -300,4 +300,3 @@ where
} }
} }
*/ */

View File

@ -9,14 +9,16 @@ use xxhash_rust::xxh3::xxh3_64_with_seed;
#[cfg(feature = "std")] #[cfg(feature = "std")]
use std::time::{SystemTime, UNIX_EPOCH}; use std::time::{SystemTime, UNIX_EPOCH};
pub type StdRand = Xoshiro256StarRand; pub type StdRand = RomuTrioRand;
/// Ways to get random around here /// Ways to get random around here
pub trait Rand: Debug { pub trait Rand: Debug {
// Sets the seed of this Rand // Sets the seed of this Rand
fn set_seed(&mut self, seed: u64); fn set_seed(&mut self, seed: u64);
// Gets the next 64 bit value // Gets the next 64 bit value
fn next(&mut self) -> u64; fn next(&mut self) -> u64;
// Gets a value below the given 64 bit val (inclusive) // Gets a value below the given 64 bit val (inclusive)
fn below(&mut self, upper_bound_excl: u64) -> u64 { fn below(&mut self, upper_bound_excl: u64) -> u64 {
if upper_bound_excl <= 1 { if upper_bound_excl <= 1 {
@ -73,6 +75,15 @@ where
const HASH_CONST: u64 = 0xa5b35705; const HASH_CONST: u64 = 0xa5b35705;
#[cfg(feature = "std")]
/// Gets current nanoseconds since UNIX_EPOCH
pub fn current_nanos() -> u64 {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_nanos() as u64
}
/// XXH3 Based, hopefully speedy, rnd implementation /// XXH3 Based, hopefully speedy, rnd implementation
/// ///
#[derive(Copy, Clone, Debug, Default)] #[derive(Copy, Clone, Debug, Default)]
@ -91,6 +102,7 @@ impl Rand for Xoshiro256StarRand {
self.seeded = true; self.seeded = true;
} }
#[inline]
fn next(&mut self) -> u64 { fn next(&mut self) -> u64 {
let ret: u64 = self.rand_seed[0] let ret: u64 = self.rand_seed[0]
.wrapping_add(self.rand_seed[3]) .wrapping_add(self.rand_seed[3])
@ -125,19 +137,11 @@ impl Xoshiro256StarRand {
ret ret
} }
pub fn to_rc_refcell(self) -> Rc<RefCell<Self>> {
self.into()
}
/// Creates a rand instance, pre-seeded with the current time in nanoseconds. /// Creates a rand instance, pre-seeded with the current time in nanoseconds.
/// Needs stdlib timer /// Needs stdlib timer
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub fn preseeded() -> Self { pub fn preseeded() -> Self {
let seed = SystemTime::now() Self::new(current_nanos())
.duration_since(UNIX_EPOCH)
.unwrap()
.as_nanos() as u64;
Self::new(seed)
} }
} }
@ -155,6 +159,7 @@ impl Rand for XorShift64Rand {
self.seeded = true; self.seeded = true;
} }
#[inline]
fn next(&mut self) -> u64 { fn next(&mut self) -> u64 {
let mut x = self.rand_seed; let mut x = self.rand_seed;
x ^= x << 13; x ^= x << 13;
@ -179,19 +184,11 @@ impl XorShift64Rand {
ret ret
} }
pub fn to_rc_refcell(self) -> Rc<RefCell<Self>> {
self.into()
}
/// Creates a rand instance, pre-seeded with the current time in nanoseconds. /// Creates a rand instance, pre-seeded with the current time in nanoseconds.
/// Needs stdlib timer /// Needs stdlib timer
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub fn preseeded() -> Self { pub fn preseeded() -> Self {
let seed = SystemTime::now() Self::new(current_nanos())
.duration_since(UNIX_EPOCH)
.unwrap()
.as_nanos() as u64;
Self::new(seed)
} }
} }
@ -209,6 +206,7 @@ impl Rand for Lehmer64Rand {
self.seeded = true; self.seeded = true;
} }
#[inline]
fn next(&mut self) -> u64 { fn next(&mut self) -> u64 {
self.rand_seed *= 0xda942042e4dd58b5; self.rand_seed *= 0xda942042e4dd58b5;
return (self.rand_seed >> 64) as u64; return (self.rand_seed >> 64) as u64;
@ -222,26 +220,98 @@ impl Into<Rc<RefCell<Self>>> for Lehmer64Rand {
} }
impl Lehmer64Rand { impl Lehmer64Rand {
/// Creates a new Xoshiro rand with the given seed /// Creates a new Lehmer rand with the given seed
pub fn new(seed: u64) -> Self { pub fn new(seed: u64) -> Self {
let mut ret: Self = Default::default(); let mut ret: Self = Default::default();
ret.set_seed(seed); // TODO: Proper random seed? ret.set_seed(seed);
ret ret
} }
pub fn to_rc_refcell(self) -> Rc<RefCell<Self>> {
self.into()
}
/// Creates a rand instance, pre-seeded with the current time in nanoseconds. /// Creates a rand instance, pre-seeded with the current time in nanoseconds.
/// Needs stdlib timer /// Needs stdlib timer
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub fn preseeded() -> Self { pub fn preseeded() -> Self {
let seed = SystemTime::now() Self::new(current_nanos())
.duration_since(UNIX_EPOCH) }
.unwrap() }
.as_nanos() as u64;
Self::new(seed) /// Extremely quick rand implementation
/// see https://arxiv.org/pdf/2002.11331.pdf
#[derive(Copy, Clone, Debug, Default)]
pub struct RomuTrioRand {
x_state: u64,
y_state: u64,
z_state: u64,
}
impl RomuTrioRand {
pub fn new(seed: u64) -> Self {
let mut rand = Self::default();
rand.set_seed(seed);
rand
}
/// Creates a rand instance, pre-seeded with the current time in nanoseconds.
/// Needs stdlib timer
#[cfg(feature = "std")]
pub fn preseeded() -> Self {
Self::new(current_nanos())
}
}
impl Rand for RomuTrioRand {
fn set_seed(&mut self, seed: u64) {
self.x_state = seed ^ 0x12345;
self.y_state = seed ^ 0x6789A;
self.z_state = seed ^ 0xBCDEF;
}
#[inline]
fn next(&mut self) -> u64 {
let xp = self.x_state;
let yp = self.y_state;
let zp = self.z_state;
self.x_state = 15241094284759029579u64.wrapping_mul(zp);
self.y_state = yp.wrapping_sub(xp).rotate_left(12);
self.z_state = zp.wrapping_sub(yp).rotate_left(44);
xp
}
}
/// see https://arxiv.org/pdf/2002.11331.pdf
#[derive(Copy, Clone, Debug, Default)]
pub struct RomuDuoJrRand {
x_state: u64,
y_state: u64,
}
impl RomuDuoJrRand {
pub fn new(seed: u64) -> Self {
let mut rand = Self::default();
rand.set_seed(seed);
rand
}
/// Creates a rand instance, pre-seeded with the current time in nanoseconds.
/// Needs stdlib timer
#[cfg(feature = "std")]
pub fn preseeded() -> Self {
Self::new(current_nanos())
}
}
impl Rand for RomuDuoJrRand {
fn set_seed(&mut self, seed: u64) {
self.x_state = seed ^ 0x12345;
self.y_state = seed ^ 0x6789A;
}
#[inline]
fn next(&mut self) -> u64 {
let xp = self.x_state;
self.x_state = 15241094284759029579u64.wrapping_mul(self.y_state);
self.y_state = self.y_state.wrapping_sub(xp).rotate_left(27);
xp
} }
} }