diff --git a/clippy.sh b/clippy.sh new file mode 100755 index 0000000000..88af86df4a --- /dev/null +++ b/clippy.sh @@ -0,0 +1,15 @@ +#!/bin/sh +# Clippy checks +cargo clean +RUST_BACKTRACE=full cargo clippy --all -- \ + -D clippy::pedantic \ + -W missing-docs \ + -W clippy::missing-errors-doc \ + -W clippy::similar-names \ + -A clippy::missing-docs-in-private-items \ + -A clippy::unseparated-literal-suffix \ + -A clippy::module-name-repetitions \ + -A clippy::unreadable-literal \ + -A clippy::if-not-else \ + #--allow clippy::print-with-newline \ + #--allow clippy::write-with-newline \ diff --git a/libafl/build.rs b/libafl/build.rs index ff4a614f3d..f1bf264c6b 100644 --- a/libafl/build.rs +++ b/libafl/build.rs @@ -1,3 +1,5 @@ +//! special handling to build and link libafl + fn main() { #[cfg(target_os = "windows")] windows::build!( diff --git a/libafl/src/bolts/llmp.rs b/libafl/src/bolts/llmp.rs index 479e9b943d..f99823e5f0 100644 --- a/libafl/src/bolts/llmp.rs +++ b/libafl/src/bolts/llmp.rs @@ -1064,6 +1064,7 @@ where } /// Returns the next message, tag, buf, if avaliable, else None + #[allow(clippy::type_complexity)] #[inline] pub fn recv_buf(&mut self) -> Result, Error> { unsafe { @@ -1824,6 +1825,7 @@ where } /// Returns the next message, tag, buf, if avaliable, else None + #[allow(clippy::type_complexity)] #[inline] pub fn recv_buf(&mut self) -> Result, Error> { self.receiver.recv_buf() diff --git a/libafl/src/bolts/os/unix_signals.rs b/libafl/src/bolts/os/unix_signals.rs index 8248306a45..0c149afca8 100644 --- a/libafl/src/bolts/os/unix_signals.rs +++ b/libafl/src/bolts/os/unix_signals.rs @@ -24,6 +24,7 @@ pub use libc::{c_void, siginfo_t}; #[derive(IntoPrimitive, TryFromPrimitive, Clone, Copy)] #[repr(i32)] +#[allow(clippy::clippy::pub_enum_variant_names)] pub enum Signal { SigAbort = SIGABRT, SigBus = SIGBUS, diff --git a/libafl/src/bolts/shmem.rs b/libafl/src/bolts/shmem.rs index 84cf07e5b3..94c5ed52f6 100644 --- a/libafl/src/bolts/shmem.rs +++ b/libafl/src/bolts/shmem.rs @@ -356,6 +356,7 @@ pub mod unix_shmem { } /// Deinitialize this shmem instance + #[allow(clippy::clippy::clippy::unnecessary_cast)] // for c_ types unsafe fn unix_shmem_deinit(shm: *mut UnixShMem) { if shm.is_null() || (*shm).map.is_null() { /* Serialized map id */ @@ -369,6 +370,7 @@ pub mod unix_shmem { /// Functions to create Shared memory region, for observation channels and /// opening inputs and stuff. + #[allow(clippy::clippy::clippy::unnecessary_cast)] // for c_ types unsafe fn unix_shmem_init(shm: *mut UnixShMem, map_size: usize) -> *mut c_uchar { (*shm).map_size = map_size; (*shm).map = ptr::null_mut(); @@ -394,13 +396,14 @@ pub mod unix_shmem { if (*shm).map == -(1 as c_int) as *mut c_void as *mut c_uchar || (*shm).map.is_null() { shmctl((*shm).shm_id, 0 as c_int, ptr::null_mut()); (*shm).shm_id = -(1 as c_int); - (*shm).shm_str[0 as c_int as usize] = 0u8; + (*shm).shm_str[0] = 0u8; return ptr::null_mut(); } (*shm).map } /// Uses a shmap id string to open a shared map + #[allow(clippy::clippy::unnecessary_cast)] // for c_int and c_long unsafe fn unix_shmem_by_str( shm: *mut UnixShMem, shm_str: &CStr, @@ -414,7 +417,7 @@ pub mod unix_shmem { strncpy( (*shm).shm_str.as_mut_ptr() as *mut c_char, shm_str.as_ptr() as *const c_char, - (size_of::<[c_char; 20]>() as c_ulong).wrapping_sub(1 as c_int as c_ulong), + (size_of::<[c_char; 20]>() as c_ulong).wrapping_sub(1 as c_ulong), ); (*shm).shm_id = shm_str .to_str() diff --git a/libafl/src/events/llmp.rs b/libafl/src/events/llmp.rs index cbd113ef30..72797512aa 100644 --- a/libafl/src/events/llmp.rs +++ b/libafl/src/events/llmp.rs @@ -206,6 +206,7 @@ where } /// Handle arriving events in the broker + #[allow(clippy::clippy::unnecessary_wraps)] fn handle_in_broker( stats: &mut ST, sender_id: u32, @@ -398,6 +399,7 @@ where } /// Deserialize the state and corpus tuple, previously serialized with `serialize_state_corpus(...)` +#[allow(clippy::type_complexity)] pub fn deserialize_state_mgr( state_corpus_serialized: &[u8], ) -> Result<(S, LlmpEventManager), Error> @@ -505,6 +507,7 @@ where /// A restarting state is a combination of restarter and runner, that can be used on systems without `fork`. /// The restarter will start a new process each time the child crashes or timeouts. #[cfg(feature = "std")] +#[allow(clippy::clippy::unnecessary_operation)] // for { mgr = LlmpEventManager... } pub fn setup_restarting_mgr( //mgr: &mut LlmpEventManager, stats: ST, @@ -534,43 +537,44 @@ where println!("Doing broker things. Run this tool again to start fuzzing in a client."); mgr.broker_loop()?; return Err(Error::ShuttingDown); - } else { - // We are the fuzzer respawner in a llmp client - mgr.to_env(_ENV_FUZZER_BROKER_CLIENT_INITIAL); + } - // First, create a channel from the fuzzer (sender) to us (receiver) to report its state for restarts. - let sender = LlmpSender::new(0, false)?; - let receiver = LlmpReceiver::on_existing_map( - SH::clone_ref(&sender.out_maps.last().unwrap().shmem)?, - None, - )?; - // Store the information to a map. - sender.to_env(_ENV_FUZZER_SENDER)?; - receiver.to_env(_ENV_FUZZER_RECEIVER)?; + // We are the fuzzer respawner in a llmp client + mgr.to_env(_ENV_FUZZER_BROKER_CLIENT_INITIAL); - let mut ctr: u64 = 0; - // Client->parent loop - loop { - dbg!("Spawning next client (id {})", ctr); + // First, create a channel from the fuzzer (sender) to us (receiver) to report its state for restarts. + let sender = LlmpSender::new(0, false)?; + let receiver = LlmpReceiver::on_existing_map( + SH::clone_ref(&sender.out_maps.last().unwrap().shmem)?, + None, + )?; + // Store the information to a map. + sender.to_env(_ENV_FUZZER_SENDER)?; + receiver.to_env(_ENV_FUZZER_RECEIVER)?; - // On Unix, we fork (todo: measure if that is actually faster.) - #[cfg(unix)] - let _ = match unsafe { fork() }? { - ForkResult::Parent(handle) => handle.status(), - ForkResult::Child => break (sender, receiver), - }; + let mut ctr: u64 = 0; + // Client->parent loop + loop { + dbg!("Spawning next client (id {})", ctr); - // On windows, we spawn ourself again - #[cfg(windows)] - startable_self()?.status()?; + // On Unix, we fork (todo: measure if that is actually faster.) + #[cfg(unix)] + let _ = match unsafe { fork() }? { + ForkResult::Parent(handle) => handle.status(), + ForkResult::Child => break (sender, receiver), + }; - if unsafe { read_volatile(&(*receiver.current_recv_map.page()).size_used) } == 0 { - // Storing state in the last round did not work - panic!("Fuzzer-respawner: Storing state in crashed fuzzer instance did not work, no point to spawn the next client!"); - } + // On windows, we spawn ourself again + #[cfg(windows)] + startable_self()?.status()?; - ctr = ctr.wrapping_add(1); + if unsafe { read_volatile(&(*receiver.current_recv_map.page()).size_used) } == 0 { + // Storing state in the last round did not work + panic!("Fuzzer-respawner: Storing state in crashed fuzzer instance did not work, no point to spawn the next client!"); } + + ctr = ctr.wrapping_add(1); + } } else { // We are the newly started fuzzing instance, first, connect to our own restore map. diff --git a/libafl/src/events/simple.rs b/libafl/src/events/simple.rs index ab0d88cab3..82b7c401bb 100644 --- a/libafl/src/events/simple.rs +++ b/libafl/src/events/simple.rs @@ -73,6 +73,7 @@ where } // Handle arriving events in the broker + #[allow(clippy::unnecessary_wraps)] fn handle_in_broker(stats: &mut ST, event: &Event) -> Result { match event { Event::NewTestcase { diff --git a/libafl/src/executors/mod.rs b/libafl/src/executors/mod.rs index 3c751e080e..b0ac310a55 100644 --- a/libafl/src/executors/mod.rs +++ b/libafl/src/executors/mod.rs @@ -21,7 +21,7 @@ use crate::{ pub enum ExitKind { Ok, Crash, - OOM, + Oom, Timeout, } diff --git a/libafl/src/generators/mod.rs b/libafl/src/generators/mod.rs index f42a6c175a..27c94a1056 100644 --- a/libafl/src/generators/mod.rs +++ b/libafl/src/generators/mod.rs @@ -93,7 +93,7 @@ where /// Generates up to DUMMY_BYTES_MAX non-random dummy bytes (0) fn generate_dummy(&self) -> BytesInput { let size = min(self.max_size, DUMMY_BYTES_MAX); - BytesInput::new(vec![0u8; size]) + BytesInput::new(vec![0_u8; size]) } } diff --git a/libafl/src/inputs/bytes.rs b/libafl/src/inputs/bytes.rs index 5840e783be..03bbaa538b 100644 --- a/libafl/src/inputs/bytes.rs +++ b/libafl/src/inputs/bytes.rs @@ -16,10 +16,11 @@ pub struct BytesInput { impl Input for BytesInput {} + /// Rc Ref-cell from Input -impl Into>> for BytesInput { - fn into(self) -> Rc> { - Rc::new(RefCell::new(self)) +impl From for Rc> { + fn from(input: BytesInput) -> Self { + Rc::new(RefCell::new(input)) } } diff --git a/libafl/src/mutators/scheduled.rs b/libafl/src/mutators/scheduled.rs index 5aefac6747..70b02fe552 100644 --- a/libafl/src/mutators/scheduled.rs +++ b/libafl/src/mutators/scheduled.rs @@ -179,7 +179,7 @@ where /// Create a new StdScheduledMutator instance specifying mutations pub fn new(mutations: MT) -> Self { StdScheduledMutator { - mutations: mutations, + mutations, phantom: PhantomData, } } @@ -377,7 +377,7 @@ where /// Create a new StdScheduledMutator instance without mutations and corpus pub fn new(scheduled: SM) -> Self { Self { - scheduled: scheduled, + scheduled, mutation_log: vec![], phantom: PhantomData, } diff --git a/libafl/src/mutators/token_mutations.rs b/libafl/src/mutators/token_mutations.rs index 240f2afae0..6f8a6bfe9a 100644 --- a/libafl/src/mutators/token_mutations.rs +++ b/libafl/src/mutators/token_mutations.rs @@ -49,6 +49,7 @@ impl Tokens { /// Adds a token to a dictionary, checking it is not a duplicate /// Returns `false` if the token was already present and did not get added. + #[allow(clippy::clippy::ptr_arg)] pub fn add_token(&mut self, token: &Vec) -> bool { if self.token_vec.contains(token) { return false; diff --git a/libafl/src/stages/mutational.rs b/libafl/src/stages/mutational.rs index 9c9b4d3731..f8024b1fe3 100644 --- a/libafl/src/stages/mutational.rs +++ b/libafl/src/stages/mutational.rs @@ -81,6 +81,7 @@ where R: Rand, { mutator: M, + #[allow(clippy::type_complexity)] phantom: PhantomData<(C, CS, E, EM, I, OT, R, S)>, } diff --git a/libafl/src/state/mod.rs b/libafl/src/state/mod.rs index b55cec8fc1..b82e179a9d 100644 --- a/libafl/src/state/mod.rs +++ b/libafl/src/state/mod.rs @@ -25,7 +25,7 @@ use crate::{ use crate::inputs::bytes::BytesInput; /// The maximum size of a testcase -pub const DEFAULT_MAX_SIZE: usize = 1048576; +pub const DEFAULT_MAX_SIZE: usize = 1_048_576; /// Trait for elements offering a corpus pub trait HasCorpus @@ -453,9 +453,9 @@ where where OT: ObserversTuple, { - Ok(self + self .feedbacks_mut() - .is_interesting_all(input, observers, exit_kind)?) + .is_interesting_all(input, observers, exit_kind) } /// Adds this input to the corpus, if it's intersting, and return the index diff --git a/libafl/src/stats/mod.rs b/libafl/src/stats/mod.rs index 6a0883c707..d2a2386907 100644 --- a/libafl/src/stats/mod.rs +++ b/libafl/src/stats/mod.rs @@ -97,14 +97,14 @@ pub trait Stats { fn corpus_size(&self) -> u64 { self.client_stats() .iter() - .fold(0u64, |acc, x| acc + x.corpus_size) + .fold(0_u64, |acc, x| acc + x.corpus_size) } /// Amount of elements in the objectives (combined for all children) fn objective_size(&self) -> u64 { self.client_stats() .iter() - .fold(0u64, |acc, x| acc + x.objective_size) + .fold(0_u64, |acc, x| acc + x.objective_size) } /// Total executions @@ -112,7 +112,7 @@ pub trait Stats { fn total_execs(&mut self) -> u64 { self.client_stats() .iter() - .fold(0u64, |acc, x| acc + x.executions) + .fold(0_u64, |acc, x| acc + x.executions) } /// Executions per second @@ -121,7 +121,7 @@ pub trait Stats { let cur_time = current_time(); self.client_stats_mut() .iter_mut() - .fold(0u64, |acc, x| acc + x.execs_per_sec(cur_time)) + .fold(0_u64, |acc, x| acc + x.execs_per_sec(cur_time)) } /// The client stats for a specific id, creating new if it doesn't exist diff --git a/libafl/src/utils.rs b/libafl/src/utils.rs index 74734333d1..88c18840ec 100644 --- a/libafl/src/utils.rs +++ b/libafl/src/utils.rs @@ -179,6 +179,7 @@ pub struct Xoshiro256StarRand { } impl Rand for Xoshiro256StarRand { + #[allow(clippy::clippy::unreadable_literal)] fn set_seed(&mut self, seed: u64) { self.rand_seed[0] = xxh3_64_with_seed(&HASH_CONST.to_le_bytes(), seed); self.rand_seed[1] = self.rand_seed[0] ^ 0x1234567890abcdef; @@ -223,6 +224,7 @@ pub struct XorShift64Rand { } impl Rand for XorShift64Rand { + #[allow(clippy::clippy::unreadable_literal)] fn set_seed(&mut self, seed: u64) { self.rand_seed = seed ^ 0x1234567890abcdef; } @@ -254,11 +256,13 @@ pub struct Lehmer64Rand { } impl Rand for Lehmer64Rand { + #[allow(clippy::clippy::unreadable_literal)] fn set_seed(&mut self, seed: u64) { self.rand_seed = (seed as u128) ^ 0x1234567890abcdef; } #[inline] + #[allow(clippy::clippy::unreadable_literal)] fn next(&mut self) -> u64 { self.rand_seed *= 0xda942042e4dd58b5; (self.rand_seed >> 64) as u64 @@ -303,6 +307,7 @@ impl Rand for RomuTrioRand { } #[inline] + #[allow(clippy::clippy::unreadable_literal)] fn next(&mut self) -> u64 { let xp = self.x_state; let yp = self.y_state; @@ -339,6 +344,7 @@ impl Rand for RomuDuoJrRand { } #[inline] + #[allow(clippy::clippy::unreadable_literal)] fn next(&mut self) -> u64 { let xp = self.x_state; self.x_state = 15241094284759029579u64.wrapping_mul(self.y_state); diff --git a/libafl_cc/src/lib.rs b/libafl_cc/src/lib.rs index 4898150c66..6c41039300 100644 --- a/libafl_cc/src/lib.rs +++ b/libafl_cc/src/lib.rs @@ -1,36 +1,46 @@ +//! Compiler Wrapper from `LibAFL` + use std::{process::Command, string::String, vec::Vec}; +/// `LibAFL` CC Error Type #[derive(Debug)] pub enum Error { + /// CC Wrapper called with invalid arguments InvalidArguments(String), - IOError(std::io::Error), + /// Io error occurred + Io(std::io::Error), + /// Something else happened Unknown(String), } // TODO macOS +/// extension for static libraries #[cfg(windows)] -pub const LIB_EXT: &'static str = "lib"; +pub const LIB_EXT: &str = "lib"; +/// extension for static libraries #[cfg(not(windows))] -pub const LIB_EXT: &'static str = "a"; +pub const LIB_EXT: &str = "a"; +/// prefix for static libraries #[cfg(windows)] -pub const LIB_PREFIX: &'static str = ""; +pub const LIB_PREFIX: &str = ""; +/// prefix for static libraries #[cfg(not(windows))] -pub const LIB_PREFIX: &'static str = "lib"; +pub const LIB_PREFIX: &str = "lib"; /// Wrap a compiler hijacking its arguments pub trait CompilerWrapper { /// Set the wrapper arguments parsing a command line set of arguments - fn from_args<'a>(&'a mut self, args: &[String]) -> Result<&'a mut Self, Error>; + fn from_args(&mut self, args: &[String]) -> Result<&'_ mut Self, Error>; /// Add a compiler argument - fn add_arg<'a>(&'a mut self, arg: String) -> Result<&'a mut Self, Error>; + fn add_arg(&mut self, arg: String) -> Result<&'_ mut Self, Error>; /// Add a compiler argument only when compiling - fn add_cc_arg<'a>(&'a mut self, arg: String) -> Result<&'a mut Self, Error>; + fn add_cc_arg(&mut self, arg: String) -> Result<&'_ mut Self, Error>; /// Add a compiler argument only when linking - fn add_link_arg<'a>(&'a mut self, arg: String) -> Result<&'a mut Self, Error>; + fn add_link_arg(&mut self, arg: String) -> Result<&'_ mut Self, Error>; /// Command to run the compiler fn command(&mut self) -> Result, Error>; @@ -42,14 +52,14 @@ pub trait CompilerWrapper { fn run(&mut self) -> Result<(), Error> { let args = self.command()?; dbg!(&args); - if args.len() < 1 { + if args.is_empty() { return Err(Error::InvalidArguments( "The number of arguments cannot be 0".into(), )); } let status = match Command::new(&args[0]).args(&args[1..]).status() { Ok(s) => s, - Err(e) => return Err(Error::IOError(e)), + Err(e) => return Err(Error::Io(e)), }; dbg!(status); Ok(()) @@ -57,6 +67,7 @@ pub trait CompilerWrapper { } /// Wrap Clang +#[allow(clippy::clippy::struct_excessive_bools)] pub struct ClangWrapper { optimize: bool, wrapped_cc: String, @@ -73,10 +84,11 @@ pub struct ClangWrapper { link_args: Vec, } +#[allow(clippy::match_same_arms)] // for the linking = false wip for "shared" impl CompilerWrapper for ClangWrapper { fn from_args<'a>(&'a mut self, args: &[String]) -> Result<&'a mut Self, Error> { let mut new_args = vec![]; - if args.len() < 1 { + if args.is_empty() { return Err(Error::InvalidArguments( "The number of arguments cannot be 0".into(), )); @@ -122,17 +134,17 @@ impl CompilerWrapper for ClangWrapper { Ok(self) } - fn add_arg<'a>(&'a mut self, arg: String) -> Result<&'a mut Self, Error> { + fn add_arg(&mut self, arg: String) -> Result<&'_ mut Self, Error> { self.base_args.push(arg); Ok(self) } - fn add_cc_arg<'a>(&'a mut self, arg: String) -> Result<&'a mut Self, Error> { + fn add_cc_arg(&mut self, arg: String) -> Result<&'_ mut Self, Error> { self.cc_args.push(arg); Ok(self) } - fn add_link_arg<'a>(&'a mut self, arg: String) -> Result<&'a mut Self, Error> { + fn add_link_arg(&mut self, arg: String) -> Result<&'_ mut Self, Error> { self.link_args.push(arg); Ok(self) } @@ -165,6 +177,8 @@ impl CompilerWrapper for ClangWrapper { } impl ClangWrapper { + /// Create a new Clang Wrapper + #[must_use] pub fn new(wrapped_cc: &str, wrapped_cxx: &str) -> Self { Self { optimize: true, @@ -181,12 +195,14 @@ impl ClangWrapper { } } - pub fn dont_optimize<'a>(&'a mut self) -> &'a mut Self { + /// Disable optimizations + pub fn dont_optimize(&mut self) -> &'_ mut Self { self.optimize = false; self } - pub fn is_cpp<'a>(&'a mut self) -> &'a mut Self { + /// set cpp mode + pub fn is_cpp(&mut self) -> &'_ mut Self { self.is_cpp = true; self } diff --git a/libafl_targets/build.rs b/libafl_targets/build.rs index 5e95ab0cf2..01caad4adf 100644 --- a/libafl_targets/build.rs +++ b/libafl_targets/build.rs @@ -1,4 +1,4 @@ -// build.rs +//! build.rs for `libafl_targets` use std::env; use std::path::Path; diff --git a/libafl_targets/src/lib.rs b/libafl_targets/src/lib.rs index e817b8a57c..e8f1636554 100644 --- a/libafl_targets/src/lib.rs +++ b/libafl_targets/src/lib.rs @@ -1,3 +1,5 @@ +//! `libafl_targets` contains runtime code, injected in the target itself during compilation. + #[cfg(any(feature = "pcguard_edges", feature = "pcguard_hitcounts"))] pub mod pcguard; #[cfg(any(feature = "pcguard_edges", feature = "pcguard_hitcounts"))]