trying to get things to work

This commit is contained in:
Dominik Maier 2021-01-04 14:06:43 +01:00
parent bade18eaf3
commit da5ffd6c14
13 changed files with 210 additions and 68 deletions

View File

@ -29,9 +29,10 @@ opt-level = 3
debug = true
[features]
default = ["std"]
default = ["std", "anymapdbg"]
std = [] # print, sharedmap, ... support
runtime = [] # a runtime for clang inmem-executor
anymapdbg = [] # uses serde_json to Debug the anymap trait. Disable for smaller footprint.
[[example]]
name = "llmp_test"
@ -48,4 +49,5 @@ serde = { version = "1.0", default-features = false, features = ["alloc"] } # se
erased-serde = "0.3.12"
postcard = { version = "0.5.1", features = ["alloc"] } # no_std compatible serde serialization fromat
static_assertions = "1.1.0"
serde_json = { version = "1.0", default-features = false, features = ["alloc"] } # an easy way to debug print SerdeAnyMap
#TODO: for llmp brotli = { version = "3.3.0", default-features = false } # brotli compression

View File

@ -119,7 +119,7 @@ where
}
/// A corpus handling all important fuzzing in memory.
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(bound = "I: serde::de::DeserializeOwned")]
pub struct InMemoryCorpus<I, R>
where
@ -185,7 +185,7 @@ where
/// A corpus able to store testcases to dis, and load them from disk, when they are being used.
#[cfg(feature = "std")]
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(bound = "I: serde::de::DeserializeOwned")]
pub struct OnDiskCorpus<I, R>
where
@ -273,7 +273,7 @@ where
}
/// A Queue-like corpus, wrapping an existing Corpus instance
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(bound = "I: serde::de::DeserializeOwned")]
pub struct QueueCorpus<C, I, R>
where

View File

@ -9,7 +9,7 @@ use crate::serde_anymap::{SerdeAny, SerdeAnyMap};
use crate::AflError;
/// An entry in the Testcase Corpus
#[derive(Default, Serialize, Deserialize)]
#[derive(Default, Serialize, Deserialize, Clone, Debug)]
#[serde(bound = "I: serde::de::DeserializeOwned")]
pub struct Testcase<I>
where

View File

