Tuneable Stage, Scheduler, ScheduledMutator (#874)

* Tuneable Stage, Scheduler, and Mutators

* rename

* fix build

* get rid of prelude

* fmt

* Reworked tunable, fixed stuff, add testcase

* clippy

* further fixes

* fix typo, fmt
This commit is contained in:
Dominik Maier 2022-11-12 03:02:54 +01:00 committed by GitHub
parent fe459f6fa5
commit e5aaf85d3c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 555 additions and 28 deletions

View File

@ -18,9 +18,9 @@ use libafl::{
Error,
};
const _TAG_SIMPLE_U32_V1: Tag = 0x51300321;
const _TAG_MATH_RESULT_V1: Tag = 0x77474331;
const _TAG_1MEG_V1: Tag = 0xB1111161;
const _TAG_SIMPLE_U32_V1: Tag = 0x5130_0321;
const _TAG_MATH_RESULT_V1: Tag = 0x7747_4331;
const _TAG_1MEG_V1: Tag = 0xB111_1161;
#[cfg(all(unix, feature = "std"))]
fn adder_loop(port: u16) -> ! {
@ -71,15 +71,17 @@ fn large_msg_loop(port: u16) -> ! {
let mut client =
llmp::LlmpClient::create_attach_to_tcp(StdShMemProvider::new().unwrap(), port).unwrap();
#[allow(clippy::large_stack_arrays)]
let meg_buf = [1u8; 1 << 20];
loop {
client.send_buf(_TAG_1MEG_V1, &meg_buf).unwrap();
println!("Sending the next megabyte");
thread::sleep(time::Duration::from_millis(100))
thread::sleep(time::Duration::from_millis(100));
}
}
#[allow(clippy::unnecessary_wraps)]
#[cfg(all(unix, feature = "std"))]
fn broker_message_hook(
client_id: u32,
@ -133,20 +135,20 @@ fn main() {
.unwrap_or_else(|| "4242".into())
.parse::<u16>()
.unwrap();
println!("Launching in mode {} on port {}", mode, port);
println!("Launching in mode {mode} on port {port}");
match mode.as_str() {
"broker" => {
let mut broker = llmp::LlmpBroker::new(StdShMemProvider::new().unwrap()).unwrap();
broker.launch_tcp_listener_on(port).unwrap();
broker.loop_forever(&mut broker_message_hook, Some(Duration::from_millis(5)))
broker.loop_forever(&mut broker_message_hook, Some(Duration::from_millis(5)));
}
"b2b" => {
let mut broker = llmp::LlmpBroker::new(StdShMemProvider::new().unwrap()).unwrap();
broker.launch_tcp_listener_on(b2b_port).unwrap();
// connect back to the main broker.
broker.connect_b2b(("127.0.0.1", port)).unwrap();
broker.loop_forever(&mut broker_message_hook, Some(Duration::from_millis(5)))
broker.loop_forever(&mut broker_message_hook, Some(Duration::from_millis(5)));
}
"ctr" => {
let mut client =
@ -158,8 +160,8 @@ fn main() {
client
.send_buf(_TAG_SIMPLE_U32_V1, &counter.to_le_bytes())
.unwrap();
println!("CTR Client writing {}", counter);
thread::sleep(Duration::from_secs(1))
println!("CTR Client writing {counter}");
thread::sleep(Duration::from_secs(1));
}
}
"adder" => {

View File

@ -35,10 +35,10 @@ use crate::{
use crate::{inputs::Input, Error};
/// How to deliver input to an external program
/// `StdIn`: The traget reads from stdin
/// `StdIn`: The target reads from stdin
/// `File`: The target reads from the specified [`InputFile`]
#[derive(Debug, Clone, PartialEq, Eq)]
enum InputLocation {
pub enum InputLocation {
/// Mutate a commandline argument to deliver an input
Arg {
/// The offset of the argument to mutate

View File

@ -14,6 +14,8 @@ pub mod gramatron;
pub use gramatron::*;
pub mod grimoire;
pub use grimoire::*;
pub mod tuneable;
pub use tuneable::*;
#[cfg(feature = "nautilus")]
pub mod nautilus;

View File

@ -644,6 +644,7 @@ where
}
/// Get the next mutation to apply
#[inline]
fn schedule(&self, state: &mut S, _: &S::Input) -> usize {
state
.metadata_mut()

View File

@ -0,0 +1,240 @@
//! An extension to the `ScheduledMutator` which schedules multiple mutations internally.
//! Instead of a random mutator for a random amount of iterations, we can run
//! a specific mutator for a specified amount of iterations
use alloc::vec::Vec;
use core::{
fmt::{self, Debug},
marker::PhantomData,
};
use serde::{Deserialize, Serialize};
pub use crate::mutators::{mutations::*, token_mutations::*};
use crate::{
bolts::rands::Rand,
impl_serdeany,
mutators::{ComposedByMutations, MutationResult, Mutator, MutatorsTuple, ScheduledMutator},
state::{HasMetadata, HasRand, State},
Error,
};
/// Metadata in the state, that controls the behavior of the [`TuneableScheduledMutator`] at runtime
#[derive(Default, Clone, Eq, PartialEq, Debug, Serialize, Deserialize)]
pub struct TuneableScheduledMutatorMetadata {
/// The offsets of mutators to run, in order. Clear to fall back to random.
pub next: Vec<usize>,
/// The next index to read from in the `next` vec
pub next_idx: usize,
/// The count of total mutations to perform.
/// If `next` is of length `10`, and this number is `20`,
/// the mutations will be iterated through twice.
pub iters: Option<u64>,
}
impl TuneableScheduledMutatorMetadata {
/// Gets the stored metadata, used to alter the [`TuneableScheduledMutator`] behavior
pub fn get<S: HasMetadata>(state: &S) -> Result<&Self, Error> {
state
.metadata()
.get::<Self>()
.ok_or_else(|| Error::illegal_state("TuneableScheduledMutator not in use"))
}
/// Gets the stored metadata, used to alter the [`TuneableScheduledMutator`] behavior, mut
pub fn get_mut<S: HasMetadata>(state: &mut S) -> Result<&mut Self, Error> {
state
.metadata_mut()
.get_mut::<Self>()
.ok_or_else(|| Error::illegal_state("TuneableScheduledMutator not in use"))
}
}
impl_serdeany!(TuneableScheduledMutatorMetadata);
/// A [`Mutator`] that schedules one of the embedded mutations on each call.
/// The index of the next mutation can be set.
pub struct TuneableScheduledMutator<MT, S>
where
MT: MutatorsTuple<S>,
S: State + HasRand,
{
mutations: MT,
max_stack_pow: u64,
phantom: PhantomData<S>,
}
impl<MT, S> Debug for TuneableScheduledMutator<MT, S>
where
MT: MutatorsTuple<S>,
S: State + HasRand,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"TuneableScheduledMutator with {} mutations for Input type {}",
self.mutations.len(),
core::any::type_name::<S::Input>()
)
}
}
impl<MT, S> Mutator<S> for TuneableScheduledMutator<MT, S>
where
MT: MutatorsTuple<S>,
S: State + HasRand + HasMetadata,
{
#[inline]
fn mutate(
&mut self,
state: &mut S,
input: &mut S::Input,
stage_idx: i32,
) -> Result<MutationResult, Error> {
self.scheduled_mutate(state, input, stage_idx)
}
}
impl<MT, S> ComposedByMutations<MT, S> for TuneableScheduledMutator<MT, S>
where
MT: MutatorsTuple<S>,
S: State + HasRand,
{
/// Get the mutations
#[inline]
fn mutations(&self) -> &MT {
&self.mutations
}
// Get the mutations (mutable)
#[inline]
fn mutations_mut(&mut self) -> &mut MT {
&mut self.mutations
}
}
impl<MT, S> ScheduledMutator<MT, S> for TuneableScheduledMutator<MT, S>
where
MT: MutatorsTuple<S>,
S: State + HasRand + HasMetadata,
{
/// Compute the number of iterations used to apply stacked mutations
fn iterations(&self, state: &mut S, _: &S::Input) -> u64 {
if let Some(iters) = Self::get_iters(state) {
iters
} else {
// fall back to random
1 << (1 + state.rand_mut().below(self.max_stack_pow))
}
}
/// Get the next mutation to apply
fn schedule(&self, state: &mut S, _: &S::Input) -> usize {
debug_assert!(!self.mutations().is_empty());
// Assumption: we can not reach this code path without previously adding this metadatum.
let metadata = TuneableScheduledMutatorMetadata::get_mut(state).unwrap();
#[allow(clippy::cast_possible_truncation)]
if metadata.next.is_empty() {
// fall back to random if no entries in the vec
state.rand_mut().below(self.mutations().len() as u64) as usize
} else {
let ret = metadata.next[metadata.next_idx];
metadata.next_idx += 1_usize;
if metadata.next_idx >= metadata.next.len() {
metadata.next_idx = 0;
}
debug_assert!(
self.mutations().len() > ret,
"TuneableScheduler: next vec may not contain idx larger than number of mutations!"
);
ret
}
}
}
impl<MT, S> TuneableScheduledMutator<MT, S>
where
MT: MutatorsTuple<S>,
S: State + HasRand + HasMetadata,
{
/// Create a new [`TuneableScheduledMutator`] instance specifying mutations
pub fn new(state: &mut S, mutations: MT) -> Self {
if !state.has_metadata::<TuneableScheduledMutatorMetadata>() {
state.add_metadata(TuneableScheduledMutatorMetadata::default());
}
TuneableScheduledMutator {
mutations,
max_stack_pow: 7,
phantom: PhantomData,
}
}
fn metadata_mut(state: &mut S) -> &mut TuneableScheduledMutatorMetadata {
state
.metadata_mut()
.get_mut::<TuneableScheduledMutatorMetadata>()
.unwrap()
}
fn metadata(state: &S) -> &TuneableScheduledMutatorMetadata {
state
.metadata()
.get::<TuneableScheduledMutatorMetadata>()
.unwrap()
}
/// Sets the next iterations count, i.e., how many times to mutate the input
///
/// Using `set_next_and_iter` to set multiple values at the same time
/// will be faster than setting them individually
/// as it internally only needs a single metadata lookup
pub fn set_iters(state: &mut S, iters: u64) {
let metadata = Self::metadata_mut(state);
metadata.iters = Some(iters);
}
/// Gets the set iterations
pub fn get_iters(state: &S) -> Option<u64> {
let metadata = Self::metadata(state);
metadata.iters
}
/// Resets this to a randomic mutational stage
pub fn reset(state: &mut S) {
let metadata = Self::metadata_mut(state);
metadata.next.clear();
metadata.next_idx = 0;
metadata.iters = None;
}
}
#[cfg(test)]
mod test {
use super::{
BitFlipMutator, ByteDecMutator, TuneableScheduledMutator, TuneableScheduledMutatorMetadata,
};
use crate::{
bolts::tuples::tuple_list,
inputs::BytesInput,
mutators::{ByteRandMutator, ScheduledMutator},
state::NopState,
};
#[test]
fn test_tuning() {
let mut state = NopState::new();
let mutators = tuple_list!(
BitFlipMutator::new(),
ByteDecMutator::new(),
ByteRandMutator::new()
);
let tuneable = TuneableScheduledMutator::new(&mut state, mutators);
let input = BytesInput::new(vec![42]);
let metadata = TuneableScheduledMutatorMetadata::get_mut(&mut state).unwrap();
metadata.next.push(1);
metadata.next.push(2);
assert_eq!(tuneable.schedule(&mut state, &input), 1);
assert_eq!(tuneable.schedule(&mut state, &input), 2);
assert_eq!(tuneable.schedule(&mut state, &input), 1);
}
}

View File

@ -27,6 +27,9 @@ use alloc::borrow::ToOwned;
pub use powersched::PowerQueueScheduler;
pub mod tuneable;
pub use tuneable::*;
use crate::{
bolts::rands::Rand,
corpus::{Corpus, Testcase},

View File

@ -0,0 +1,108 @@
//! The queue corpus scheduler implements an AFL-like queue mechanism
//! The [`TuneableScheduler`] extends the queue scheduler with a method to
//! chose the next corpus entry manually
use alloc::borrow::ToOwned;
use core::marker::PhantomData;
use serde::{Deserialize, Serialize};
use crate::{
corpus::Corpus,
impl_serdeany,
inputs::UsesInput,
schedulers::Scheduler,
state::{HasCorpus, HasMetadata, UsesState},
Error,
};
#[derive(Default, Clone, Copy, Eq, PartialEq, Debug, Serialize, Deserialize)]
struct TuneableSchedulerMetadata {
next: Option<usize>,
}
impl_serdeany!(TuneableSchedulerMetadata);
/// Walk the corpus in a queue-like fashion
/// With the specific `set_next` method, we can chose the next corpus entry manually
#[derive(Debug, Clone)]
pub struct TuneableScheduler<S> {
phantom: PhantomData<S>,
}
impl<S> TuneableScheduler<S>
where
S: HasMetadata + HasCorpus,
{
/// Creates a new `TuneableScheduler`
#[must_use]
pub fn new(state: &mut S) -> Self {
if !state.has_metadata::<TuneableSchedulerMetadata>() {
state.add_metadata(TuneableSchedulerMetadata::default());
}
Self {
phantom: PhantomData,
}
}
fn metadata_mut(state: &mut S) -> &mut TuneableSchedulerMetadata {
state
.metadata_mut()
.get_mut::<TuneableSchedulerMetadata>()
.unwrap()
}
fn metadata(state: &S) -> &TuneableSchedulerMetadata {
state.metadata().get::<TuneableSchedulerMetadata>().unwrap()
}
/// Sets the next corpus id to be used
pub fn set_next(state: &mut S, next: usize) {
Self::metadata_mut(state).next = Some(next);
}
/// Gets the next set corpus id
pub fn get_next(state: &S) -> Option<usize> {
Self::metadata(state).next
}
/// Resets this to a queue scheduler
pub fn reset(state: &mut S) {
let metadata = Self::metadata_mut(state);
metadata.next = None;
}
/// Gets the current corpus entry id
pub fn get_current(state: &S) -> usize {
state.corpus().current().unwrap_or_default()
}
}
impl<S> UsesState for TuneableScheduler<S>
where
S: UsesInput,
{
type State = S;
}
impl<S> Scheduler for TuneableScheduler<S>
where
S: HasCorpus + HasMetadata,
{
/// Gets the next entry in the queue
fn next(&self, state: &mut Self::State) -> Result<usize, Error> {
if state.corpus().count() == 0 {
return Err(Error::empty("No entries in corpus".to_owned()));
}
let id = if let Some(next) = Self::get_next(state) {
// next was set
next
} else if Self::get_current(state) + 1 >= state.corpus().count() {
0
} else {
Self::get_current(state) + 1
};
*state.corpus_mut().current_mut() = Some(id);
Ok(id)
}
}

View File

@ -30,6 +30,9 @@ pub use generalization::GeneralizationStage;
pub mod owned;
pub use owned::StagesOwnedList;
pub mod tuneable;
pub use tuneable::*;
#[cfg(feature = "std")]
pub mod concolic;
#[cfg(feature = "std")]

View File

@ -37,7 +37,7 @@ where
fn mutator_mut(&mut self) -> &mut M;
/// Gets the number of iterations this mutator should run for.
fn iterations(&self, state: &mut Z::State, corpus_idx: usize) -> Result<usize, Error>;
fn iterations(&self, state: &mut Z::State, corpus_idx: usize) -> Result<u64, Error>;
/// Runs this (mutational) stage for the given testcase
#[allow(clippy::cast_possible_wrap)] // more than i32 stages on 32 bit system - highly unlikely...
@ -109,8 +109,8 @@ where
}
/// Gets the number of iterations as a random number
fn iterations(&self, state: &mut Z::State, _corpus_idx: usize) -> Result<usize, Error> {
Ok(1 + state.rand_mut().below(DEFAULT_MUTATIONAL_MAX_ITERATIONS) as usize)
fn iterations(&self, state: &mut Z::State, _corpus_idx: usize) -> Result<u64, Error> {
Ok(1 + state.rand_mut().below(DEFAULT_MUTATIONAL_MAX_ITERATIONS))
}
}

View File

@ -58,10 +58,10 @@ where
/// Gets the number of iterations as a random number
#[allow(clippy::cast_sign_loss)]
fn iterations(&self, state: &mut E::State, corpus_idx: usize) -> Result<usize, Error> {
fn iterations(&self, state: &mut E::State, corpus_idx: usize) -> Result<u64, Error> {
// Update handicap
let mut testcase = state.corpus().get(corpus_idx)?.borrow_mut();
let score = F::compute(&mut *testcase, state)? as usize;
let score = F::compute(&mut *testcase, state)? as u64;
Ok(score)
}

View File

@ -0,0 +1,148 @@
//! A [`crate::stages::MutationalStage`] where the mutator iteration can be tuned at runtime
use core::marker::PhantomData;
use serde::{Deserialize, Serialize};
use crate::{
bolts::rands::Rand,
impl_serdeany,
mutators::Mutator,
stages::{mutational::DEFAULT_MUTATIONAL_MAX_ITERATIONS, MutationalStage, Stage},
state::{HasClientPerfMonitor, HasCorpus, HasMetadata, HasRand, UsesState},
Error, Evaluator,
};
#[derive(Default, Clone, Copy, Eq, PartialEq, Debug, Serialize, Deserialize)]
struct TuneableMutationalStageMetadata {
iters: Option<u64>,
}
impl_serdeany!(TuneableMutationalStageMetadata);
/// Set the number of iterations to be used by this mutational stage
pub fn set_iters<S: HasMetadata>(state: &mut S, iters: u64) -> Result<(), Error> {
let metadata = state
.metadata_mut()
.get_mut::<TuneableMutationalStageMetadata>()
.ok_or_else(|| Error::illegal_state("TuneableMutationslStage not in use"));
metadata.map(|metadata| {
metadata.iters = Some(iters);
})
}
/// Get the set iterations
pub fn get_iters<S: HasMetadata>(state: &S) -> Result<Option<u64>, Error> {
state
.metadata()
.get::<TuneableMutationalStageMetadata>()
.ok_or_else(|| Error::illegal_state("TuneableMutationslStage not in use"))
.map(|metadata| metadata.iters)
}
/// Reset this to a normal, randomized, stage
pub fn reset<S: HasMetadata>(state: &mut S) -> Result<(), Error> {
state
.metadata_mut()
.get_mut::<TuneableMutationalStageMetadata>()
.ok_or_else(|| Error::illegal_state("TuneableMutationslStage not in use"))
.map(|metadata| metadata.iters = None)
}
/// A [`crate::stages::MutationalStage`] where the mutator iteration can be tuned at runtime
#[derive(Clone, Debug)]
pub struct TuneableMutationalStage<E, EM, M, Z> {
mutator: M,
phantom: PhantomData<(E, EM, Z)>,
}
impl<E, EM, M, Z> MutationalStage<E, EM, M, Z> for TuneableMutationalStage<E, EM, M, Z>
where
E: UsesState<State = Z::State>,
EM: UsesState<State = Z::State>,
M: Mutator<Z::State>,
Z: Evaluator<E, EM>,
Z::State: HasClientPerfMonitor + HasCorpus + HasRand + HasMetadata,
{
/// The mutator, added to this stage
#[inline]
fn mutator(&self) -> &M {
&self.mutator
}
/// The list of mutators, added to this stage (as mutable ref)
#[inline]
fn mutator_mut(&mut self) -> &mut M {
&mut self.mutator
}
/// Gets the number of iterations as a random number
#[allow(clippy::cast_possible_truncation)]
fn iterations(&self, state: &mut Z::State, _corpus_idx: usize) -> Result<u64, Error> {
Ok(if let Some(iters) = get_iters(state)? {
iters
} else {
// fall back to random
1 + state.rand_mut().below(DEFAULT_MUTATIONAL_MAX_ITERATIONS)
})
}
}
impl<E, EM, M, Z> UsesState for TuneableMutationalStage<E, EM, M, Z>
where
E: UsesState<State = Z::State>,
EM: UsesState<State = Z::State>,
M: Mutator<Z::State>,
Z: Evaluator<E, EM>,
Z::State: HasClientPerfMonitor + HasCorpus + HasRand,
{
type State = Z::State;
}
impl<E, EM, M, Z> Stage<E, EM, Z> for TuneableMutationalStage<E, EM, M, Z>
where
E: UsesState<State = Z::State>,
EM: UsesState<State = Z::State>,
M: Mutator<Z::State>,
Z: Evaluator<E, EM>,
Z::State: HasClientPerfMonitor + HasCorpus + HasRand + HasMetadata,
{
#[inline]
#[allow(clippy::let_and_return)]
fn perform(
&mut self,
fuzzer: &mut Z,
executor: &mut E,
state: &mut Z::State,
manager: &mut EM,
corpus_idx: usize,
) -> Result<(), Error> {
let ret = self.perform_mutational(fuzzer, executor, state, manager, corpus_idx);
#[cfg(feature = "introspection")]
state.introspection_monitor_mut().finish_stage();
ret
}
}
impl<E, EM, M, Z> TuneableMutationalStage<E, EM, M, Z>
where
E: UsesState<State = Z::State>,
EM: UsesState<State = Z::State>,
M: Mutator<Z::State>,
Z: Evaluator<E, EM>,
Z::State: HasClientPerfMonitor + HasCorpus + HasRand + HasMetadata,
{
/// Creates a new default mutational stage
#[must_use]
pub fn new(state: &mut Z::State, mutator: M) -> Self {
if !state.has_metadata::<TuneableMutationalStageMetadata>() {
state.add_metadata(TuneableMutationalStageMetadata::default());
}
Self {
mutator,
phantom: PhantomData,
}
}
}

View File

@ -9,6 +9,8 @@ use std::{
use serde::{de::DeserializeOwned, Deserialize, Serialize};
#[cfg(test)]
use crate::bolts::rands::StdRand;
use crate::{
bolts::{
rands::Rand,
@ -599,8 +601,11 @@ impl<I, C, R, SC> HasClientPerfMonitor for StdState<I, C, R, SC> {
}
#[cfg(test)]
/// A very simple state without any bells or whistles, for testing.
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct NopState<I> {
metadata: SerdeAnyMap,
rand: StdRand,
phantom: PhantomData<I>,
}
@ -610,6 +615,8 @@ impl<I> NopState<I> {
#[must_use]
pub fn new() -> Self {
NopState {
metadata: SerdeAnyMap::new(),
rand: StdRand::default(),
phantom: PhantomData,
}
}
@ -637,11 +644,24 @@ impl<I> HasExecutions for NopState<I> {
#[cfg(test)]
impl<I> HasMetadata for NopState<I> {
fn metadata(&self) -> &SerdeAnyMap {
unimplemented!()
&self.metadata
}
fn metadata_mut(&mut self) -> &mut SerdeAnyMap {
unimplemented!()
&mut self.metadata
}
}
#[cfg(test)]
impl<I> HasRand for NopState<I> {
type Rand = StdRand;
fn rand(&self) -> &Self::Rand {
&self.rand
}
fn rand_mut(&mut self) -> &mut Self::Rand {
&mut self.rand
}
}

View File

@ -17,7 +17,7 @@ echo "[+] Done fixing build"
echo
echo 'Fixing clippy (might need a "git commit" and a rerun, if "cargo fix" changed the source)'
RUST_BACKTRACE=full cargo +nightly clippy --fix --release --all --all-features --tests -- -Z macro-backtrace \
RUST_BACKTRACE=full cargo +nightly clippy --fix --release --all --all-features --tests --examples --benches -- -Z macro-backtrace \
-D clippy::all \
-D clippy::pedantic \
-W clippy::similar_names \
@ -32,7 +32,7 @@ RUST_BACKTRACE=full cargo +nightly clippy --fix --release --all --all-features -
-A clippy::module-name-repetitions \
-A clippy::unreadable-literal \
cargo +nightly clippy --fix --tests --all-features --allow-dirty --allow-staged
cargo +nightly clippy --fix --tests --examples --benches --all-features --allow-dirty --allow-staged
echo "[+] Done fixing clippy"
echo

View File

@ -1,4 +1,4 @@
cargo clippy --all --all-features --tests -- `
cargo clippy --all --all-features --tests --benches --examples -- `
-D clippy::all `
-D clippy::pedantic `
-W clippy::similar_names `

View File

@ -2,7 +2,7 @@
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
cd "$SCRIPT_DIR/.." || exit 1
RUST_BACKTRACE=full cargo +nightly clippy --all --all-features --release --tests -- -Z macro-backtrace \
RUST_BACKTRACE=full cargo +nightly clippy --all --all-features --release --tests --examples --benches -- -Z macro-backtrace \
-D clippy::all \
-D clippy::pedantic \
-W clippy::similar_names \

View File

@ -2,7 +2,7 @@
# Script to find .rs files that don't get built.
cargo +nightly build --examples --all-features --tests
cargo +nightly build --examples --all-features --tests --examples --benches
# Find all files in deps, then compare to all actual .d files. Ignore a range of files.
grep --no-filename '^[^/].*\.rs:$' target/debug/deps/*.d | sed 's/:$//' | sort -u | diff - <(find . -name '*.rs' | sed 's/\.\///' | sort -u) | grep -Ev '(target/|scripts/|symcc_runtime/|build.rs|fuzzers/)'

View File

@ -15,7 +15,7 @@ fn criterion_benchmark(c: &mut Criterion) {
}
c.bench_function("xxh3", |b| {
b.iter(|| xxh3::xxh3_64_with_seed(black_box(&bench_vec), 0))
b.iter(|| xxh3::xxh3_64_with_seed(black_box(&bench_vec), 0));
});
/*c.bench_function("const_xxh3", |b| {
b.iter(|| const_xxh3::xxh3_64_with_seed(black_box(&bench_vec), 0))
@ -24,15 +24,15 @@ fn criterion_benchmark(c: &mut Criterion) {
b.iter(|| {
let mut hasher = ahash::AHasher::new_with_keys(123, 456);
hasher.write(black_box(&bench_vec));
hasher.finish()
})
hasher.finish();
});
});
c.bench_function("fxhash", |b| {
b.iter(|| {
let mut hasher = rustc_hash::FxHasher::default();
hasher.write(black_box(&bench_vec));
hasher.finish()
})
hasher.finish();
});
});
}