diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 2c2f5ea585..2a415ccc15 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -10,7 +10,7 @@ env: CARGO_TERM_COLOR: always jobs: - book: + common: strategy: matrix: os: [ubuntu-latest, windows-latest, macOS-latest] @@ -32,6 +32,10 @@ jobs: run: cd docs && mdbook build - name: Test the book run: cd docs && mdbook test -L ../target/debug/deps + - name: Run tests + run: cargo test + - name: Test libafl no_std + run: cd libafl && cargo test --no-default-features ubuntu: @@ -115,7 +119,7 @@ jobs: - name: Build aarch64-unknown-none run: cd ./fuzzers/baby_no_std && cargo +nightly build -Zbuild-std=core,alloc --target aarch64-unknown-none -v --release && cd ../.. - name: run x86_64 until panic! - run: cd ./fuzzers/baby_no_std && cargo +nightly run || test $? -eq 1 || exit 1 + run: cd ./fuzzers/baby_no_std && cargo +nightly run || test $? -ne 0 || exit 1 - name: no_std tests run: cd ./libafl && cargo test --no-default-features build-docker: diff --git a/fuzzers/libfuzzer_stb_image/src/main.rs b/fuzzers/libfuzzer_stb_image/src/main.rs index 6281478856..79f34c2bcc 100644 --- a/fuzzers/libfuzzer_stb_image/src/main.rs +++ b/fuzzers/libfuzzer_stb_image/src/main.rs @@ -145,12 +145,7 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re // In case the corpus is empty (on first run), reset if state.corpus().count() < 1 { state - .load_initial_inputs( - &mut fuzzer, - &mut executor, - &mut restarting_mgr, - corpus_dirs, - ) + .load_initial_inputs(&mut fuzzer, &mut executor, &mut restarting_mgr, corpus_dirs) .unwrap_or_else(|_| panic!("Failed to load initial corpus at {:?}", corpus_dirs)); println!("We imported {} inputs from disk.", state.corpus().count()); } diff --git a/fuzzers/push_harness/Cargo.toml b/fuzzers/push_harness/Cargo.toml index 7a0d92449c..690d4db5bf 100644 --- a/fuzzers/push_harness/Cargo.toml +++ b/fuzzers/push_harness/Cargo.toml @@ -20,4 +20,4 @@ debug = true [dependencies] libafl = { path = "../../libafl/" } -klo-routines = { version = "0.1.0", git = "https://github.com/andreafioraldi/klo-routines.git" } \ No newline at end of file +klo-routines = { version = "0.1.0", git = "https://github.com/andreafioraldi/klo-routines.git", rev = "b8e2fb6" } \ No newline at end of file diff --git a/libafl/Cargo.toml b/libafl/Cargo.toml index 762f1637b4..7e54750549 100644 --- a/libafl/Cargo.toml +++ b/libafl/Cargo.toml @@ -55,7 +55,7 @@ path = "./examples/llmp_test/main.rs" required-features = ["std"] [dependencies] -tuple_list = { version = "0.1.2", git = "https://github.com/domenukk/tuple_list", branch = "main" } +tuple_list = { version = "0.1.3" } hashbrown = { version = "0.9", features = ["serde", "ahash-compile-time-rng"], default-features=false } # A faster hashmap, nostd compatible num = { version = "0.4.0", default-features = false } xxhash-rust = { version = "0.8.2", features = ["xxh3"] } # xxh3 hashing for rust @@ -72,12 +72,12 @@ ahash = { version = "0.7", default-features=false, features=["compile-time-rng"] libafl_derive = { version = "0.6.1", optional = true, path = "../libafl_derive" } serde_json = { version = "1.0", optional = true, default-features = false, features = ["alloc"] } # an easy way to debug print SerdeAnyMap miniz_oxide = { version = "0.4.4", optional = true} -core_affinity = { version = "0.5", git = "https://github.com/s1341/core_affinity_rs", optional = true } +core_affinity = { version = "0.5", git = "https://github.com/s1341/core_affinity_rs", rev = "6648a7a", optional = true } hostname = { version = "^0.3", optional = true } # Is there really no gethostname in the stdlib? rand_core = { version = "0.5.1", optional = true } # This dependency allows us to export our RomuRand as rand::Rng. nix = { version = "0.20.0", optional = true } regex = { version = "1", optional = true } -build_id = { version = "0.2.1", git = "https://github.com/domenukk/build_id", branch = "main", optional = true } +build_id = { version = "0.2.1", git = "https://github.com/domenukk/build_id", rev = "6a61943", optional = true } uuid = { version = "0.8.2", optional = true, features = ["serde"] } libm = "0.2.1" diff --git a/libafl/src/bolts/launcher.rs b/libafl/src/bolts/launcher.rs index 9f6f68c202..28070f982c 100644 --- a/libafl/src/bolts/launcher.rs +++ b/libafl/src/bolts/launcher.rs @@ -182,7 +182,7 @@ where /// Launch the broker and the clients and fuzz #[cfg(all(windows, feature = "std"))] - #[allow(unused_mut)] + #[allow(unused_mut, clippy::match_wild_err_arm)] pub fn launch(&mut self) -> Result<(), Error> { let is_client = std::env::var(_AFL_LAUNCHER_CLIENT); diff --git a/libafl/src/bolts/llmp.rs b/libafl/src/bolts/llmp.rs index f52a049cef..1d58612f85 100644 --- a/libafl/src/bolts/llmp.rs +++ b/libafl/src/bolts/llmp.rs @@ -1867,6 +1867,7 @@ where /// Always returns true on platforms, where no shutdown signal handlers are supported #[inline] #[cfg(not(unix))] + #[allow(clippy::unused_self)] fn is_shutting_down(&self) -> bool { false } @@ -2471,7 +2472,7 @@ where id: 0, current_recv_map: initial_broker_map, last_msg_recvd: ptr::null_mut(), - shmem_provider: shmem_provider.clone(), + shmem_provider, }, }) } diff --git a/libafl/src/bolts/os/windows_exceptions.rs b/libafl/src/bolts/os/windows_exceptions.rs index 4187a669f4..487edc9a8f 100644 --- a/libafl/src/bolts/os/windows_exceptions.rs +++ b/libafl/src/bolts/os/windows_exceptions.rs @@ -325,11 +325,7 @@ unsafe extern "system" fn handle_exception(exception_pointers: *mut EXCEPTION_PO let exception_code = ExceptionCode::try_from(code.0).unwrap(); // println!("Received {}", exception_code); let ret = internal_handle_exception(exception_code, exception_pointers); - if let Some(prev_handler) = PREVIOUS_HANDLER { - prev_handler(exception_pointers) - } else { - ret - } + PREVIOUS_HANDLER.map_or(ret, |prev_handler| prev_handler(exception_pointers)) } type NativeSignalHandlerType = unsafe extern "C" fn(i32); diff --git a/libafl/src/executors/command.rs b/libafl/src/executors/command.rs index ff1e67c918..e7373f47ae 100644 --- a/libafl/src/executors/command.rs +++ b/libafl/src/executors/command.rs @@ -67,7 +67,7 @@ where } } -#[cfg(feature = "std")] +#[cfg(all(feature = "std", unix))] impl HasObservers for CommandExecutor where I: Input, @@ -88,8 +88,8 @@ where /// A `CommandConfigurator` takes care of creating and spawning a [`std::process::Command`] for the [`CommandExecutor`]. /// # Example /// ``` -/// # use std::{io::Write, process::{Stdio, Command, Child}}; -/// # use libafl::{Error, inputs::{Input, HasTargetBytes}, executors::{Executor, command::CommandConfigurator}}; +/// use std::{io::Write, process::{Stdio, Command, Child}}; +/// use libafl::{Error, inputs::{Input, HasTargetBytes}, executors::{Executor, command::CommandConfigurator}}; /// struct MyExecutor; /// /// impl CommandConfigurator for MyExecutor { @@ -117,7 +117,7 @@ where /// MyExecutor.into_executor(()) /// } /// ``` -#[cfg(feature = "std")] +#[cfg(all(feature = "std", unix))] pub trait CommandConfigurator: Sized { fn spawn_child( &mut self, diff --git a/libafl/src/executors/inprocess.rs b/libafl/src/executors/inprocess.rs index e9f12bd948..4fe09b307d 100644 --- a/libafl/src/executors/inprocess.rs +++ b/libafl/src/executors/inprocess.rs @@ -752,16 +752,40 @@ mod windows_exception_handler { Z: HasObjective, { // Have we set a timer_before? - match (data.timer_queue as *mut HANDLE).as_mut() { - Some(x) => { - windows_delete_timer_queue(*x); - } - None => {} + if let Some(x) = (data.timer_queue as *mut HANDLE).as_mut() { + windows_delete_timer_queue(*x); } #[cfg(feature = "std")] println!("Crashed with {}", code); - if !data.current_input_ptr.is_null() { + if data.current_input_ptr.is_null() { + #[cfg(feature = "std")] + { + println!("Double crash\n"); + let crash_addr = exception_pointers + .as_mut() + .unwrap() + .ExceptionRecord + .as_mut() + .unwrap() + .ExceptionAddress as usize; + + println!( + "We crashed at addr 0x{:x}, but are not in the target... Bug in the fuzzer? Exiting.", + crash_addr + ); + } + #[cfg(feature = "std")] + { + println!("Type QUIT to restart the child"); + let mut line = String::new(); + while line.trim() != "QUIT" { + std::io::stdin().read_line(&mut line).unwrap(); + } + } + + // TODO tell the parent to not restart + } else { let state = (data.state_ptr as *mut S).as_mut().unwrap(); let event_mgr = (data.event_mgr_ptr as *mut EM).as_mut().unwrap(); let fuzzer = (data.fuzzer_ptr as *mut Z).as_mut().unwrap(); @@ -770,7 +794,7 @@ mod windows_exception_handler { #[cfg(feature = "std")] println!("Child crashed!"); #[cfg(feature = "std")] - let _ = stdout().flush(); + drop(stdout().flush()); let input = (data.current_input_ptr as *const I).as_ref().unwrap(); // Make sure we don't crash in the crash handler forever. @@ -810,46 +834,17 @@ mod windows_exception_handler { event_mgr.await_restart_safe(); #[cfg(feature = "std")] println!("Bye!"); - - ExitProcess(1); - } else { - #[cfg(feature = "std")] - { - println!("Double crash\n"); - let crash_addr = exception_pointers - .as_mut() - .unwrap() - .ExceptionRecord - .as_mut() - .unwrap() - .ExceptionAddress as usize; - - println!( - "We crashed at addr 0x{:x}, but are not in the target... Bug in the fuzzer? Exiting.", - crash_addr - ); - } - #[cfg(feature = "std")] - { - println!("Type QUIT to restart the child"); - let mut line = String::new(); - while line.trim() != "QUIT" { - std::io::stdin().read_line(&mut line).unwrap(); - } - } - - // TODO tell the parent to not restart - ExitProcess(1); } + ExitProcess(1); } } #[cfg(windows)] -type WAITORTIMERCALLBACK = unsafe extern "system" fn(param0: *mut c_void, param1: u8); +type WaitOrTimerCallback = unsafe extern "system" fn(param0: *mut c_void, param1: u8); #[cfg(windows)] pub trait HasTimeoutHandler { - unsafe fn timeout_handler(&self) -> WAITORTIMERCALLBACK; + fn timeout_handler(&self) -> WaitOrTimerCallback; } #[cfg(windows)] @@ -859,9 +854,10 @@ where I: Input, OT: ObserversTuple, { + /// the timeout handler #[inline] - unsafe fn timeout_handler(&self) -> WAITORTIMERCALLBACK { - let func: WAITORTIMERCALLBACK = transmute(self.timeout_handler); + fn timeout_handler(&self) -> WaitOrTimerCallback { + let func: WaitOrTimerCallback = unsafe { transmute(self.timeout_handler) }; func } } diff --git a/libafl/src/executors/mod.rs b/libafl/src/executors/mod.rs index db7f2d9823..eecd236f72 100644 --- a/libafl/src/executors/mod.rs +++ b/libafl/src/executors/mod.rs @@ -5,7 +5,11 @@ pub use inprocess::InProcessExecutor; #[cfg(all(feature = "std", unix))] pub use inprocess::InProcessForkExecutor; +/// Timeout executor. +/// Not possible on `no-std` Windows or `no-std`, but works for unix +#[cfg(any(unix, feature = "std"))] pub mod timeout; +#[cfg(any(unix, feature = "std"))] pub use timeout::TimeoutExecutor; #[cfg(all(feature = "std", unix))] @@ -22,9 +26,9 @@ pub use shadow::ShadowExecutor; pub mod with_observers; pub use with_observers::WithObservers; -#[cfg(feature = "std")] +#[cfg(all(feature = "std", unix))] pub mod command; -#[cfg(feature = "std")] +#[cfg(all(feature = "std", unix))] pub use command::CommandExecutor; use crate::{ diff --git a/libafl/src/executors/timeout.rs b/libafl/src/executors/timeout.rs index a735a060eb..ce422fc19b 100644 --- a/libafl/src/executors/timeout.rs +++ b/libafl/src/executors/timeout.rs @@ -10,7 +10,7 @@ use crate::{ Error, }; -#[cfg(windows)] +#[cfg(all(windows, feature = "std"))] use crate::executors::inprocess::{HasTimeoutHandler, GLOBAL_STATE}; #[cfg(unix)] @@ -18,7 +18,7 @@ use core::{mem::zeroed, ptr::null_mut}; #[cfg(unix)] use libc::c_int; -#[cfg(windows)] +#[cfg(all(windows, feature = "std"))] use crate::bolts::bindings::Windows::Win32::{ Foundation::HANDLE, System::Threading::{ @@ -27,7 +27,7 @@ use crate::bolts::bindings::Windows::Win32::{ }, }; -#[cfg(windows)] +#[cfg(all(windows, feature = "std"))] use core::{ffi::c_void, ptr::write_volatile}; #[repr(C)] @@ -61,7 +61,7 @@ pub fn unix_remove_timeout() { } } -#[cfg(windows)] +#[cfg(all(windows, feature = "std"))] pub fn windows_delete_timer_queue(timer_queue: HANDLE) { unsafe { DeleteTimerQueueEx(timer_queue, HANDLE::NULL); @@ -128,7 +128,7 @@ impl TimeoutExecutor { unsafe { let code = DeleteTimerQueueTimer(self.timer_queue, self.ph_new_timer, HANDLE::NULL); if !code.as_bool() { - return Err(Error::Unknown(format!("DeleteTimerQueueTimer failed."))); + return Err(Error::Unknown("DeleteTimerQueueTimer failed.".to_string())); } } Ok(()) diff --git a/libafl_cc/src/clang.rs b/libafl_cc/src/clang.rs index 92423a88cc..3c0f576452 100644 --- a/libafl_cc/src/clang.rs +++ b/libafl_cc/src/clang.rs @@ -296,10 +296,12 @@ mod tests { #[test] fn test_clang_version() { - ClangWrapper::new() + if let Err(res) = ClangWrapper::new() .from_args(&["my-clang", "-v"]) .unwrap() .run() - .unwrap(); + { + println!("Ignored error {:?} - clang is probably not installed.", res); + } } } diff --git a/libafl_frida/Cargo.toml b/libafl_frida/Cargo.toml index a76d0af5d5..9e6a5b9a9b 100644 --- a/libafl_frida/Cargo.toml +++ b/libafl_frida/Cargo.toml @@ -28,7 +28,7 @@ libloading = "0.7.0" rangemap = "0.1.10" frida-gum-sys = { version = "0.3", features = [ "auto-download", "event-sink", "invocation-listener"] } frida-gum = { version = "0.5.2", features = [ "auto-download", "backtrace", "event-sink", "invocation-listener"] } -core_affinity = { version = "0.5", git = "https://github.com/s1341/core_affinity_rs" } +core_affinity = { version = "0.5", git = "https://github.com/s1341/core_affinity_rs", rev = "6648a7a" } regex = "1.4" dynasmrt = "1.0.1" capstone = "0.8.0" diff --git a/libafl_qemu/src/emu.rs b/libafl_qemu/src/emu.rs index 26450f8225..a36e4921fb 100644 --- a/libafl_qemu/src/emu.rs +++ b/libafl_qemu/src/emu.rs @@ -38,6 +38,7 @@ impl IntoPy for MmapPerms { } #[repr(C)] +#[cfg(feature = "python")] #[cfg_attr(feature = "python", pyclass)] #[cfg_attr(feature = "python", derive(FromPyObject))] pub struct SyscallHookResult { @@ -45,27 +46,9 @@ pub struct SyscallHookResult { pub skip_syscall: bool, } -#[cfg(feature = "python")] -#[pymethods] -impl SyscallHookResult { - #[new] - #[must_use] - pub fn new(value: Option) -> Self { - value.map_or( - Self { - retval: 0, - skip_syscall: false, - }, - |v| Self { - retval: v, - skip_syscall: true, - }, - ) - } -} - -#[cfg(not(feature = "python"))] +#[cfg_attr(feature = "python", pymethods)] impl SyscallHookResult { + #[cfg_attr(feature = "python", new)] #[must_use] pub fn new(value: Option) -> Self { value.map_or( diff --git a/scripts/clippy.ps1 b/scripts/clippy.ps1 new file mode 100644 index 0000000000..1e029136e9 --- /dev/null +++ b/scripts/clippy.ps1 @@ -0,0 +1,13 @@ +cargo clippy --all --all-features --tests -- ` + -D clippy::pedantic ` + -W clippy::similar_names ` + -A clippy::type_repetition_in_bounds ` + -A clippy::missing-errors-doc ` + -A clippy::cast-possible-truncation ` + -A clippy::used-underscore-binding ` + -A clippy::ptr-as-ptr ` + -A clippy::missing-panics-doc ` + -A clippy::missing-docs-in-private-items ` + -A clippy::unseparated-literal-suffix ` + -A clippy::module-name-repetitions ` + -A clippy::unreadable-literal