@ -31,7 +31,7 @@ pub trait StateMetadata: Debug {
}
/// The state a fuzz run.
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(bound = "FT: serde::de::DeserializeOwned")]
pub struct State<I, R, FT, OT>
where
@ -322,6 +322,7 @@ where
}
}
#[derive(Clone, Debug)]
pub struct Engine<E, OT, ET, I>
where
E: Executor<I> + HasObservers<OT>,
@ -432,6 +433,7 @@ where
}
}
#[derive(Clone, Debug)]
pub struct StdFuzzer<ST, EM, E, OT, FT, ET, C, I, R>
where
ST: StagesTuple<EM, E, OT, FT, ET, C, I, R>,
@ -519,7 +521,7 @@ mod tests {
let testcase = Testcase::new(vec![0; 4]).into();
corpus.add(testcase);
let executor = InMemoryExecutor::<BytesInput, _>::new("main", harness, tuple_list!());
let executor = InMemoryExecutor::<BytesInput, _>::new("main", harness, tuple_list!(), None);
let mut state = State::new(tuple_list!());
let mut events_manager = LoggerEventManager::new(SimpleStats::new(|s| {

View File

@ -280,7 +280,7 @@ where
// TODO Custom event fire (dyn CustomEvent or similar)
}
#[derive(Debug)]
#[derive(Clone, Debug)]
pub enum LoggerEvent<I>
where
I: Input,
@ -404,6 +404,7 @@ where
}
}
#[derive(Clone, Debug)]
pub struct LoggerEventManager<C, E, OT, FT, I, R, ST>
where
C: Corpus<I, R>,
@ -532,7 +533,7 @@ where
}
}
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(bound = "I: serde::de::DeserializeOwned")]
pub enum LLMPEventKind<'a, I>
where
@ -568,7 +569,7 @@ where
},*/
}
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(bound = "I: serde::de::DeserializeOwned")]
pub struct LLMPEvent<'a, I>
where
@ -704,6 +705,7 @@ const _LLMP_TAG_EVENT_TO_BROKER: llmp::Tag = 0x2B80438;
/// Handle in both
const LLMP_TAG_EVENT_TO_BOTH: llmp::Tag = 0x2B0741;
#[derive(Clone, Debug)]
pub struct LlmpEventManager<C, E, OT, FT, I, R, SH, ST>
where
C: Corpus<I, R>,
@ -732,10 +734,10 @@ where
R: Rand,
ST: Stats,
{
#[cfg(feature = "std")]
/// Create llmp on a port
/// If the port is not yet bound, it will act as broker
/// Else, it will act as client.
#[cfg(feature = "std")]
pub fn new_on_port_std(port: u16, stats: ST) -> Result<Self, AflError> {
Ok(Self {
llmp: llmp::LlmpConnection::on_port(port)?,
@ -746,6 +748,7 @@ where
/// If a client respawns, it may reuse the existing connection, previously stored by LlmpClient::to_env
/// Std uses AflShmem.
#[cfg(feature = "std")]
pub fn existing_client_from_env_std(env_name: &str, stats: ST) -> Result<Self, AflError> {
Self::existing_client_from_env(env_name, stats)
}
@ -762,10 +765,10 @@ where
SH: ShMem,
ST: Stats,
{
#[cfg(feature = "std")]
/// Create llmp on a port
/// If the port is not yet bound, it will act as broker
/// Else, it will act as client.
#[cfg(feature = "std")]
pub fn new_on_port(port: u16, stats: ST) -> Result<Self, AflError> {
Ok(Self {
llmp: llmp::LlmpConnection::on_port(port)?,
@ -775,6 +778,7 @@ where
}
/// If a client respawns, it may reuse the existing connection, previously stored by LlmpClient::to_env
#[cfg(features = "std")]
pub fn existing_client_from_env(env_name: &str, stats: ST) -> Result<Self, AflError> {
Ok(Self {
llmp: llmp::LlmpConnection::IsClient {
@ -796,8 +800,8 @@ where
}
}
#[cfg(feature = "std")]
/// Write the config for a client eventmgr to env vars, a new client can reattach using existing_client_from_env
#[cfg(feature = "std")]
pub fn to_env(&self, env_name: &str) {
match &self.llmp {
llmp::LlmpConnection::IsBroker { broker: _ } => {

View File

@ -1,15 +1,18 @@
use core::ffi::c_void;
use core::ptr;
use alloc::boxed::Box;
use core::{ffi::c_void, ptr};
use crate::executors::{Executor, ExitKind, HasObservers};
use crate::inputs::{HasTargetBytes, Input};
use crate::observers::ObserversTuple;
use crate::tuples::Named;
use crate::AflError;
use crate::{
executors::{Executor, ExitKind, HasObservers},
inputs::{HasTargetBytes, Input},
observers::ObserversTuple,
tuples::Named,
AflError,
};
/// The (unsafe) pointer to the current inmem input, for the current run.
/// This is neede for certain non-rust side effects, as well as unix signal handling.
static mut CURRENT_INPUT_PTR: *const c_void = ptr::null();
static mut CURRENT_ON_CRASH_FN: *const Box<dyn FnOnce(ExitKind)> = ptr::null();
/// The inmem executor harness
type HarnessFunction<I> = fn(&dyn Executor<I>, &[u8]) -> ExitKind;
@ -26,10 +29,8 @@ where
harness: HarnessFunction<I>,
/// The observers, observing each run
observers: OT,
/*
/// A special function being called right before the process crashes. It may save state to restore fuzzing after respawn.
on_crash_fn: Option<Box<dyn FnOnce(ExitKind)>>,
*/
on_crash_fn: Box<dyn FnOnce(ExitKind)>,
}
impl<I, OT> Executor<I> for InMemoryExecutor<I, OT>
@ -41,10 +42,12 @@ where
fn run_target(&mut self, input: &I) -> Result<ExitKind, AflError> {
let bytes = input.target_bytes();
unsafe {
CURRENT_ON_CRASH_FN = &self.on_crash_fn as *const _;
CURRENT_INPUT_PTR = input as *const _ as *const c_void;
}
let ret = (self.harness)(self, bytes.as_slice());
unsafe {
CURRENT_ON_CRASH_FN = ptr::null();
CURRENT_INPUT_PTR = ptr::null();
}
Ok(ret)
@ -91,11 +94,12 @@ where
pub fn new(
name: &'static str,
harness_fn: HarnessFunction<I>,
observers: OT, /*on_crash_fn: Option<Box<dyn FnOnce(ExitKind)>*/
observers: OT,
on_crash_fn: Box<dyn FnOnce(ExitKind)>,
) -> Self {
Self {
harness: harness_fn,
//on_crash_fn,
on_crash_fn,
observers,
name,
}
@ -107,22 +111,32 @@ where
pub mod unix_signals {
extern crate libc;
use self::libc::{c_int, c_void, sigaction, siginfo_t};
// Unhandled signals: SIGALRM, SIGHUP, SIGINT, SIGKILL, SIGQUIT, SIGTERM
use self::libc::{
SA_NODEFER, SA_SIGINFO, SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGPIPE, SIGSEGV, SIGUSR2,
};
use std::io::{stdout, Write}; // Write brings flush() into scope
use std::{mem, process, ptr};
use crate::corpus::Corpus;
use crate::events::EventManager;
use crate::executors::inmemory::CURRENT_INPUT_PTR;
use crate::executors::Executor;
use crate::feedbacks::FeedbacksTuple;
use crate::inputs::Input;
use crate::observers::ObserversTuple;
use crate::utils::Rand;
// Unhandled signals: SIGALRM, SIGHUP, SIGINT, SIGKILL, SIGQUIT, SIGTERM
use libc::{
c_int, c_void, sigaction, siginfo_t, SA_NODEFER, SA_SIGINFO, SIGABRT, SIGBUS, SIGFPE,
SIGILL, SIGPIPE, SIGSEGV, SIGUSR2,
};
use std::{
io::{stdout, Write}, // Write brings flush() into scope
mem,
process,
ptr,
};
use crate::{
corpus::Corpus,
events::EventManager,
executors::{
inmemory::{ExitKind, CURRENT_INPUT_PTR, CURRENT_ON_CRASH_FN},
Executor,
},
feedbacks::FeedbacksTuple,
inputs::Input,
observers::ObserversTuple,
utils::Rand,
};
static mut EVENT_MANAGER_PTR: *mut c_void = ptr::null_mut();
@ -156,6 +170,10 @@ pub mod unix_signals {
manager.crash(input).expect("Error in sending Crash event");
if !CURRENT_ON_CRASH_FN.is_null() {
(*CURRENT_ON_CRASH_FN)(ExitKind::Crash);
}
std::process::exit(139);
}
@ -173,7 +191,7 @@ pub mod unix_signals {
R: Rand,
{
dbg!("TIMEOUT/SIGUSR2 received");
if CURRENT_INPUT_PTR == ptr::null() {
if CURRENT_INPUT_PTR.is_null() {
dbg!("TIMEOUT or SIGUSR2 happened, but currently not fuzzing.");
return;
}
@ -185,6 +203,10 @@ pub mod unix_signals {
.timeout(input)
.expect("Error in sending Timeout event");
if !CURRENT_ON_CRASH_FN.is_null() {
(*CURRENT_ON_CRASH_FN)(ExitKind::Timeout);
}
// TODO: send LLMP.
println!("Timeout in fuzz run.");
let _ = stdout().flush();
@ -238,6 +260,8 @@ pub mod unix_signals {
#[cfg(test)]
mod tests {
use alloc::boxed::Box;
use crate::executors::inmemory::InMemoryExecutor;
use crate::executors::{Executor, ExitKind};
use crate::inputs::{HasTargetBytes, Input, TargetBytes};
@ -267,7 +291,8 @@ mod tests {
#[test]
fn test_inmem_exec() {
let mut in_mem_executor = InMemoryExecutor::new("main", test_harness_fn_nop, tuple_list!());
let mut in_mem_executor =
InMemoryExecutor::new("main", test_harness_fn_nop, tuple_list!(), Box::new(|_| ()));
let mut input = NopInput {};
assert!(in_mem_executor.run_target(&mut input).is_ok());
}

View File

@ -41,6 +41,30 @@ where
fn discard_metadata(&mut self, _input: &I) -> Result<(), AflError> {
Ok(())
}
/*
/// Serialize this feedback's state only, to be restored later using deserialize_state
/// As opposed to completely serializing the observer, this is only needed when the fuzzer is to be restarted
/// If no state is needed to be kept, just return an empty vec.
/// Example:
/// >> The virgin_bits map in AFL needs to be in sync with the corpus
#[inline]
fn serialize_state(&mut self) -> Result<Vec<u8>, AflError> {
Ok(vec![])
}
/// Restore the state from a given vec, priviously stored using `serialize_state`
#[inline]
fn deserialize_state(&mut self, serialized_state: &[u8]) -> Result<(), AflError> {
let _ = serialized_state;
Ok(())
}
// TODO: Restore_from
fn restore_from(&mut self, restore_from: Self) -> Result<(), AflError> {
Ok(())
}
*/
}
pub trait FeedbacksTuple<I>: serde::Serialize + serde::de::DeserializeOwned
@ -59,25 +83,38 @@ where
/// Discards metadata - the end of this input's execution
fn discard_metadata_all(&mut self, input: &I) -> Result<(), AflError>;
/*
/// Restores the state from each of the containing feedbacks in a list of the same shape.
/// Used (prette exclusively) to restore the feedback states after a crash.
fn restore_state_from_all(&mut self, restore_from: &Self) -> Result<(), AflError>;
*/
}
impl<I> FeedbacksTuple<I> for ()
where
I: Input,
{
fn is_interesting_all<OT: ObserversTuple>(
&mut self,
_input: &I,
_observers: &OT,
) -> Result<u32, AflError> {
#[inline]
fn is_interesting_all<OT: ObserversTuple>(&mut self, _: &I, _: &OT) -> Result<u32, AflError> {
Ok(0)
}
#[inline]
fn append_metadata_all(&mut self, _testcase: &mut Testcase<I>) -> Result<(), AflError> {
Ok(())
}
#[inline]
fn discard_metadata_all(&mut self, _input: &I) -> Result<(), AflError> {
Ok(())
}
/*
fn restore_state_from_all(&mut self, restore_from: &Self) -> Result<(), AflError> {
Ok(())
}
*/
}
impl<Head, Tail, I> FeedbacksTuple<I> for (Head, Tail)
@ -104,6 +141,13 @@ where
self.0.discard_metadata(input)?;
self.1.discard_metadata_all(input)
}
/*
fn restore_state_from_all(&mut self, restore_from: &Self) -> Result<(), AflError> {
self.0.restore_from(restore_from.0)?;
self.1.restore_state_from_all(restore_from.1)?;
}
*/
}
/// A Reducer function is used to aggregate values for the novelty search
@ -114,7 +158,7 @@ where
fn reduce(first: T, second: T) -> T;
}
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct MaxReducer<T>
where
T: Integer + Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
@ -136,7 +180,7 @@ where
}
}
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct MinReducer<T>
where
T: Integer + Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
@ -159,7 +203,7 @@ where
}
/// The most common AFL-like feedback type
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(bound = "T: serde::de::DeserializeOwned")]
pub struct MapFeedback<T, R, O>
where

View File

@ -23,6 +23,7 @@ where
fn generate_dummy(&self) -> I;
}
#[derive(Clone, Debug)]
/// Generates random bytes
pub struct RandBytesGenerator<R>
where
@ -64,6 +65,7 @@ where
}
}
#[derive(Clone, Debug)]
/// Generates random printable characters
pub struct RandPrintablesGenerator<R> {
max_size: usize,

View File

@ -44,6 +44,7 @@ where
}
}
#[derive(Clone)]
pub struct StdScheduledMutator<C, I, R>
where
C: Corpus<I, R>,
@ -142,6 +143,7 @@ where
}
}
#[derive(Clone, Debug)]
/// Schedule some selected byte level mutations given a ScheduledMutator type
pub struct HavocBytesMutator<SM, C, I, R>
where

View File

@ -17,12 +17,31 @@ pub trait Observer: Named + serde::Serialize + serde::de::DeserializeOwned + 'st
Ok(())
}
/// Resets the observer
fn reset(&mut self) -> Result<(), AflError>;
/// This function is executed after each fuzz run
#[inline]
fn post_exec(&mut self) -> Result<(), AflError> {
Ok(())
}
/// Serialize this observer's state only, to be restored later using deserialize_state
/// As opposed to completely serializing the observer, this is only needed when the fuzzer is to be restarted
/// If no state is needed to be kept, just return an empty vec.
/// Example:
/// >> The virgin_bits map in AFL needs to be in sync with the corpus
#[inline]
fn serialize_state(&mut self) -> Result<Vec<u8>, AflError> {
Ok(vec![])
}
/// Restore the state from a given vec, priviously stored using `serialize_state`
#[inline]
fn deserialize_state(&mut self, serialized_state: &[u8]) -> Result<(), AflError> {
let _ = serialized_state;
Ok(())
}
}
pub trait ObserversTuple:
@ -124,7 +143,7 @@ where
/// The Map Observer retrieves the state of a map,
/// that will get updated by the target.
/// A well-known example is the AFL-Style coverage map.
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(bound = "T: serde::de::DeserializeOwned")]
pub struct StdMapObserver<T>
where
@ -212,7 +231,7 @@ where
}
}
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(bound = "T: serde::de::DeserializeOwned")]
pub struct VariableMapObserver<T>
where

View File

@ -1,8 +1,9 @@
use serde::Deserialize;
use alloc::boxed::Box;
use alloc::vec::Vec;
use alloc::{boxed::Box, vec::Vec};
use core::any::{Any, TypeId};
#[cfg(fature = "anymap_debug")]
use serde_json;
// yolo
@ -16,8 +17,11 @@ pub fn unpack_type_id(id: TypeId) -> u64 {
unsafe { *(&id as *const _ as *const u64) }
}
/// An any object
pub trait SerdeAny: Any + erased_serde::Serialize {
/// returns this as Any trait
fn as_any(&self) -> &dyn Any;
/// returns this as mutable Any trait
fn as_any_mut(&mut self) -> &mut dyn Any;
}
@ -68,6 +72,7 @@ macro_rules! create_serde_registry_for_trait {
use alloc::string::String;
use core::any::{Any, TypeId};
use core::fmt;
use postcard;
use serde::{Deserialize, Serialize};
use hashbrown::hash_map::{Keys, Values, ValuesMut};
@ -159,6 +164,30 @@ macro_rules! create_serde_registry_for_trait {
map: HashMap<u64, Box<dyn $trait_name>>,
}
// Cloning by serializing and deserializing. It ain't fast, but it's honest work.
// We unwrap postcard, it should not have a reason to fail.
impl Clone for SerdeAnyMap {
fn clone(&self) -> Self {
let serialized = postcard::to_allocvec(&self).unwrap();
postcard::from_bytes(&serialized).unwrap()
}
}
#[cfg(fature = "anymapdbg")]
impl fmt::Debug for SerdeAnyMap {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let json = serde_json::to_string(&self);
write!(f, "SerdeAnyMap: [{}]", json)
}
}
#[cfg(not(fature = "anymapdbg"))]
impl fmt::Debug for SerdeAnyMap {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "SerdeAnymap with {} elements", self.len())
}
}
impl SerdeAnyMap {
#[inline]
pub fn get<T>(&self) -> Option<&T>
@ -463,6 +492,7 @@ macro_rules! create_serde_registry_for_trait {
create_serde_registry_for_trait!(serdeany_serde, crate::serde_anymap::SerdeAny);
pub use serdeany_serde::*;
#[derive(Clone, Debug)]
pub enum Ptr<'a, T: 'a + ?Sized> {
Ref(&'a T),
Owned(Box<T>),
@ -629,6 +659,7 @@ impl<'a, T: Sized> SliceMut<'a, T> {
}
}
#[derive(Clone, Debug)]
pub enum Cptr<T: Sized> {
Cptr(*const T),
Owned(Box<T>),
@ -741,6 +772,7 @@ impl<T: Sized> Array<T> {
}
}
#[derive(Clone, Debug)]
pub enum ArrayMut<T: Sized> {
Cptr((*mut T, usize)),
Owned(Vec<T>),

View File

@ -84,6 +84,7 @@ where
}
}
#[derive(Clone, Debug)]
/// The default mutational stage
pub struct StdMutationalStage<M, EM, E, OT, FT, ET, C, I, R>
where

View File

@ -105,6 +105,11 @@ fn fuzz(input: Option<Vec<PathBuf>>, broker_port: u16) -> Result<(), AflError> {
let mut receiver = LlmpReceiver::<AflShmem>::on_existing_from_env(ENV_FUZZER_RECEIVER)?;
let mut sender = LlmpSender::<AflShmem>::on_existing_from_env(ENV_FUZZER_SENDER)?;
let edges_observer =
StdMapObserver::new_from_ptr(&NAME_COV_MAP, unsafe { __lafl_edges_map }, unsafe {
__lafl_max_edges_size as usize
});
// Call LLVMFUzzerInitialize() if present.
unsafe {
if afl_libfuzzer_init() == -1 {
@ -113,28 +118,32 @@ fn fuzz(input: Option<Vec<PathBuf>>, broker_port: u16) -> Result<(), AflError> {
}
// If we're restarting, deserialize the old corpus.
let mut corpus = match receiver.recv_buf()? {
let (mut state, mut corpus) = match receiver.recv_buf()? {
None => {
// Initial execution, read or generate initial inputs
InMemoryCorpus::new()
// Initial execution, read or generate initial state, corpus, and feedbacks
let edges_feedback = MaxMapFeedback::new_with_observer(&NAME_COV_MAP, &edges_observer);
let state = State::new(tuple_list!(edges_feedback));
let corpus = InMemoryCorpus::new();
(state, corpus)
}
// Restoring from a previous run, deserialize state and corpus.
Some((_sender, _tag, msg)) => postcard::from_bytes(msg)?,
};
// We reset the sender, the next sender and receiver (after crash) will reuse the page from the initial message.
unsafe { sender.reset_last_page() };
// TODO: How to restore the observer state?
let edges_observer =
StdMapObserver::new_from_ptr(&NAME_COV_MAP, unsafe { __lafl_edges_map }, unsafe {
__lafl_max_edges_size as usize
});
let edges_feedback = MaxMapFeedback::new_with_observer(&NAME_COV_MAP, &edges_observer);
let executor = InMemoryExecutor::new("Libfuzzer", harness, tuple_list!(edges_observer));
let mut state = State::new(tuple_list!(edges_feedback));
// Create the engine
let executor = InMemoryExecutor::new("Libfuzzer", harness, tuple_list!(edges_observer), Some(Box::new(|exit_kind| {
// TODO: How to access state, corpus? Unsafe is fine?
/*
let serialized = postcard::to_allocvec(&(state, corpus)).unwrap();
sender.send_buf(0x1, &serialized).unwrap();
*/
})));
let mut engine = Engine::new(executor);
// in case the corpus is empty (on first run), reset
if corpus.count() < 1 {
match input {
Some(x) => state
@ -142,6 +151,7 @@ fn fuzz(input: Option<Vec<PathBuf>>, broker_port: u16) -> Result<(), AflError> {
.expect(&format!("Failed to load initial corpus at {:?}", &x)),
None => (),
}
println!("We imported {} inputs from disk.", corpus.count());
}
if corpus.count() < 1 {
println!("Generating random inputs");
@ -155,10 +165,9 @@ fn fuzz(input: Option<Vec<PathBuf>>, broker_port: u16) -> Result<(), AflError> {
4,
)
.expect("Failed to generate initial inputs");
println!("We generated {} inputs.", corpus.count());
}
println!("We have {} inputs.", corpus.count());
let mut mutator = HavocBytesMutator::new_default();
mutator.set_max_size(4096);