started moving to no_std
This commit is contained in:
parent
629287251f
commit
ec36301414
@ -9,9 +9,12 @@ edition = "2018"
|
||||
[dev-dependencies]
|
||||
criterion = "0.3" # Benchmarking
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = []
|
||||
|
||||
[dependencies]
|
||||
xxhash-rust = { version = "0.8.0-beta.4", features = ["xxh3"] } # xxh3 hashing for rust
|
||||
thiserror = "1.0" # A nicer way to write Errors
|
||||
hashbrown = "0.9" # A faster hashmap, nostd compatible
|
||||
libc = "0.2" # For (*nix) libc
|
||||
num = "*"
|
@ -3,9 +3,12 @@ extern crate alloc;
|
||||
pub mod testcase;
|
||||
pub use testcase::{Testcase, TestcaseMetadata};
|
||||
|
||||
use alloc::borrow::ToOwned;
|
||||
use alloc::rc::Rc;
|
||||
use alloc::vec::Vec;
|
||||
use core::cell::RefCell;
|
||||
use core::marker::PhantomData;
|
||||
#[cfg(feature = "std")]
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::inputs::Input;
|
||||
@ -34,16 +37,10 @@ where
|
||||
}
|
||||
|
||||
/// Add an entry to the corpus
|
||||
#[allow(unused_mut)]
|
||||
fn add(&mut self, mut testcase: Rc<RefCell<Testcase<I>>>) {
|
||||
fn add(&mut self, testcase: Rc<RefCell<Testcase<I>>>) {
|
||||
self.entries_mut().push(testcase);
|
||||
}
|
||||
|
||||
/// Add an input to the corpus
|
||||
fn add_input(&mut self, input: I) {
|
||||
self.add(Testcase::new(input.into()).into());
|
||||
}
|
||||
|
||||
/// Removes an entry from the corpus, returning it if it was present.
|
||||
fn remove(&mut self, entry: &Testcase<I>) -> Option<Rc<RefCell<Testcase<I>>>> {
|
||||
let mut i: usize = 0;
|
||||
@ -135,6 +132,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub struct OnDiskCorpus<I, R>
|
||||
where
|
||||
I: Input,
|
||||
@ -145,6 +143,7 @@ where
|
||||
dir_path: PathBuf,
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<I, R> HasEntriesVec<I> for OnDiskCorpus<I, R>
|
||||
where
|
||||
I: Input,
|
||||
@ -158,6 +157,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<I, R> HasRand for OnDiskCorpus<I, R>
|
||||
where
|
||||
I: Input,
|
||||
@ -170,6 +170,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<I, R> Corpus<I> for OnDiskCorpus<I, R>
|
||||
where
|
||||
I: Input,
|
||||
@ -179,9 +180,9 @@ where
|
||||
fn add(&mut self, entry: Rc<RefCell<Testcase<I>>>) {
|
||||
if *entry.borrow().filename() == None {
|
||||
// TODO walk entry metadatas to ask for pices of filename (e.g. :havoc in AFL)
|
||||
let filename = &(String::from("id:") + &self.entries.len().to_string());
|
||||
let filename = self.dir_path.join(filename);
|
||||
*entry.borrow_mut().filename_mut() = Some(filename);
|
||||
let filename = self.dir_path.join(format!("id_{}", &self.entries.len()));
|
||||
let filename_str = filename.to_str().expect("Invalid Path");
|
||||
*entry.borrow_mut().filename_mut() = Some(filename_str.into());
|
||||
}
|
||||
self.entries.push(entry);
|
||||
}
|
||||
@ -189,6 +190,7 @@ where
|
||||
// TODO save and remove files, cache, etc..., ATM use just InMemoryCorpus
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<I, R> OnDiskCorpus<I, R>
|
||||
where
|
||||
I: Input,
|
||||
@ -352,6 +354,7 @@ And then:
|
||||
*/
|
||||
|
||||
#[cfg(test)]
|
||||
#[cfg(feature = "std")]
|
||||
mod tests {
|
||||
use crate::corpus::Corpus;
|
||||
use crate::corpus::Testcase;
|
||||
@ -363,11 +366,11 @@ mod tests {
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[test]
|
||||
|
||||
fn test_queuecorpus() {
|
||||
let rand: Rc<_> = DefaultRand::preseeded().into();
|
||||
let rand: Rc<_> = DefaultRand::new(0).into();
|
||||
let mut q = QueueCorpus::new(OnDiskCorpus::new(&rand, PathBuf::from("fancy/path")));
|
||||
let t: Rc<_> = Testcase::with_filename(BytesInput::new(vec![0 as u8; 4]), PathBuf::from("fancyfile")).into();
|
||||
let t: Rc<_> =
|
||||
Testcase::with_filename(BytesInput::new(vec![0 as u8; 4]), "fancyfile".into()).into();
|
||||
q.add(t);
|
||||
let filename = q
|
||||
.next()
|
||||
@ -387,6 +390,6 @@ mod tests {
|
||||
.unwrap()
|
||||
.to_owned()
|
||||
);
|
||||
assert_eq!(filename, PathBuf::from("fancyfile"));
|
||||
assert_eq!(filename, "fancyfile");
|
||||
}
|
||||
}
|
||||
|
@ -7,9 +7,12 @@ use alloc::rc::Rc;
|
||||
use core::cell::RefCell;
|
||||
use core::convert::Into;
|
||||
use hashbrown::HashMap;
|
||||
#[cfg(feature = "std")]
|
||||
use std::fs::File;
|
||||
#[cfg(feature = "std")]
|
||||
use std::io::Write;
|
||||
use std::path::{Path, PathBuf};
|
||||
#[cfg(feature = "std")]
|
||||
use std::path::Path;
|
||||
|
||||
// TODO: Give example
|
||||
/// Metadata for a testcase
|
||||
@ -18,6 +21,24 @@ pub trait TestcaseMetadata {
|
||||
fn name(&self) -> &'static str;
|
||||
}
|
||||
|
||||
/*
|
||||
pub trait Testcase<I, T>
|
||||
where
|
||||
I: Input,
|
||||
T: TestcaseMetadata,
|
||||
{
|
||||
|
||||
fn input(&mut self) -> Option<I>
|
||||
|
||||
input: Option<I>,
|
||||
/// Filename, if this testcase is backed by a file in the filesystem
|
||||
filename: Option<String>,
|
||||
/// Map of metadatas associated with this testcase
|
||||
metadatas: HashMap<&'static str, Box<dyn TestcaseMetadata>>,
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
pub enum FileBackedTestcase<I, P> {
|
||||
/// A testcase on disk, not yet loaded
|
||||
Stored { filename: P },
|
||||
@ -109,7 +130,7 @@ where
|
||||
/// The input of this testcase
|
||||
input: Option<I>,
|
||||
/// Filename, if this testcase is backed by a file in the filesystem
|
||||
filename: Option<PathBuf>,
|
||||
filename: Option<String>,
|
||||
/// Map of metadatas associated with this testcase
|
||||
metadatas: HashMap<&'static str, Box<dyn TestcaseMetadata>>,
|
||||
}
|
||||
@ -133,7 +154,7 @@ where
|
||||
// TODO: Implement cache to disk
|
||||
match self.input.as_ref() {
|
||||
Some(i) => Ok(i),
|
||||
None => Err(AflError::NotImplemented("load_input".to_string())),
|
||||
None => Err(AflError::NotImplemented("load_input".into())),
|
||||
}
|
||||
}
|
||||
|
||||
@ -151,15 +172,15 @@ where
|
||||
}
|
||||
|
||||
/// Get the filename, if any
|
||||
pub fn filename(&self) -> &Option<PathBuf> {
|
||||
pub fn filename(&self) -> &Option<String> {
|
||||
&self.filename
|
||||
}
|
||||
/// Get the filename, if any (mutable)
|
||||
pub fn filename_mut(&mut self) -> &mut Option<PathBuf> {
|
||||
pub fn filename_mut(&mut self) -> &mut Option<String> {
|
||||
&mut self.filename
|
||||
}
|
||||
/// Set the filename
|
||||
pub fn set_filename(&mut self, filename: Option<PathBuf>) {
|
||||
pub fn set_filename(&mut self, filename: Option<String>) {
|
||||
self.filename = filename;
|
||||
}
|
||||
|
||||
@ -183,7 +204,7 @@ where
|
||||
}
|
||||
|
||||
/// Create a new Testcase instace given an input and a filename
|
||||
pub fn with_filename(input: I, filename: PathBuf) -> Self {
|
||||
pub fn with_filename(input: I, filename: String) -> Self {
|
||||
Testcase {
|
||||
input: Some(input),
|
||||
filename: Some(filename),
|
||||
|
@ -103,7 +103,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_engine() {
|
||||
let rand: Rc<_> = DefaultRand::preseeded().into();
|
||||
let rand: Rc<_> = DefaultRand::new(0).into();
|
||||
|
||||
let mut corpus = InMemoryCorpus::<BytesInput, _>::new(&rand);
|
||||
let testcase = Testcase::new(BytesInput::new(vec![0; 4])).into();
|
||||
|
@ -67,11 +67,11 @@ where
|
||||
self.observers.push(observer);
|
||||
}
|
||||
|
||||
fn observers(&self) -> &Vec<Box<dyn Observer>> {
|
||||
fn observers(&self) -> &[Box<dyn Observer>] {
|
||||
&self.observers
|
||||
}
|
||||
|
||||
fn feedbacks(&self) -> &Vec<Box<dyn Feedback<I>>> {
|
||||
fn feedbacks(&self) -> &[Box<dyn Feedback<I>>] {
|
||||
&self.feedbacks
|
||||
}
|
||||
|
||||
@ -211,10 +211,10 @@ mod tests {
|
||||
|
||||
impl Observer for Nopserver {
|
||||
fn reset(&mut self) -> Result<(), AflError> {
|
||||
Err(AflError::Unknown("Nop reset, testing only".to_string()))
|
||||
Err(AflError::Unknown("Nop reset, testing only".into()))
|
||||
}
|
||||
fn post_exec(&mut self) -> Result<(), AflError> {
|
||||
Err(AflError::Unknown("Nop exec, testing only".to_string()))
|
||||
Err(AflError::Unknown("Nop exec, testing only".into()))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,6 @@
|
||||
extern crate alloc;
|
||||
pub mod inmemory;
|
||||
|
||||
use alloc::rc::Rc;
|
||||
use core::cell::RefCell;
|
||||
|
||||
use crate::corpus::Testcase;
|
||||
use crate::corpus::TestcaseMetadata;
|
||||
use crate::feedbacks::Feedback;
|
||||
use crate::inputs::Input;
|
||||
@ -37,13 +33,13 @@ where
|
||||
fn add_observer(&mut self, observer: Box<dyn Observer>);
|
||||
|
||||
/// Get the linked observers
|
||||
fn observers(&self) -> &Vec<Box<dyn Observer>>;
|
||||
fn observers(&self) -> &[Box<dyn Observer>];
|
||||
|
||||
/// Adds a feedback
|
||||
fn add_feedback(&mut self, feedback: Box<dyn Feedback<I>>);
|
||||
|
||||
/// Returns vector of feebacks
|
||||
fn feedbacks(&self) -> &Vec<Box<dyn Feedback<I>>>;
|
||||
fn feedbacks(&self) -> &[Box<dyn Feedback<I>>];
|
||||
|
||||
/// Returns vector of feebacks (mutable)
|
||||
fn feedbacks_mut(&mut self) -> &mut Vec<Box<dyn Feedback<I>>>;
|
||||
@ -66,12 +62,6 @@ where
|
||||
}
|
||||
|
||||
if rate_acc >= 25 {
|
||||
let new_entry = Rc::new(RefCell::new(Testcase::<I>::new(input.clone())));
|
||||
for meta in metadatas {
|
||||
new_entry.borrow_mut().add_metadata(meta);
|
||||
}
|
||||
//TODO corpus.add(new_entry);
|
||||
|
||||
Ok(true)
|
||||
} else {
|
||||
Ok(false)
|
||||
|
@ -3,6 +3,8 @@ extern crate num;
|
||||
|
||||
use core::cell::RefCell;
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use alloc::vec::*;
|
||||
use num::Integer;
|
||||
|
||||
use crate::corpus::TestcaseMetadata;
|
||||
|
@ -1,9 +1,10 @@
|
||||
extern crate alloc;
|
||||
|
||||
use core::convert::From;
|
||||
|
||||
use alloc::borrow::ToOwned;
|
||||
use alloc::rc::Rc;
|
||||
use alloc::vec::Vec;
|
||||
use core::cell::RefCell;
|
||||
use core::convert::From;
|
||||
|
||||
use crate::inputs::{HasBytesVec, HasTargetBytes, Input};
|
||||
use crate::AflError;
|
||||
@ -20,7 +21,9 @@ impl Input for BytesInput {
|
||||
}
|
||||
|
||||
fn deserialize(buf: &[u8]) -> Result<Self, AflError> {
|
||||
Ok(Self { bytes: buf.into() })
|
||||
Ok(Self {
|
||||
bytes: buf.to_owned(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,7 +35,7 @@ impl Into<Rc<RefCell<Self>>> for BytesInput {
|
||||
}
|
||||
|
||||
impl HasBytesVec for BytesInput {
|
||||
fn bytes(&self) -> &Vec<u8> {
|
||||
fn bytes(&self) -> &[u8] {
|
||||
&self.bytes
|
||||
}
|
||||
fn bytes_mut(&mut self) -> &mut Vec<u8> {
|
||||
@ -41,7 +44,7 @@ impl HasBytesVec for BytesInput {
|
||||
}
|
||||
|
||||
impl HasTargetBytes for BytesInput {
|
||||
fn target_bytes(&self) -> &Vec<u8> {
|
||||
fn target_bytes(&self) -> &[u8] {
|
||||
&self.bytes
|
||||
}
|
||||
}
|
||||
@ -71,7 +74,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_input() {
|
||||
let mut rand = DefaultRand::preseeded();
|
||||
let mut rand = DefaultRand::new(0);
|
||||
assert_ne!(rand.next(), rand.next());
|
||||
assert!(rand.below(100) < 100);
|
||||
assert_eq!(rand.below(1), 0);
|
||||
|
@ -3,15 +3,21 @@ extern crate alloc;
|
||||
pub mod bytes;
|
||||
pub use bytes::BytesInput;
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use core::clone::Clone;
|
||||
use std::io::Write;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use std::fs::File;
|
||||
#[cfg(feature = "std")]
|
||||
use std::io::{Read, Write};
|
||||
#[cfg(feature = "std")]
|
||||
use std::path::Path;
|
||||
use std::{fs::File, io::Read};
|
||||
|
||||
use crate::AflError;
|
||||
|
||||
/// An input for the target
|
||||
pub trait Input: Clone {
|
||||
#[cfg(feature = "std")]
|
||||
/// Write this input to the file
|
||||
fn to_file<P>(&self, path: P) -> Result<(), AflError>
|
||||
where
|
||||
@ -22,7 +28,15 @@ pub trait Input: Clone {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
/// Write this input to the file
|
||||
fn to_file<P>(&self, string: P) -> Result<(), AflError>
|
||||
where {
|
||||
Err(AflError::NotImplemented("Not suppored in no_std".into()))
|
||||
}
|
||||
|
||||
/// Load the contents of this input from a file
|
||||
#[cfg(feature = "std")]
|
||||
fn from_file<P>(path: P) -> Result<Self, AflError>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
@ -33,6 +47,13 @@ pub trait Input: Clone {
|
||||
Self::deserialize(&bytes)
|
||||
}
|
||||
|
||||
/// Write this input to the file
|
||||
#[cfg(not(feature = "std"))]
|
||||
fn from_file<P>(string: P) -> Result<Self, AflError>
|
||||
where {
|
||||
Err(AflError::NotImplemented("Not suppored in no_std".into()))
|
||||
}
|
||||
|
||||
/// Serialize this input, for later deserialization.
|
||||
/// This is not necessarily the representation to be used by the target
|
||||
/// Instead, to get bytes for a target, use [HasTargetBytes](afl::inputs::HasTargetBytes).
|
||||
@ -47,13 +68,13 @@ pub trait Input: Clone {
|
||||
/// Instead, it can be used as bytes input for a target
|
||||
pub trait HasTargetBytes {
|
||||
/// Target bytes, that can be written to a target
|
||||
fn target_bytes(&self) -> &Vec<u8>;
|
||||
fn target_bytes(&self) -> &[u8];
|
||||
}
|
||||
|
||||
/// Contains an internal bytes Vector
|
||||
pub trait HasBytesVec {
|
||||
/// The internal bytes map
|
||||
fn bytes(&self) -> &Vec<u8>;
|
||||
fn bytes(&self) -> &[u8];
|
||||
/// The internal bytes map (as mutable borrow)
|
||||
fn bytes_mut(&mut self) -> &mut Vec<u8>;
|
||||
}
|
||||
|
46
src/lib.rs
46
src/lib.rs
@ -1,3 +1,5 @@
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
#[macro_use]
|
||||
extern crate alloc;
|
||||
|
||||
pub mod corpus;
|
||||
@ -11,32 +13,52 @@ pub mod observers;
|
||||
pub mod stages;
|
||||
pub mod utils;
|
||||
|
||||
use alloc::string::String;
|
||||
use core::fmt;
|
||||
#[cfg(feature = "std")]
|
||||
use std::io;
|
||||
use thiserror::Error;
|
||||
|
||||
/// Main error struct for AFL
|
||||
#[derive(Error, Debug)]
|
||||
#[derive(Debug)]
|
||||
pub enum AflError {
|
||||
#[error("Error in Serialization: `{0}`")]
|
||||
Serialize(String),
|
||||
#[error("File IO failed")]
|
||||
File(#[from] io::Error),
|
||||
#[error("Optional value `{0}` was not set")]
|
||||
#[cfg(feature = "std")]
|
||||
File(io::Error),
|
||||
EmptyOptional(String),
|
||||
#[error("Key `{0}` not in Corpus")]
|
||||
KeyNotFound(String),
|
||||
#[error("No items in {0}")]
|
||||
Empty(String),
|
||||
#[error("All elements have been processed in {0} iterator")]
|
||||
IteratorEnd(String),
|
||||
#[error("Not implemented: {0}")]
|
||||
NotImplemented(String),
|
||||
#[error("Illegal state: {0}")]
|
||||
IllegalState(String),
|
||||
#[error("Unknown error: {0}")]
|
||||
Unknown(String),
|
||||
}
|
||||
|
||||
impl fmt::Display for AflError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Self::Serialize(s) => write!(f, "Error in Serialization: `{0}`", &s),
|
||||
#[cfg(feature = "std")]
|
||||
Self::File(err) => write!(f, "File IO failed: {:?}", &err),
|
||||
Self::EmptyOptional(s) => write!(f, "Optional value `{0}` was not set", &s),
|
||||
Self::KeyNotFound(s) => write!(f, "Key `{0}` not in Corpus", &s),
|
||||
Self::Empty(s) => write!(f, "No items in {0}", &s),
|
||||
Self::IteratorEnd(s) => {
|
||||
write!(f, "All elements have been processed in {0} iterator", &s)
|
||||
}
|
||||
Self::NotImplemented(s) => write!(f, "Not implemented: {0}", &s),
|
||||
Self::IllegalState(s) => write!(f, "Illegal state: {0}", &s),
|
||||
Self::Unknown(s) => write!(f, "Unknown error: {0}", &s),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl From<io::Error> for AflError {
|
||||
fn from(err: io::Error) -> Self {
|
||||
Self::File(err)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
|
@ -7,6 +7,7 @@ use crate::utils::{HasRand, Rand};
|
||||
use crate::AflError;
|
||||
|
||||
use alloc::rc::Rc;
|
||||
use alloc::vec::Vec;
|
||||
use core::cell::RefCell;
|
||||
use core::marker::PhantomData;
|
||||
|
||||
@ -42,7 +43,7 @@ where
|
||||
fn schedule(&mut self, _input: &I) -> Result<MutationFunction<C, Self, I>, AflError> {
|
||||
let count = self.mutations_count() as u64;
|
||||
if count == 0 {
|
||||
return Err(AflError::Empty("no mutations".to_string()));
|
||||
return Err(AflError::Empty("no mutations".into()));
|
||||
}
|
||||
let idx;
|
||||
{
|
||||
@ -109,7 +110,7 @@ where
|
||||
{
|
||||
fn mutation_by_idx(&self, index: usize) -> Result<MutationFunction<C, Self, I>, AflError> {
|
||||
if index >= self.mutations.len() {
|
||||
return Err(AflError::Unknown("oob".to_string()));
|
||||
return Err(AflError::Unknown("oob".into()));
|
||||
}
|
||||
Ok(self.mutations[index])
|
||||
}
|
||||
@ -172,7 +173,7 @@ where
|
||||
}
|
||||
|
||||
/// Returns the first and last diff position between the given vectors, stopping at the min len
|
||||
fn locate_diffs(this: &Vec<u8>, other: &Vec<u8>) -> (i64, i64) {
|
||||
fn locate_diffs(this: &[u8], other: &[u8]) -> (i64, i64) {
|
||||
let mut first_diff: i64 = -1;
|
||||
let mut last_diff: i64 = -1;
|
||||
for (i, (this_el, other_el)) in this.iter().zip(other.iter()).enumerate() {
|
||||
@ -208,7 +209,7 @@ where
|
||||
Err(_) => {
|
||||
if retry_count == 20 {
|
||||
return Err(AflError::Empty(
|
||||
"No suitable testcase found for splicing".to_owned(),
|
||||
"No suitable testcase found for splicing".into(),
|
||||
));
|
||||
}
|
||||
retry_count += 1;
|
||||
@ -231,7 +232,7 @@ where
|
||||
break (f, l);
|
||||
}
|
||||
if counter == 20 {
|
||||
return Err(AflError::Empty("No valid diff found".to_owned()));
|
||||
return Err(AflError::Empty("No valid diff found".into()));
|
||||
}
|
||||
counter += 1;
|
||||
};
|
||||
@ -324,10 +325,13 @@ where
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::corpus::{Corpus, InMemoryCorpus};
|
||||
use crate::inputs::{BytesInput, HasBytesVec};
|
||||
use crate::inputs::BytesInput;
|
||||
use crate::mutators::scheduled::mutation_splice;
|
||||
use crate::utils::{DefaultHasRand, Rand, XKCDRand};
|
||||
use crate::{
|
||||
corpus::{Corpus, InMemoryCorpus, Testcase},
|
||||
inputs::HasBytesVec,
|
||||
};
|
||||
use alloc::rc::Rc;
|
||||
|
||||
#[test]
|
||||
@ -336,8 +340,8 @@ mod tests {
|
||||
let rand: Rc<_> = XKCDRand::new().into();
|
||||
let mut has_rand = DefaultHasRand::new(&rand);
|
||||
let mut corpus = InMemoryCorpus::new(&rand);
|
||||
corpus.add_input(BytesInput::new(vec!['a' as u8, 'b' as u8, 'c' as u8]));
|
||||
corpus.add_input(BytesInput::new(vec!['d' as u8, 'e' as u8, 'f' as u8]));
|
||||
corpus.add(Testcase::new(BytesInput::new(vec!['a' as u8, 'b' as u8, 'c' as u8])).into());
|
||||
corpus.add(Testcase::new(BytesInput::new(vec!['d' as u8, 'e' as u8, 'f' as u8])).into());
|
||||
|
||||
let testcase_rr = corpus.next().expect("Corpus did not contain entries");
|
||||
let mut testcase = testcase_rr.borrow_mut();
|
||||
@ -346,10 +350,11 @@ mod tests {
|
||||
rand.borrow_mut().set_seed(5);
|
||||
mutation_splice(&mut has_rand, &mut corpus, &mut input).unwrap();
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
println!("{:?}", input.bytes());
|
||||
|
||||
// The pre-seeded rand should have spliced at position 2.
|
||||
// TODO: Maybe have a fixed rand for this purpose?
|
||||
assert_eq!(input.bytes(), &vec!['a' as u8, 'b' as u8, 'f' as u8])
|
||||
assert_eq!(input.bytes(), &['a' as u8, 'b' as u8, 'f' as u8])
|
||||
}
|
||||
}
|
||||
|
10
src/utils.rs
10
src/utils.rs
@ -5,9 +5,11 @@ use alloc::rc::Rc;
|
||||
use core::cell::RefCell;
|
||||
use core::debug_assert;
|
||||
use core::fmt::Debug;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
use xxhash_rust::xxh3::xxh3_64_with_seed;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
pub type DefaultRand = Xoshiro256StarRand;
|
||||
|
||||
/// Ways to get random around here
|
||||
@ -128,6 +130,8 @@ impl Xoshiro256StarRand {
|
||||
}
|
||||
|
||||
/// Creates a rand instance, pre-seeded with the current time in nanoseconds.
|
||||
/// Needs stdlib timer
|
||||
#[cfg(feature = "std")]
|
||||
pub fn preseeded() -> Self {
|
||||
let seed = SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
@ -220,7 +224,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_rand() {
|
||||
let mut rand = DefaultRand::preseeded();
|
||||
let mut rand = DefaultRand::new(0);
|
||||
assert_ne!(rand.next(), rand.next());
|
||||
assert!(rand.below(100) < 100);
|
||||
assert_eq!(rand.below(1), 0);
|
||||
@ -230,7 +234,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_has_rand() {
|
||||
let rand = DefaultRand::preseeded().into();
|
||||
let rand = DefaultRand::new(0).into();
|
||||
let has_rand = DefaultHasRand::new(&rand);
|
||||
|
||||
assert!(has_rand.rand_below(100) < 100);
|
||||
|
Loading…
x
Reference in New Issue
Block a user