diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 755ac75d89..555d559d9e 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -223,6 +223,7 @@ jobs: steps: - uses: actions/checkout@v4 - uses: taiki-e/install-action@cargo-hack + - run: rustup upgrade # Note: We currently only specify minimum rust versions for the default workspace members - run: cargo hack check --rust-version -p libafl -p libafl_bolts -p libafl_derive -p libafl_cc -p libafl_targets diff --git a/.gitignore b/.gitignore index de5478a871..71fcadb3f5 100644 --- a/.gitignore +++ b/.gitignore @@ -74,6 +74,5 @@ libafl_nyx/packer harness program fuzzer_libpng* -forkserver_simple *.patch diff --git a/bindings/pylibafl/Cargo.toml b/bindings/pylibafl/Cargo.toml index b13c6cf5ad..a05351889f 100644 --- a/bindings/pylibafl/Cargo.toml +++ b/bindings/pylibafl/Cargo.toml @@ -5,7 +5,7 @@ version = "0.15.1" license = "MIT OR Apache-2.0" repository = "https://github.com/AFLplusplus/LibAFL/" keywords = ["fuzzing", "testing", "security", "python"] -edition = "2021" +edition = "2024" categories = ["development-tools::testing", "emulators", "embedded", "os"] [dependencies] diff --git a/docs/src/advanced_features/no_std.md b/docs/src/advanced_features/no_std.md index 529e4148fd..38c7267604 100644 --- a/docs/src/advanced_features/no_std.md +++ b/docs/src/advanced_features/no_std.md @@ -31,7 +31,7 @@ Here, we use it in Rust. `external_current_millis` is then called from LibAFL. Note that it needs to be `no_mangle` in order to get picked up by LibAFL at linktime: ```rust,ignore -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn external_current_millis() -> u64 { unsafe { my_real_seconds()*1000 } } diff --git a/docs/src/core_concepts/executor.md b/docs/src/core_concepts/executor.md index ce0c800dda..6f42286ae0 100644 --- a/docs/src/core_concepts/executor.md +++ b/docs/src/core_concepts/executor.md @@ -32,7 +32,9 @@ As you can see from the forkserver example, //Coverage map shared between observer and executor let mut shmem = StdShMemProvider::new().unwrap().new_shmem(MAP_SIZE).unwrap(); //let the forkserver know the shmid -shmem.write_to_env("__AFL_SHM_ID").unwrap(); +unsafe { + shmem.write_to_env("__AFL_SHM_ID").unwrap(); +} let mut shmem_buf = shmem.as_slice_mut(); ``` diff --git a/fuzzers/baby/baby_fuzzer_swap_differential/Cargo.toml b/fuzzers/baby/baby_fuzzer_swap_differential/Cargo.toml index 333f3ce50e..efcccaa4aa 100644 --- a/fuzzers/baby/baby_fuzzer_swap_differential/Cargo.toml +++ b/fuzzers/baby/baby_fuzzer_swap_differential/Cargo.toml @@ -21,7 +21,7 @@ debug = true [build-dependencies] anyhow = "1.0.89" -bindgen = "0.70.1" +bindgen = "0.71.1" cc = "=1.2.7" # fix me later [dependencies] diff --git a/fuzzers/baby/backtrace_baby_fuzzers/forkserver_executor/src/main.rs b/fuzzers/baby/backtrace_baby_fuzzers/forkserver_executor/src/main.rs index 600056c412..0c99d60f14 100644 --- a/fuzzers/baby/backtrace_baby_fuzzers/forkserver_executor/src/main.rs +++ b/fuzzers/baby/backtrace_baby_fuzzers/forkserver_executor/src/main.rs @@ -40,7 +40,9 @@ pub fn main() { let mut shmem = shmem_provider.new_shmem(MAP_SIZE).unwrap(); //let the forkserver know the shmid - shmem.write_to_env("__AFL_SHM_ID").unwrap(); + unsafe { + shmem.write_to_env("__AFL_SHM_ID").unwrap(); + } let shmem_map: &mut [u8; MAP_SIZE] = shmem .as_slice_mut() .try_into() diff --git a/fuzzers/forkserver/forkserver_libafl_cc/src/main.rs b/fuzzers/forkserver/forkserver_libafl_cc/src/main.rs index 6d5f7f3998..910345a4a9 100644 --- a/fuzzers/forkserver/forkserver_libafl_cc/src/main.rs +++ b/fuzzers/forkserver/forkserver_libafl_cc/src/main.rs @@ -97,7 +97,9 @@ pub fn main() { // The coverage map shared between observer and executor let mut shmem = shmem_provider.new_shmem(MAP_SIZE).unwrap(); // let the forkserver know the shmid - shmem.write_to_env("__AFL_SHM_ID").unwrap(); + unsafe { + shmem.write_to_env("__AFL_SHM_ID").unwrap(); + } let shmem_buf = shmem.as_slice_mut(); // the next line is not needed // unsafe { EDGES_MAP_PTR = shmem_buf.as_mut_ptr() }; diff --git a/fuzzers/forkserver/forkserver_simple/Cargo.toml b/fuzzers/forkserver/forkserver_simple/Cargo.toml index 073744a200..926725324d 100644 --- a/fuzzers/forkserver/forkserver_simple/Cargo.toml +++ b/fuzzers/forkserver/forkserver_simple/Cargo.toml @@ -2,7 +2,7 @@ name = "forkserver_simple" version = "0.14.1" authors = ["tokatoka "] -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/fuzzers/forkserver/forkserver_simple/build.rs b/fuzzers/forkserver/forkserver_simple/build.rs index dc8c8dd146..bda99090a8 100644 --- a/fuzzers/forkserver/forkserver_simple/build.rs +++ b/fuzzers/forkserver/forkserver_simple/build.rs @@ -1,7 +1,7 @@ use std::{ env, path::Path, - process::{exit, Command}, + process::{Command, exit}, }; const AFL_URL: &str = "https://github.com/AFLplusplus/AFLplusplus"; @@ -12,7 +12,9 @@ fn main() { exit(0); } - env::remove_var("DEBUG"); + unsafe { + env::remove_var("DEBUG"); + } let cwd = env::current_dir().unwrap().to_string_lossy().to_string(); let afl = format!("{}/AFLplusplus", &cwd); diff --git a/fuzzers/forkserver/forkserver_simple/src/main.rs b/fuzzers/forkserver/forkserver_simple/src/main.rs index c08b44084b..1bb66514bf 100644 --- a/fuzzers/forkserver/forkserver_simple/src/main.rs +++ b/fuzzers/forkserver/forkserver_simple/src/main.rs @@ -3,27 +3,26 @@ use std::path::PathBuf; use clap::Parser; use libafl::{ + HasMetadata, corpus::{Corpus, InMemoryCorpus, OnDiskCorpus}, events::SimpleEventManager, - executors::{forkserver::ForkserverExecutor, HasObservers}, + executors::{HasObservers, forkserver::ForkserverExecutor}, feedback_and_fast, feedback_or, feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback}, fuzzer::{Fuzzer, StdFuzzer}, inputs::BytesInput, monitors::SimpleMonitor, - mutators::{havoc_mutations, tokens_mutations, StdScheduledMutator, Tokens}, + mutators::{StdScheduledMutator, Tokens, havoc_mutations, tokens_mutations}, observers::{CanTrack, HitcountsMapObserver, StdMapObserver, TimeObserver}, schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler}, stages::mutational::StdMutationalStage, state::{HasCorpus, StdState}, - HasMetadata, }; use libafl_bolts::{ - current_nanos, + AsSliceMut, Truncate, current_nanos, rands::StdRand, shmem::{ShMem, ShMemProvider, UnixShMemProvider}, - tuples::{tuple_list, Handled, Merge}, - AsSliceMut, Truncate, + tuples::{Handled, Merge, tuple_list}, }; use nix::sys::signal::Signal; @@ -97,7 +96,9 @@ pub fn main() { // The coverage map shared between observer and executor let mut shmem = shmem_provider.new_shmem(MAP_SIZE).unwrap(); // let the forkserver know the shmid - shmem.write_to_env("__AFL_SHM_ID").unwrap(); + unsafe { + shmem.write_to_env("__AFL_SHM_ID").unwrap(); + } let shmem_buf = shmem.as_slice_mut(); // Create an observation channel using the signals map diff --git a/fuzzers/forkserver/fuzzbench_forkserver/src/main.rs b/fuzzers/forkserver/fuzzbench_forkserver/src/main.rs index f47334b429..c321c4cb0d 100644 --- a/fuzzers/forkserver/fuzzbench_forkserver/src/main.rs +++ b/fuzzers/forkserver/fuzzbench_forkserver/src/main.rs @@ -242,7 +242,9 @@ fn fuzz( // The coverage map shared between observer and executor let mut shmem = shmem_provider.new_shmem(MAP_SIZE).unwrap(); // let the forkserver know the shmid - shmem.write_to_env("__AFL_SHM_ID").unwrap(); + unsafe { + shmem.write_to_env("__AFL_SHM_ID").unwrap(); + } let shmem_buf = shmem.as_slice_mut(); // To let know the AFL++ binary that we have a big map std::env::set_var("AFL_MAP_SIZE", format!("{}", MAP_SIZE)); @@ -348,7 +350,9 @@ fn fuzz( // The cmplog map shared between observer and executor let mut cmplog_shmem = shmem_provider.uninit_on_shmem::().unwrap(); // let the forkserver know the shmid - cmplog_shmem.write_to_env("__AFL_CMPLOG_SHM_ID").unwrap(); + unsafe { + cmplog_shmem.write_to_env("__AFL_CMPLOG_SHM_ID").unwrap(); + } let cmpmap = unsafe { OwnedRefMut::::from_shmem(&mut cmplog_shmem) }; let cmplog_observer = StdCmpObserver::new("cmplog", cmpmap, true); diff --git a/fuzzers/forkserver/fuzzbench_forkserver_cmplog/src/main.rs b/fuzzers/forkserver/fuzzbench_forkserver_cmplog/src/main.rs index 70db2c148a..65b9e75c86 100644 --- a/fuzzers/forkserver/fuzzbench_forkserver_cmplog/src/main.rs +++ b/fuzzers/forkserver/fuzzbench_forkserver_cmplog/src/main.rs @@ -244,7 +244,9 @@ fn fuzz( // The coverage map shared between observer and executor let mut shmem = shmem_provider.new_shmem(MAP_SIZE).unwrap(); // let the forkserver know the shmid - shmem.write_to_env("__AFL_SHM_ID").unwrap(); + unsafe { + shmem.write_to_env("__AFL_SHM_ID").unwrap(); + } let shmem_buf = shmem.as_slice_mut(); // To let know the AFL++ binary that we have a big map std::env::set_var("AFL_MAP_SIZE", format!("{MAP_SIZE}")); @@ -351,7 +353,9 @@ fn fuzz( // The cmplog map shared between observer and executor let mut cmplog_shmem = shmem_provider.uninit_on_shmem::().unwrap(); // let the forkserver know the shmid - cmplog_shmem.write_to_env("__AFL_CMPLOG_SHM_ID").unwrap(); + unsafe { + cmplog_shmem.write_to_env("__AFL_CMPLOG_SHM_ID").unwrap(); + } let cmpmap = unsafe { OwnedRefMut::from_shmem(&mut cmplog_shmem) }; let cmplog_observer = AFLppCmpLogObserver::new("cmplog", cmpmap, true); diff --git a/fuzzers/forkserver/libafl-fuzz/src/executor.rs b/fuzzers/forkserver/libafl-fuzz/src/executor.rs index 71bcdb2f1f..b511be315c 100644 --- a/fuzzers/forkserver/libafl-fuzz/src/executor.rs +++ b/fuzzers/forkserver/libafl-fuzz/src/executor.rs @@ -200,7 +200,7 @@ pub fn find_afl_binary(filename: &str, same_dir_as: Option) -> Result

"-", - Some(ref p) => match p.as_str() { + Some(p) => match p.as_str() { "0" => opt.executable.to_str().unwrap(), _ => p, }, @@ -468,7 +475,9 @@ define_run_client!(state, mgr, fuzzer_dir, core_id, opt, is_main_node, { let mut cmplog_shmem = shmem_provider.uninit_on_shmem::().unwrap(); // Let the Forkserver know the CmpLog shared memory map ID. - cmplog_shmem.write_to_env("__AFL_CMPLOG_SHM_ID").unwrap(); + unsafe { + cmplog_shmem.write_to_env("__AFL_CMPLOG_SHM_ID").unwrap(); + } let cmpmap = unsafe { OwnedRefMut::from_shmem(&mut cmplog_shmem) }; // Create the CmpLog observer. diff --git a/fuzzers/inprocess/fuzzbench/Cargo.toml b/fuzzers/inprocess/fuzzbench/Cargo.toml index 3b52752b0c..b71e879e4f 100644 --- a/fuzzers/inprocess/fuzzbench/Cargo.toml +++ b/fuzzers/inprocess/fuzzbench/Cargo.toml @@ -5,7 +5,7 @@ authors = [ "Andrea Fioraldi ", "Dominik Maier ", ] -edition = "2021" +edition = "2024" [features] default = ["std"] diff --git a/fuzzers/inprocess/fuzzbench/src/bin/libafl_cc.rs b/fuzzers/inprocess/fuzzbench/src/bin/libafl_cc.rs index 972c99c9a4..63753702c2 100644 --- a/fuzzers/inprocess/fuzzbench/src/bin/libafl_cc.rs +++ b/fuzzers/inprocess/fuzzbench/src/bin/libafl_cc.rs @@ -8,10 +8,15 @@ pub fn main() { let mut dir = env::current_exe().unwrap(); let wrapper_name = dir.file_name().unwrap().to_str().unwrap(); - let is_cpp = match wrapper_name[wrapper_name.len()-2..].to_lowercase().as_str() { + let is_cpp = match wrapper_name[wrapper_name.len() - 2..] + .to_lowercase() + .as_str() + { "cc" => false, "++" | "pp" | "xx" => true, - _ => panic!("Could not figure out if c or c++ wrapper was called. Expected {dir:?} to end with c or cxx"), + _ => panic!( + "Could not figure out if c or c++ wrapper was called. Expected {dir:?} to end with c or cxx" + ), }; dir.pop(); diff --git a/fuzzers/inprocess/fuzzbench/src/lib.rs b/fuzzers/inprocess/fuzzbench/src/lib.rs index 8851abe92d..4b87c09cd6 100644 --- a/fuzzers/inprocess/fuzzbench/src/lib.rs +++ b/fuzzers/inprocess/fuzzbench/src/lib.rs @@ -16,47 +16,46 @@ use std::{ use clap::{Arg, Command}; use libafl::{ + Error, HasMetadata, corpus::{Corpus, InMemoryOnDiskCorpus, OnDiskCorpus}, events::SimpleRestartingEventManager, - executors::{inprocess::InProcessExecutor, ExitKind}, + executors::{ExitKind, inprocess::InProcessExecutor}, feedback_or, feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback}, fuzzer::{Fuzzer, StdFuzzer}, inputs::{BytesInput, HasTargetBytes}, monitors::SimpleMonitor, mutators::{ - havoc_mutations, token_mutations::I2SRandReplace, tokens_mutations, StdMOptMutator, - StdScheduledMutator, Tokens, + StdMOptMutator, StdScheduledMutator, Tokens, havoc_mutations, + token_mutations::I2SRandReplace, tokens_mutations, }, observers::{CanTrack, HitcountsMapObserver, TimeObserver}, schedulers::{ - powersched::PowerSchedule, IndexesLenTimeMinimizerScheduler, StdWeightedScheduler, + IndexesLenTimeMinimizerScheduler, StdWeightedScheduler, powersched::PowerSchedule, }, stages::{ - calibrate::CalibrationStage, power::StdPowerMutationalStage, StdMutationalStage, - TracingStage, + StdMutationalStage, TracingStage, calibrate::CalibrationStage, + power::StdPowerMutationalStage, }, state::{HasCorpus, StdState}, - Error, HasMetadata, }; use libafl_bolts::{ - current_time, + AsSlice, current_time, os::dup2, rands::StdRand, shmem::{ShMemProvider, StdShMemProvider}, - tuples::{tuple_list, Merge}, - AsSlice, + tuples::{Merge, tuple_list}, }; #[cfg(any(target_os = "linux", target_vendor = "apple"))] use libafl_targets::autotokens; use libafl_targets::{ - libfuzzer_initialize, libfuzzer_test_one_input, std_edges_map_observer, CmpLogObserver, + CmpLogObserver, libfuzzer_initialize, libfuzzer_test_one_input, std_edges_map_observer, }; #[cfg(unix)] use nix::unistd::dup; /// The fuzzer main (as `no_mangle` C function) -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn libafl_main() { // Registry the metadata types used in this fuzzer // Needed only on no_std diff --git a/fuzzers/structure_aware/forkserver_simple_nautilus/src/main.rs b/fuzzers/structure_aware/forkserver_simple_nautilus/src/main.rs index 682a65a9a2..c06997b2dc 100644 --- a/fuzzers/structure_aware/forkserver_simple_nautilus/src/main.rs +++ b/fuzzers/structure_aware/forkserver_simple_nautilus/src/main.rs @@ -95,8 +95,12 @@ pub fn main() { // The coverage map shared between observer and executor let mut shmem = shmem_provider.new_shmem(MAP_SIZE).unwrap(); - // let the forkserver know the shmid - shmem.write_to_env("__AFL_SHM_ID").unwrap(); + + unsafe { + // let the forkserver know the shmid + shmem.write_to_env("__AFL_SHM_ID").unwrap(); + } + let shmem_buf = shmem.as_slice_mut(); // Create an observation channel using the signals map diff --git a/libafl/Cargo.toml b/libafl/Cargo.toml index d7982829b6..d5b15f2dd8 100644 --- a/libafl/Cargo.toml +++ b/libafl/Cargo.toml @@ -11,8 +11,8 @@ repository = "https://github.com/AFLplusplus/LibAFL/" readme = "../README.md" license = "MIT OR Apache-2.0" keywords = ["fuzzing", "testing", "security"] -edition = "2021" -rust-version = "1.82" +edition = "2024" +rust-version = "1.85" categories = [ "development-tools::testing", "emulators", diff --git a/libafl/examples/tui_mock/main.rs b/libafl/examples/tui_mock/main.rs index f7f3a89946..a6cd121023 100644 --- a/libafl/examples/tui_mock/main.rs +++ b/libafl/examples/tui_mock/main.rs @@ -4,9 +4,9 @@ use std::{thread::sleep, time::Duration}; use libafl::monitors::{ - stats::{manager::ClientStatsManager, ClientStats}, - tui::TuiMonitor, Monitor, + stats::{ClientStats, manager::ClientStatsManager}, + tui::TuiMonitor, }; use libafl_bolts::ClientId; diff --git a/libafl/src/common/mod.rs b/libafl/src/common/mod.rs index da1e2d4fa1..9e50806129 100644 --- a/libafl/src/common/mod.rs +++ b/libafl/src/common/mod.rs @@ -7,8 +7,8 @@ use core::any::type_name; pub mod nautilus; use libafl_bolts::{ - serdeany::{NamedSerdeAnyMap, SerdeAny, SerdeAnyMap}, Error, + serdeany::{NamedSerdeAnyMap, SerdeAny, SerdeAnyMap}, }; /// Trait for elements offering metadata pub trait HasMetadata { diff --git a/libafl/src/common/nautilus/grammartec/chunkstore.rs b/libafl/src/common/nautilus/grammartec/chunkstore.rs index 40c97a8f5d..91627d74a1 100644 --- a/libafl/src/common/nautilus/grammartec/chunkstore.rs +++ b/libafl/src/common/nautilus/grammartec/chunkstore.rs @@ -2,7 +2,7 @@ use alloc::{string::String, vec::Vec}; use std::{ fs::File, io::Write, - sync::{atomic::AtomicBool, RwLock}, + sync::{RwLock, atomic::AtomicBool}, }; use hashbrown::{HashMap, HashSet}; diff --git a/libafl/src/common/nautilus/grammartec/mutator.rs b/libafl/src/common/nautilus/grammartec/mutator.rs index dbc1aee927..d59071f0bd 100644 --- a/libafl/src/common/nautilus/grammartec/mutator.rs +++ b/libafl/src/common/nautilus/grammartec/mutator.rs @@ -2,7 +2,7 @@ use alloc::vec::Vec; use core::{mem, num::NonZero}; use hashbrown::HashSet; -use libafl_bolts::{rands::Rand, Error}; +use libafl_bolts::{Error, rands::Rand}; use crate::common::nautilus::grammartec::{ chunkstore::ChunkStore, diff --git a/libafl/src/common/nautilus/grammartec/recursion_info.rs b/libafl/src/common/nautilus/grammartec/recursion_info.rs index 6933be1c59..581f071645 100644 --- a/libafl/src/common/nautilus/grammartec/recursion_info.rs +++ b/libafl/src/common/nautilus/grammartec/recursion_info.rs @@ -3,8 +3,8 @@ use std::fmt; use hashbrown::HashMap; use libafl_bolts::{ - rands::{loaded_dice::LoadedDiceSampler, Rand}, Error, + rands::{Rand, loaded_dice::LoadedDiceSampler}, }; use crate::common::nautilus::grammartec::{ diff --git a/libafl/src/common/nautilus/grammartec/tree.rs b/libafl/src/common/nautilus/grammartec/tree.rs index 72b2ee5292..a922c19a83 100644 --- a/libafl/src/common/nautilus/grammartec/tree.rs +++ b/libafl/src/common/nautilus/grammartec/tree.rs @@ -4,9 +4,9 @@ use std::{cmp, io, io::Write, marker::Sized}; use hashbrown::HashSet; use libafl_bolts::rands::Rand; use pyo3::{ + PyTypeInfo, prelude::{PyObject, PyResult, Python}, types::{PyAnyMethods, PyBytes, PyBytesMethods, PyString, PyStringMethods, PyTuple}, - PyTypeInfo, }; use serde::{Deserialize, Serialize}; @@ -380,11 +380,7 @@ impl Tree { done_nterms.insert(nterm); } } - if ret.is_empty() { - None - } else { - Some(ret) - } + if ret.is_empty() { None } else { Some(ret) } } #[expect(dead_code)] diff --git a/libafl/src/corpus/cached.rs b/libafl/src/corpus/cached.rs index ecc9007ccf..c9befc19e2 100644 --- a/libafl/src/corpus/cached.rs +++ b/libafl/src/corpus/cached.rs @@ -7,12 +7,12 @@ use std::path::Path; use serde::{Deserialize, Serialize}; use crate::{ + Error, corpus::{ - inmemory_ondisk::InMemoryOnDiskCorpus, ondisk::OnDiskMetadataFormat, Corpus, CorpusId, - HasTestcase, Testcase, + Corpus, CorpusId, HasTestcase, Testcase, inmemory_ondisk::InMemoryOnDiskCorpus, + ondisk::OnDiskMetadataFormat, }, inputs::Input, - Error, }; /// A corpus that keeps a maximum number of [`Testcase`]s in memory diff --git a/libafl/src/corpus/inmemory.rs b/libafl/src/corpus/inmemory.rs index f89b6f6d69..d4760386bf 100644 --- a/libafl/src/corpus/inmemory.rs +++ b/libafl/src/corpus/inmemory.rs @@ -7,8 +7,8 @@ use serde::{Deserialize, Serialize}; use super::HasTestcase; use crate::{ - corpus::{Corpus, CorpusId, Testcase}, Error, + corpus::{Corpus, CorpusId, Testcase}, }; /// Keep track of the stored `Testcase` and the siblings ids (insertion order) @@ -60,10 +60,9 @@ impl TestcaseStorageMap { /// Replace a testcase given a `CorpusId` #[cfg(not(feature = "corpus_btreemap"))] pub fn replace(&mut self, id: CorpusId, testcase: Testcase) -> Option> { - if let Some(entry) = self.map.get_mut(&id) { - Some(entry.testcase.replace(testcase)) - } else { - None + match self.map.get_mut(&id) { + Some(entry) => Some(entry.testcase.replace(testcase)), + _ => None, } } @@ -76,23 +75,30 @@ impl TestcaseStorageMap { /// Remove a testcase given a [`CorpusId`] #[cfg(not(feature = "corpus_btreemap"))] pub fn remove(&mut self, id: CorpusId) -> Option>> { - if let Some(item) = self.map.remove(&id) { - self.remove_key(id); - if let Some(prev) = item.prev { - self.map.get_mut(&prev).unwrap().next = item.next; - } else { - // first elem - self.first_id = item.next; + match self.map.remove(&id) { + Some(item) => { + self.remove_key(id); + match item.prev { + Some(prev) => { + self.map.get_mut(&prev).unwrap().next = item.next; + } + _ => { + // first elem + self.first_id = item.next; + } + } + match item.next { + Some(next) => { + self.map.get_mut(&next).unwrap().prev = item.prev; + } + _ => { + // last elem + self.last_id = item.prev; + } + } + Some(item.testcase) } - if let Some(next) = item.next { - self.map.get_mut(&next).unwrap().prev = item.prev; - } else { - // last elem - self.last_id = item.prev; - } - Some(item.testcase) - } else { - None + _ => None, } } @@ -121,10 +127,9 @@ impl TestcaseStorageMap { #[cfg(not(feature = "corpus_btreemap"))] #[must_use] pub fn next(&self, id: CorpusId) -> Option { - if let Some(item) = self.map.get(&id) { - item.next - } else { - None + match self.map.get(&id) { + Some(item) => item.next, + _ => None, } } @@ -152,10 +157,9 @@ impl TestcaseStorageMap { #[cfg(not(feature = "corpus_btreemap"))] #[must_use] pub fn prev(&self, id: CorpusId) -> Option { - if let Some(item) = self.map.get(&id) { - item.prev - } else { - None + match self.map.get(&id) { + Some(item) => item.prev, + _ => None, } } diff --git a/libafl/src/corpus/inmemory_ondisk.rs b/libafl/src/corpus/inmemory_ondisk.rs index 690bd82a58..d4442a01f9 100644 --- a/libafl/src/corpus/inmemory_ondisk.rs +++ b/libafl/src/corpus/inmemory_ondisk.rs @@ -20,13 +20,13 @@ use libafl_bolts::compress::GzipCompressor; use serde::{Deserialize, Serialize}; use super::{ - ondisk::{OnDiskMetadata, OnDiskMetadataFormat}, HasTestcase, + ondisk::{OnDiskMetadata, OnDiskMetadataFormat}, }; use crate::{ + Error, HasMetadata, corpus::{Corpus, CorpusId, InMemoryCorpus, Testcase}, inputs::Input, - Error, HasMetadata, }; /// Creates the given `path` and returns an error if it fails. diff --git a/libafl/src/corpus/minimizer.rs b/libafl/src/corpus/minimizer.rs index f7504fead1..c4defb6172 100644 --- a/libafl/src/corpus/minimizer.rs +++ b/libafl/src/corpus/minimizer.rs @@ -6,14 +6,14 @@ use core::{hash::Hash, marker::PhantomData}; use hashbrown::{HashMap, HashSet}; use libafl_bolts::{ - current_time, + AsIter, Named, current_time, tuples::{Handle, Handled}, - AsIter, Named, }; use num_traits::ToPrimitive; -use z3::{ast::Bool, Config, Context, Optimize}; +use z3::{Config, Context, Optimize, ast::Bool}; use crate::{ + Error, HasMetadata, HasScheduler, corpus::Corpus, events::{Event, EventFirer, LogSeverity}, executors::{Executor, HasObservers}, @@ -22,7 +22,6 @@ use crate::{ observers::{MapObserver, ObserversTuple}, schedulers::{LenTimeMulTestcaseScore, RemovableScheduler, Scheduler, TestcaseScore}, state::{HasCorpus, HasExecutions}, - Error, HasMetadata, HasScheduler, }; /// Minimizes a corpus according to coverage maps, weighting by the specified `TestcaseScore`. diff --git a/libafl/src/corpus/nop.rs b/libafl/src/corpus/nop.rs index 87d3cc8d40..a6e0f902e4 100644 --- a/libafl/src/corpus/nop.rs +++ b/libafl/src/corpus/nop.rs @@ -4,8 +4,8 @@ use core::{cell::RefCell, marker::PhantomData}; use serde::{Deserialize, Serialize}; use crate::{ - corpus::{Corpus, CorpusId, Testcase}, Error, + corpus::{Corpus, CorpusId, Testcase}, }; /// A corpus which does not store any [`Testcase`]s. diff --git a/libafl/src/corpus/ondisk.rs b/libafl/src/corpus/ondisk.rs index c6bc604202..4a69769108 100644 --- a/libafl/src/corpus/ondisk.rs +++ b/libafl/src/corpus/ondisk.rs @@ -16,9 +16,9 @@ use libafl_bolts::serdeany::SerdeAnyMap; use serde::{Deserialize, Serialize}; use crate::{ + Error, corpus::{CachedOnDiskCorpus, Corpus, CorpusId, HasTestcase, Testcase}, inputs::Input, - Error, }; /// Options for the the format of the on-disk metadata diff --git a/libafl/src/corpus/testcase.rs b/libafl/src/corpus/testcase.rs index 996cbaf0b8..1c9c4bfccf 100644 --- a/libafl/src/corpus/testcase.rs +++ b/libafl/src/corpus/testcase.rs @@ -11,11 +11,11 @@ use core::{ #[cfg(feature = "std")] use std::path::PathBuf; -use libafl_bolts::{serdeany::SerdeAnyMap, HasLen}; +use libafl_bolts::{HasLen, serdeany::SerdeAnyMap}; use serde::{Deserialize, Serialize}; use super::Corpus; -use crate::{corpus::CorpusId, Error, HasMetadata}; +use crate::{Error, HasMetadata, corpus::CorpusId}; /// Shorthand to receive a [`Ref`] or [`RefMut`] to a stored [`Testcase`], by [`CorpusId`]. /// For a normal state, this should return a [`Testcase`] in the corpus, not the objectives. diff --git a/libafl/src/events/broker_hooks/centralized.rs b/libafl/src/events/broker_hooks/centralized.rs index 28381279b0..cd6391700e 100644 --- a/libafl/src/events/broker_hooks/centralized.rs +++ b/libafl/src/events/broker_hooks/centralized.rs @@ -1,17 +1,17 @@ use alloc::vec::Vec; use core::{fmt::Debug, marker::PhantomData}; +use libafl_bolts::{ + ClientId, Error, + llmp::{Flags, LlmpBrokerInner, LlmpHook, LlmpMsgHookResult, Tag}, +}; #[cfg(feature = "llmp_compression")] use libafl_bolts::{compress::GzipCompressor, llmp::LLMP_FLAG_COMPRESSED}; -use libafl_bolts::{ - llmp::{Flags, LlmpBrokerInner, LlmpHook, LlmpMsgHookResult, Tag}, - ClientId, Error, -}; use serde::de::DeserializeOwned; #[cfg(feature = "llmp_compression")] use crate::events::COMPRESS_THRESHOLD; -use crate::events::{BrokerEventResult, Event, _LLMP_TAG_TO_MAIN}; +use crate::events::{_LLMP_TAG_TO_MAIN, BrokerEventResult, Event}; /// An LLMP-backed event manager for scalable multi-processed fuzzing pub struct CentralizedLlmpHook { diff --git a/libafl/src/events/broker_hooks/centralized_multi_machine.rs b/libafl/src/events/broker_hooks/centralized_multi_machine.rs index 08fdf2f7bb..a8d3973045 100644 --- a/libafl/src/events/broker_hooks/centralized_multi_machine.rs +++ b/libafl/src/events/broker_hooks/centralized_multi_machine.rs @@ -9,9 +9,9 @@ use std::{ #[cfg(feature = "llmp_compression")] use libafl_bolts::llmp::LLMP_FLAG_COMPRESSED; use libafl_bolts::{ - llmp::{Flags, LlmpBrokerInner, LlmpHook, LlmpMsgHookResult, Tag, LLMP_FLAG_FROM_MM}, - ownedref::OwnedRef, ClientId, Error, + llmp::{Flags, LLMP_FLAG_FROM_MM, LlmpBrokerInner, LlmpHook, LlmpMsgHookResult, Tag}, + ownedref::OwnedRef, }; use serde::Serialize; use tokio::{ @@ -23,9 +23,9 @@ use tokio::{ use crate::{ events::{ + Event, centralized::_LLMP_TAG_TO_MAIN, multi_machine::{MultiMachineMsg, TcpMultiMachineState}, - Event, }, inputs::Input, }; diff --git a/libafl/src/events/broker_hooks/mod.rs b/libafl/src/events/broker_hooks/mod.rs index e64a36100b..5d7f9f126e 100644 --- a/libafl/src/events/broker_hooks/mod.rs +++ b/libafl/src/events/broker_hooks/mod.rs @@ -2,20 +2,20 @@ use alloc::vec::Vec; use core::marker::PhantomData; +use libafl_bolts::{ + ClientId, + llmp::{Flags, LlmpBrokerInner, LlmpHook, LlmpMsgHookResult, Tag}, +}; #[cfg(feature = "llmp_compression")] use libafl_bolts::{compress::GzipCompressor, llmp::LLMP_FLAG_COMPRESSED}; -use libafl_bolts::{ - llmp::{Flags, LlmpBrokerInner, LlmpHook, LlmpMsgHookResult, Tag}, - ClientId, -}; use serde::de::DeserializeOwned; #[cfg(feature = "llmp_compression")] use crate::events::llmp::COMPRESS_THRESHOLD; use crate::{ - events::{llmp::LLMP_TAG_EVENT_TO_BOTH, BrokerEventResult, Event}, - monitors::{stats::ClientStatsManager, Monitor}, Error, + events::{BrokerEventResult, Event, llmp::LLMP_TAG_EVENT_TO_BOTH}, + monitors::{Monitor, stats::ClientStatsManager}, }; /// centralized hook diff --git a/libafl/src/events/centralized.rs b/libafl/src/events/centralized.rs index 781a17d3ae..2c6e64190c 100644 --- a/libafl/src/events/centralized.rs +++ b/libafl/src/events/centralized.rs @@ -11,34 +11,33 @@ use alloc::{string::String, vec::Vec}; use core::{fmt::Debug, marker::PhantomData, time::Duration}; use std::process; +use libafl_bolts::{ + ClientId, + llmp::{LlmpClient, LlmpClientDescription, Tag}, + shmem::{ShMem, ShMemProvider}, + tuples::{Handle, MatchNameRef}, +}; #[cfg(feature = "llmp_compression")] use libafl_bolts::{ compress::GzipCompressor, llmp::{LLMP_FLAG_COMPRESSED, LLMP_FLAG_INITIALIZED}, }; -use libafl_bolts::{ - llmp::{LlmpClient, LlmpClientDescription, Tag}, - shmem::{ShMem, ShMemProvider}, - tuples::{Handle, MatchNameRef}, - ClientId, -}; use serde::Serialize; use super::{AwaitRestartSafe, RecordSerializationTime}; #[cfg(feature = "llmp_compression")] use crate::events::llmp::COMPRESS_THRESHOLD; use crate::{ + Error, common::HasMetadata, events::{ - serialize_observers_adaptive, std_maybe_report_progress, std_report_progress, AdaptiveSerializer, CanSerializeObserver, Event, EventConfig, EventFirer, EventManagerId, EventReceiver, EventRestarter, HasEventManagerId, LogSeverity, ProgressReporter, - SendExiting, + SendExiting, serialize_observers_adaptive, std_maybe_report_progress, std_report_progress, }, inputs::Input, observers::TimeObserver, state::{HasExecutions, HasLastReportTime, MaybeHasClientPerfMonitor, Stoppable}, - Error, }; pub(crate) const _LLMP_TAG_TO_MAIN: Tag = Tag(0x3453453); @@ -389,8 +388,13 @@ where /// Write the config for a client `EventManager` to env vars, a new /// client can reattach using [`CentralizedEventManagerBuilder::build_existing_client_from_env()`]. - pub fn to_env(&self, env_name: &str) { - self.client.to_env(env_name).unwrap(); + /// + /// # Safety + /// Writes to env variables and may only be done single-threaded. + pub unsafe fn to_env(&self, env_name: &str) { + unsafe { + self.client.to_env(env_name).unwrap(); + } } /// Know if this instance is main or secondary diff --git a/libafl/src/events/events_hooks/mod.rs b/libafl/src/events/events_hooks/mod.rs index 742a05dbbb..b906eb28a4 100644 --- a/libafl/src/events/events_hooks/mod.rs +++ b/libafl/src/events/events_hooks/mod.rs @@ -4,7 +4,7 @@ //! other clients use libafl_bolts::ClientId; -use crate::{events::Event, Error}; +use crate::{Error, events::Event}; /// The `broker_hooks` that are run before and after the event manager calls `try_receive` pub trait EventManagerHook { diff --git a/libafl/src/events/launcher.rs b/libafl/src/events/launcher.rs index 67c9cf0c18..329da92f75 100644 --- a/libafl/src/events/launcher.rs +++ b/libafl/src/events/launcher.rs @@ -22,21 +22,21 @@ use std::{net::SocketAddr, string::String}; use libafl_bolts::{ core_affinity::{CoreId, Cores}, shmem::ShMemProvider, - tuples::{tuple_list, Handle}, + tuples::{Handle, tuple_list}, }; -use serde::{de::DeserializeOwned, Deserialize, Serialize}; +use serde::{Deserialize, Serialize, de::DeserializeOwned}; use typed_builder::TypedBuilder; #[cfg(all(unix, feature = "fork"))] use { crate::{ - events::{centralized::CentralizedEventManager, CentralizedLlmpHook, StdLlmpEventHook}, + events::{CentralizedLlmpHook, StdLlmpEventHook, centralized::CentralizedEventManager}, inputs::Input, }, alloc::string::ToString, libafl_bolts::{ core_affinity::get_core_ids, llmp::{Broker, Brokers, LlmpBroker}, - os::{fork, ForkResult}, + os::{ForkResult, fork}, }, std::boxed::Box, }; @@ -51,13 +51,13 @@ use {libafl_bolts::os::startable_self, std::process::Stdio}; #[cfg(all(unix, feature = "fork", feature = "multi_machine"))] use crate::events::multi_machine::{NodeDescriptor, TcpMultiMachineHooks}; use crate::{ + Error, events::{ - llmp::{LlmpRestartingEventManager, LlmpShouldSaveState, ManagerKind, RestartingMgr}, EventConfig, EventManagerHooksTuple, + llmp::{LlmpRestartingEventManager, LlmpShouldSaveState, ManagerKind, RestartingMgr}, }, monitors::Monitor, observers::TimeObserver, - Error, }; /// The (internal) `env` that indicates we're running as client. @@ -300,10 +300,13 @@ where if !debug_output { if let Some(file) = &self.opened_stdout_file { dup2(file.as_raw_fd(), libc::STDOUT_FILENO)?; - if let Some(stderr) = &self.opened_stderr_file { - dup2(stderr.as_raw_fd(), libc::STDERR_FILENO)?; - } else { - dup2(file.as_raw_fd(), libc::STDERR_FILENO)?; + match &self.opened_stderr_file { + Some(stderr) => { + dup2(stderr.as_raw_fd(), libc::STDERR_FILENO)?; + } + _ => { + dup2(file.as_raw_fd(), libc::STDERR_FILENO)?; + } } } } @@ -365,7 +368,9 @@ where } else { for handle in &handles { let mut status = 0; - log::info!("Not spawning broker (spawn_broker is false). Waiting for fuzzer children to exit..."); + log::info!( + "Not spawning broker (spawn_broker is false). Waiting for fuzzer children to exit..." + ); unsafe { libc::waitpid(*handle, &mut status, 0); if status != 0 { @@ -470,10 +475,14 @@ where let client_description = ClientDescription::new(index, overcommit_i, core_id); - std::env::set_var( - _AFL_LAUNCHER_CLIENT, - client_description.to_safe_string(), - ); + // # Safety + // This is set only once, in here, for the child. + unsafe { + std::env::set_var( + _AFL_LAUNCHER_CLIENT, + client_description.to_safe_string(), + ); + } let mut child = startable_self()?; let child = (if debug_output { &mut child @@ -522,7 +531,9 @@ where handle.kill()?; } } else { - log::info!("Not spawning broker (spawn_broker is false). Waiting for fuzzer children to exit..."); + log::info!( + "Not spawning broker (spawn_broker is false). Waiting for fuzzer children to exit..." + ); for handle in &mut handles { let ecode = handle.wait()?; if !ecode.success() { @@ -759,10 +770,13 @@ where if !debug_output { if let Some(file) = &self.opened_stdout_file { dup2(file.as_raw_fd(), libc::STDOUT_FILENO)?; - if let Some(stderr) = &self.opened_stderr_file { - dup2(stderr.as_raw_fd(), libc::STDERR_FILENO)?; - } else { - dup2(file.as_raw_fd(), libc::STDERR_FILENO)?; + match &self.opened_stderr_file { + Some(stderr) => { + dup2(stderr.as_raw_fd(), libc::STDERR_FILENO)?; + } + _ => { + dup2(file.as_raw_fd(), libc::STDERR_FILENO)?; + } } } } diff --git a/libafl/src/events/llmp/mod.rs b/libafl/src/events/llmp/mod.rs index c2baf963d5..7da1efb176 100644 --- a/libafl/src/events/llmp/mod.rs +++ b/libafl/src/events/llmp/mod.rs @@ -2,24 +2,24 @@ use core::{fmt::Debug, marker::PhantomData, time::Duration}; +use libafl_bolts::{ + ClientId, + llmp::{LlmpClient, LlmpClientDescription, Tag}, + shmem::{NopShMem, NopShMemProvider, ShMem, ShMemProvider}, +}; #[cfg(feature = "llmp_compression")] use libafl_bolts::{ compress::GzipCompressor, llmp::{LLMP_FLAG_COMPRESSED, LLMP_FLAG_INITIALIZED}, }; -use libafl_bolts::{ - llmp::{LlmpClient, LlmpClientDescription, Tag}, - shmem::{NopShMem, NopShMemProvider, ShMem, ShMemProvider}, - ClientId, -}; -use serde::{de::DeserializeOwned, Serialize}; +use serde::{Serialize, de::DeserializeOwned}; use crate::{ + Error, events::{Event, EventFirer}, fuzzer::EvaluatorObservers, inputs::{Input, InputConverter, NopInput, NopInputConverter}, state::{HasCurrentTestcase, HasSolutions, NopState}, - Error, }; /// The llmp restarting manager @@ -242,9 +242,14 @@ where } /// Write the config for a client `EventManager` to env vars, a new client can reattach using [`LlmpEventConverterBuilder::build_existing_client_from_env()`]. + /// + /// # Safety + /// Writes to env variables and may only be done single-threaded. #[cfg(feature = "std")] - pub fn to_env(&self, env_name: &str) { - self.llmp.to_env(env_name).unwrap(); + pub unsafe fn to_env(&self, env_name: &str) { + unsafe { + self.llmp.to_env(env_name).unwrap(); + } } // Handle arriving events in the client @@ -265,7 +270,9 @@ where Event::NewTestcase { input, forward_id, .. } => { - log::debug!("Received new Testcase to convert from {client_id:?} (forward {forward_id:?}, forward {forward_id:?})"); + log::debug!( + "Received new Testcase to convert from {client_id:?} (forward {forward_id:?}, forward {forward_id:?})" + ); let Some(converter) = self.converter_back.as_mut() else { return Ok(()); diff --git a/libafl/src/events/llmp/restarting.rs b/libafl/src/events/llmp/restarting.rs index 31722536cd..94ca7a179f 100644 --- a/libafl/src/events/llmp/restarting.rs +++ b/libafl/src/events/llmp/restarting.rs @@ -9,7 +9,7 @@ use alloc::vec::Vec; use core::{ marker::PhantomData, num::NonZeroUsize, - sync::atomic::{compiler_fence, Ordering}, + sync::atomic::{Ordering, compiler_fence}, time::Duration, }; use std::net::SocketAddr; @@ -21,7 +21,12 @@ use libafl_bolts::os::startable_self; #[cfg(all(unix, not(miri)))] use libafl_bolts::os::unix_signals::setup_signal_handler; #[cfg(all(feature = "fork", unix))] -use libafl_bolts::os::{fork, ForkResult}; +use libafl_bolts::os::{ForkResult, fork}; +#[cfg(feature = "std")] +use libafl_bolts::{ + IP_LOCALHOST, + llmp::{TcpRequest, TcpResponse, recv_tcp_msg, send_tcp_msg}, +}; #[cfg(feature = "llmp_compression")] use libafl_bolts::{ compress::GzipCompressor, @@ -31,19 +36,14 @@ use libafl_bolts::{ core_affinity::CoreId, current_time, llmp::{ - Broker, LlmpBroker, LlmpClient, LlmpClientDescription, LlmpConnection, LLMP_FLAG_FROM_MM, + Broker, LLMP_FLAG_FROM_MM, LlmpBroker, LlmpClient, LlmpClientDescription, LlmpConnection, }, os::CTRL_C_EXIT, shmem::{ShMem, ShMemProvider, StdShMem, StdShMemProvider}, staterestore::StateRestorer, - tuples::{tuple_list, Handle, MatchNameRef}, + tuples::{Handle, MatchNameRef, tuple_list}, }; -#[cfg(feature = "std")] -use libafl_bolts::{ - llmp::{recv_tcp_msg, send_tcp_msg, TcpRequest, TcpResponse}, - IP_LOCALHOST, -}; -use serde::{de::DeserializeOwned, Serialize}; +use serde::{Serialize, de::DeserializeOwned}; use typed_builder::TypedBuilder; #[cfg(feature = "llmp_compression")] @@ -51,14 +51,15 @@ use crate::events::COMPRESS_THRESHOLD; #[cfg(all(unix, not(miri)))] use crate::events::EVENTMGR_SIGHANDLER_STATE; use crate::{ + Error, common::HasMetadata, events::{ + _LLMP_TAG_EVENT_TO_BROKER, AdaptiveSerializer, AwaitRestartSafe, CanSerializeObserver, + Event, EventConfig, EventFirer, EventManagerHooksTuple, EventManagerId, EventReceiver, + EventRestarter, HasEventManagerId, LLMP_TAG_EVENT_TO_BOTH, LlmpShouldSaveState, + ProgressReporter, RecordSerializationTime, SendExiting, StdLlmpEventHook, launcher::ClientDescription, serialize_observers_adaptive, std_maybe_report_progress, - std_report_progress, AdaptiveSerializer, AwaitRestartSafe, CanSerializeObserver, Event, - EventConfig, EventFirer, EventManagerHooksTuple, EventManagerId, EventReceiver, - EventRestarter, HasEventManagerId, LlmpShouldSaveState, ProgressReporter, - RecordSerializationTime, SendExiting, StdLlmpEventHook, LLMP_TAG_EVENT_TO_BOTH, - _LLMP_TAG_EVENT_TO_BROKER, + std_report_progress, }, inputs::Input, monitors::Monitor, @@ -67,7 +68,6 @@ use crate::{ HasCurrentStageId, HasCurrentTestcase, HasExecutions, HasImported, HasLastReportTime, HasSolutions, MaybeHasClientPerfMonitor, Stoppable, }, - Error, }; const INITIAL_EVENT_BUFFER_SIZE: usize = 1024 * 4; @@ -285,7 +285,7 @@ where SP: ShMemProvider, { fn send_exiting(&mut self) -> Result<(), Error> { - if let Some(ref mut sr) = &mut self.staterestorer { + if let Some(sr) = &mut self.staterestorer { sr.send_exiting(); } // Also inform the broker that we are about to exit. @@ -366,7 +366,10 @@ where .. } => { #[cfg(feature = "std")] - log::debug!("[{}] Received new Testcase {evt_name} from {client_id:?} ({client_config:?}, forward {forward_id:?})", std::process::id()); + log::debug!( + "[{}] Received new Testcase {evt_name} from {client_id:?} ({client_config:?}, forward {forward_id:?})", + std::process::id() + ); if client_config.match_with(&self.configuration) && observers_buf.is_some() { return Ok(Some((event, true))); @@ -563,9 +566,14 @@ where { /// Write the config for a client `EventManager` to env vars, a new /// client can reattach using [`LlmpEventManagerBuilder::build_existing_client_from_env()`]. + /// + /// # Safety + /// This will write to process env. Should only be called from a single thread at a time. #[cfg(feature = "std")] - pub fn to_env(&self, env_name: &str) { - self.llmp.to_env(env_name).unwrap(); + pub unsafe fn to_env(&self, env_name: &str) { + unsafe { + self.llmp.to_env(env_name).unwrap(); + } } /// Get the staterestorer @@ -842,7 +850,9 @@ where )?; broker_things(broker, self.remote_broker_addr)?; - unreachable!("The broker may never return normally, only on errors or when shutting down."); + unreachable!( + "The broker may never return normally, only on errors or when shutting down." + ); } ManagerKind::Client { client_description } => { // We are a client @@ -867,7 +877,11 @@ where } // We are the fuzzer respawner in a llmp client - mgr.to_env(_ENV_FUZZER_BROKER_CLIENT_INITIAL); + // # Safety + // There should only ever be one launcher thread. + unsafe { + mgr.to_env(_ENV_FUZZER_BROKER_CLIENT_INITIAL); + } // First, create a channel from the current fuzzer to the next to store state between restarts. #[cfg(unix)] @@ -877,8 +891,13 @@ where #[cfg(not(unix))] let staterestorer: StateRestorer = StateRestorer::new(self.shmem_provider.new_shmem(256 * 1024 * 1024)?); + // Store the information to a map. - staterestorer.write_to_env(_ENV_FUZZER_SENDER)?; + // # Safety + // Very likely single threaded here. + unsafe { + staterestorer.write_to_env(_ENV_FUZZER_SENDER)?; + } let mut ctr: u64 = 0; // Client->parent loop @@ -943,9 +962,14 @@ where log::error!("Failed to detach from broker: {err}"); } #[cfg(unix)] - assert_ne!(9, child_status, "Target received SIGKILL!. This could indicate the target crashed due to OOM, user sent SIGKILL, or the target was in an unrecoverable situation and could not save state to restart"); + assert_ne!( + 9, child_status, + "Target received SIGKILL!. This could indicate the target crashed due to OOM, user sent SIGKILL, or the target was in an unrecoverable situation and could not save state to restart" + ); // 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! This can happen if the child calls `exit()`, in that case make sure it uses `abort()`, if it got killed unrecoverable (OOM), or if there is a bug in the fuzzer itself. (Child exited with: {child_status})"); + panic!( + "Fuzzer-respawner: Storing state in crashed fuzzer instance did not work, no point to spawn the next client! This can happen if the child calls `exit()`, in that case make sure it uses `abort()`, if it got killed unrecoverable (OOM), or if there is a bug in the fuzzer itself. (Child exited with: {child_status})" + ); } ctr = ctr.wrapping_add(1); @@ -1026,21 +1050,22 @@ where #[cfg(test)] mod tests { - use core::sync::atomic::{compiler_fence, Ordering}; + use core::sync::atomic::{Ordering, compiler_fence}; use libafl_bolts::{ + ClientId, llmp::{LlmpClient, LlmpSharedMap}, rands::StdRand, shmem::{ShMemProvider, StdShMem, StdShMemProvider}, staterestore::StateRestorer, - tuples::{tuple_list, Handled}, - ClientId, + tuples::{Handled, tuple_list}, }; use serial_test::serial; use crate::{ + StdFuzzer, corpus::{Corpus, InMemoryCorpus, Testcase}, - events::llmp::restarting::{LlmpEventManagerBuilder, _ENV_FUZZER_SENDER}, + events::llmp::restarting::{_ENV_FUZZER_SENDER, LlmpEventManagerBuilder}, executors::{ExitKind, InProcessExecutor}, feedbacks::ConstFeedback, fuzzer::Fuzzer, @@ -1050,7 +1075,6 @@ mod tests { schedulers::RandScheduler, stages::StdMutationalStage, state::StdState, - StdFuzzer, }; #[test] @@ -1131,7 +1155,11 @@ mod tests { assert!(staterestorer.has_content()); // Store the information to a map. - staterestorer.write_to_env(_ENV_FUZZER_SENDER).unwrap(); + // # Safety + // Single-threaded test code + unsafe { + staterestorer.write_to_env(_ENV_FUZZER_SENDER).unwrap(); + } compiler_fence(Ordering::SeqCst); diff --git a/libafl/src/events/mod.rs b/libafl/src/events/mod.rs index 2018504b12..396e78796d 100644 --- a/libafl/src/events/mod.rs +++ b/libafl/src/events/mod.rs @@ -34,9 +34,9 @@ pub use broker_hooks::*; #[cfg(feature = "std")] pub use launcher::*; #[cfg(all(unix, feature = "std"))] -use libafl_bolts::os::unix_signals::{siginfo_t, ucontext_t, Signal, SignalHandler}; -#[cfg(all(unix, feature = "std"))] use libafl_bolts::os::CTRL_C_EXIT; +#[cfg(all(unix, feature = "std"))] +use libafl_bolts::os::unix_signals::{Signal, SignalHandler, siginfo_t, ucontext_t}; #[cfg(feature = "std")] use libafl_bolts::tuples::MatchNameRef; use libafl_bolts::{current_time, tuples::Handle}; @@ -45,11 +45,11 @@ use serde::{Deserialize, Serialize}; use uuid::Uuid; use crate::{ + Error, HasMetadata, executors::ExitKind, inputs::Input, monitors::stats::UserStats, state::{HasExecutions, HasLastReportTime, MaybeHasClientPerfMonitor}, - Error, HasMetadata, }; /// Multi-machine mode @@ -871,7 +871,7 @@ pub trait AdaptiveSerializer { #[cfg(test)] mod tests { - use libafl_bolts::{current_time, tuples::tuple_list, Named}; + use libafl_bolts::{Named, current_time, tuples::tuple_list}; use tuple_list::tuple_list_type; use crate::{ diff --git a/libafl/src/events/multi_machine.rs b/libafl/src/events/multi_machine.rs index 314bea15cb..d4c6c0fa05 100644 --- a/libafl/src/events/multi_machine.rs +++ b/libafl/src/events/multi_machine.rs @@ -5,17 +5,17 @@ use std::{ io::ErrorKind, process, sync::{ - atomic::{AtomicU64, Ordering}, Arc, OnceLock, + atomic::{AtomicU64, Ordering}, }, time::Duration, vec::Vec, }; -use enumflags2::{bitflags, BitFlags}; +use enumflags2::{BitFlags, bitflags}; #[cfg(feature = "llmp_compression")] use libafl_bolts::compress::GzipCompressor; -use libafl_bolts::{current_time, ownedref::OwnedRef, Error}; +use libafl_bolts::{Error, current_time, ownedref::OwnedRef}; use serde::{Deserialize, Serialize}; use tokio::{ io::{AsyncReadExt, AsyncWriteExt}, @@ -216,34 +216,35 @@ where where I: Input + Send + Sync + 'static, { - let node_descriptor = self.node_descriptor.take().ok_or_else(|| { - Error::illegal_state( - "The node descriptor can never be `None` at this point in the code", - ) - })?; - - // Create the state of the hook. This will be shared with the background server, so we wrap - // it with concurrent-safe objects - let state = Arc::new(RwLock::new(TcpMultiMachineState { - node_descriptor, - parent: None, - children: HashMap::default(), - old_msgs: Vec::new(), - #[cfg(feature = "llmp_compression")] - compressor: GzipCompressor::new(), - })); - - let rt = - Arc::new(Runtime::new().map_err(|_| Error::unknown("Tokio runtime spawning failed"))?); - unsafe { - TcpMultiMachineState::init::(&state.clone(), &rt.clone())?; - } + let node_descriptor = self.node_descriptor.take().ok_or_else(|| { + Error::illegal_state( + "The node descriptor can never be `None` at this point in the code", + ) + })?; - Ok(TcpMultiMachineHooks { - sender: TcpMultiMachineLlmpSenderHook::new(state.clone(), rt.clone()), - receiver: TcpMultiMachineLlmpReceiverHook::new(state, rt), - }) + // Create the state of the hook. This will be shared with the background server, so we wrap + // it with concurrent-safe objects + let state = Arc::new(RwLock::new(TcpMultiMachineState { + node_descriptor, + parent: None, + children: HashMap::default(), + old_msgs: Vec::new(), + #[cfg(feature = "llmp_compression")] + compressor: GzipCompressor::new(), + })); + + let rt = Arc::new( + Runtime::new().map_err(|_| Error::unknown("Tokio runtime spawning failed"))?, + ); + + TcpMultiMachineState::init::(&state.clone(), &rt.clone())?; + + Ok(TcpMultiMachineHooks { + sender: TcpMultiMachineLlmpSenderHook::new(state.clone(), rt.clone()), + receiver: TcpMultiMachineLlmpReceiverHook::new(state, rt), + }) + } } } diff --git a/libafl/src/events/simple.rs b/libafl/src/events/simple.rs index a31499b7f7..7caeb629c9 100644 --- a/libafl/src/events/simple.rs +++ b/libafl/src/events/simple.rs @@ -2,44 +2,44 @@ use alloc::vec::Vec; #[cfg(feature = "std")] -use core::sync::atomic::{compiler_fence, Ordering}; +use core::sync::atomic::{Ordering, compiler_fence}; use core::{fmt::Debug, marker::PhantomData, time::Duration}; +use libafl_bolts::ClientId; #[cfg(all(feature = "std", any(windows, not(feature = "fork"))))] use libafl_bolts::os::startable_self; #[cfg(all(unix, feature = "std", not(miri)))] use libafl_bolts::os::unix_signals::setup_signal_handler; #[cfg(all(feature = "std", feature = "fork", unix))] -use libafl_bolts::os::{fork, ForkResult}; -use libafl_bolts::ClientId; +use libafl_bolts::os::{ForkResult, fork}; #[cfg(feature = "std")] use libafl_bolts::{ os::CTRL_C_EXIT, shmem::{ShMem, ShMemProvider}, staterestore::StateRestorer, }; +use serde::Serialize; #[cfg(feature = "std")] use serde::de::DeserializeOwned; -use serde::Serialize; -use super::{std_on_restart, AwaitRestartSafe, ProgressReporter, RecordSerializationTime}; +use super::{AwaitRestartSafe, ProgressReporter, RecordSerializationTime, std_on_restart}; #[cfg(all(unix, feature = "std", not(miri)))] use crate::events::EVENTMGR_SIGHANDLER_STATE; use crate::{ + Error, HasMetadata, events::{ - std_maybe_report_progress, std_report_progress, BrokerEventResult, CanSerializeObserver, - Event, EventFirer, EventManagerId, EventReceiver, EventRestarter, HasEventManagerId, - SendExiting, + BrokerEventResult, CanSerializeObserver, Event, EventFirer, EventManagerId, EventReceiver, + EventRestarter, HasEventManagerId, SendExiting, std_maybe_report_progress, + std_report_progress, }, - monitors::{stats::ClientStatsManager, Monitor}, + monitors::{Monitor, stats::ClientStatsManager}, state::{ HasCurrentStageId, HasExecutions, HasLastReportTime, MaybeHasClientPerfMonitor, Stoppable, }, - Error, HasMetadata, }; #[cfg(feature = "std")] use crate::{ - monitors::{stats::ClientStats, SimplePrintingMonitor}, + monitors::{SimplePrintingMonitor, stats::ClientStats}, state::HasSolutions, }; @@ -132,7 +132,7 @@ where _ => { return Err(Error::unknown(format!( "Received illegal message that message should not have arrived: {event:?}." - ))) + ))); } } } @@ -454,7 +454,12 @@ where StateRestorer::new(shmem_provider.new_shmem(256 * 1024 * 1024)?); //let staterestorer = { LlmpSender::new(shmem_provider.clone(), 0, false)? }; - staterestorer.write_to_env(_ENV_FUZZER_SENDER)?; + + // # Safety + // Launcher is usually running in a single thread. + unsafe { + staterestorer.write_to_env(_ENV_FUZZER_SENDER)?; + } let mut ctr: u64 = 0; // Client->parent loop @@ -509,10 +514,14 @@ where if !staterestorer.has_content() { #[cfg(unix)] if child_status == 9 { - panic!("Target received SIGKILL!. This could indicate the target crashed due to OOM, user sent SIGKILL, or the target was in an unrecoverable situation and could not save state to restart"); + panic!( + "Target received SIGKILL!. This could indicate the target crashed due to OOM, user sent SIGKILL, or the target was in an unrecoverable situation and could not save state to restart" + ); } // 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! This can happen if the child calls `exit()`, in that case make sure it uses `abort()`, if it got killed unrecoverable (OOM), or if there is a bug in the fuzzer itself. (Child exited with: {child_status})"); + panic!( + "Fuzzer-respawner: Storing state in crashed fuzzer instance did not work, no point to spawn the next client! This can happen if the child calls `exit()`, in that case make sure it uses `abort()`, if it got killed unrecoverable (OOM), or if there is a bug in the fuzzer itself. (Child exited with: {child_status})" + ); } ctr = ctr.wrapping_add(1); diff --git a/libafl/src/events/tcp.rs b/libafl/src/events/tcp.rs index 48c8fb5811..3931c9d85a 100644 --- a/libafl/src/events/tcp.rs +++ b/libafl/src/events/tcp.rs @@ -4,7 +4,7 @@ use alloc::vec::Vec; use core::{ marker::PhantomData, num::NonZeroUsize, - sync::atomic::{compiler_fence, Ordering}, + sync::atomic::{Ordering, compiler_fence}, time::Duration, }; use std::{ @@ -21,38 +21,38 @@ use libafl_bolts::os::startable_self; #[cfg(all(unix, not(miri)))] use libafl_bolts::os::unix_signals::setup_signal_handler; #[cfg(all(feature = "fork", unix))] -use libafl_bolts::os::{fork, ForkResult}; +use libafl_bolts::os::{ForkResult, fork}; use libafl_bolts::{ + ClientId, core_affinity::CoreId, os::CTRL_C_EXIT, shmem::{ShMem, ShMemProvider, StdShMem, StdShMemProvider}, staterestore::StateRestorer, tuples::tuple_list, - ClientId, }; -use serde::{de::DeserializeOwned, Serialize}; +use serde::{Serialize, de::DeserializeOwned}; use tokio::{ io::{AsyncReadExt, AsyncWriteExt}, sync::{broadcast, broadcast::error::RecvError, mpsc}, - task::{spawn, JoinHandle}, + task::{JoinHandle, spawn}, }; use typed_builder::TypedBuilder; -use super::{std_maybe_report_progress, std_report_progress, AwaitRestartSafe, SendExiting}; +use super::{AwaitRestartSafe, SendExiting, std_maybe_report_progress, std_report_progress}; #[cfg(all(unix, not(miri)))] use crate::events::EVENTMGR_SIGHANDLER_STATE; use crate::{ + Error, HasMetadata, events::{ - std_on_restart, BrokerEventResult, Event, EventConfig, EventFirer, EventManagerHooksTuple, - EventManagerId, EventReceiver, EventRestarter, HasEventManagerId, ProgressReporter, + BrokerEventResult, Event, EventConfig, EventFirer, EventManagerHooksTuple, EventManagerId, + EventReceiver, EventRestarter, HasEventManagerId, ProgressReporter, std_on_restart, }, inputs::Input, - monitors::{stats::ClientStatsManager, Monitor}, + monitors::{Monitor, stats::ClientStatsManager}, state::{ HasCurrentStageId, HasCurrentTestcase, HasExecutions, HasImported, HasLastReportTime, HasSolutions, MaybeHasClientPerfMonitor, Stoppable, }, - Error, HasMetadata, }; /// Tries to create (synchronously) a [`TcpListener`] that is `nonblocking` (for later use in tokio). @@ -244,8 +244,9 @@ where } if buf[..4] == this_client_id_bytes { - log::debug!("TCP Manager - Not forwarding message from this very client ({this_client_id:?})." - ); + log::debug!( + "TCP Manager - Not forwarding message from this very client ({this_client_id:?})." + ); continue; } @@ -573,8 +574,13 @@ where S: HasExecutions + HasMetadata + HasImported + Stoppable, { /// Write the client id for a client `EventManager` to env vars - pub fn to_env(&self, env_name: &str) { - env::set_var(env_name, format!("{}", self.client_id.0)); + /// + /// # Safety + /// This writes to env variables, and may only be done single-threaded + pub unsafe fn to_env(&self, env_name: &str) { + unsafe { + env::set_var(env_name, format!("{}", self.client_id.0)); + } } } @@ -684,7 +690,9 @@ where forward_id, .. } => { - log::info!("Received new Testcase from {other_client_id:?} ({client_config:?}, forward {forward_id:?})"); + log::info!( + "Received new Testcase from {other_client_id:?} ({client_config:?}, forward {forward_id:?})" + ); if client_config.match_with(&self.configuration) && observers_buf.is_some() { @@ -704,7 +712,7 @@ where return Err(Error::unknown(format!( "Received illegal message that message should not have arrived: {:?}.", event.name() - ))) + ))); } } } @@ -1118,7 +1126,9 @@ where )?; broker_things(event_broker, self.remote_broker_addr)?; - unreachable!("The broker may never return normally, only on errors or when shutting down."); + unreachable!( + "The broker may never return normally, only on errors or when shutting down." + ); } TcpManagerKind::Client { cpu_core } => { // We are a client @@ -1137,7 +1147,11 @@ where } // We are the fuzzer respawner in a tcp client - mgr.to_env(_ENV_FUZZER_BROKER_CLIENT_INITIAL); + // # Safety + // There should only ever be one thread doing launcher things. + unsafe { + mgr.to_env(_ENV_FUZZER_BROKER_CLIENT_INITIAL); + } // First, create a channel from the current fuzzer to the next to store state between restarts. #[cfg(unix)] @@ -1147,8 +1161,14 @@ where #[cfg(not(unix))] let staterestorer: StateRestorer = StateRestorer::new(self.shmem_provider.new_shmem(256 * 1024 * 1024)?); + // Store the information to a map. - staterestorer.write_to_env(_ENV_FUZZER_SENDER)?; + // # Safety + // It's reasonable to assume launcher only gets called on a single thread. + // If not, nothing too bad will happen. + unsafe { + staterestorer.write_to_env(_ENV_FUZZER_SENDER)?; + } let mut ctr: u64 = 0; // Client->parent loop @@ -1206,11 +1226,15 @@ where if child_status == 137 { // Out of Memory, see https://tldp.org/LDP/abs/html/exitcodes.html // and https://github.com/AFLplusplus/LibAFL/issues/32 for discussion. - panic!("Fuzzer-respawner: The fuzzed target crashed with an out of memory error! Fix your harness, or switch to another executor (for example, a forkserver)."); + panic!( + "Fuzzer-respawner: The fuzzed target crashed with an out of memory error! Fix your harness, or switch to another executor (for example, a forkserver)." + ); } // 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! This can happen if the child calls `exit()`, in that case make sure it uses `abort()`, if it got killed unrecoverable (OOM), or if there is a bug in the fuzzer itself. (Child exited with: {child_status})"); + panic!( + "Fuzzer-respawner: Storing state in crashed fuzzer instance did not work, no point to spawn the next client! This can happen if the child calls `exit()`, in that case make sure it uses `abort()`, if it got killed unrecoverable (OOM), or if there is a bug in the fuzzer itself. (Child exited with: {child_status})" + ); } ctr = ctr.wrapping_add(1); diff --git a/libafl/src/executors/combined.rs b/libafl/src/executors/combined.rs index 36714fa646..3a5c472c47 100644 --- a/libafl/src/executors/combined.rs +++ b/libafl/src/executors/combined.rs @@ -7,8 +7,8 @@ use libafl_bolts::tuples::RefIndexable; use super::HasTimeout; use crate::{ - executors::{Executor, ExitKind, HasObservers}, Error, + executors::{Executor, ExitKind, HasObservers}, }; /// A [`CombinedExecutor`] wraps a primary executor, forwarding its methods, and a secondary one diff --git a/libafl/src/executors/command.rs b/libafl/src/executors/command.rs index af2a1de78e..6811cfe696 100644 --- a/libafl/src/executors/command.rs +++ b/libafl/src/executors/command.rs @@ -22,9 +22,9 @@ use std::{ #[cfg(all(feature = "intel_pt", target_os = "linux"))] use libafl_bolts::core_affinity::CoreId; use libafl_bolts::{ - fs::{get_unique_std_input_file, InputFile}, - tuples::{Handle, MatchName, RefIndexable}, AsSlice, + fs::{InputFile, get_unique_std_input_file}, + tuples::{Handle, MatchName, RefIndexable}, }; #[cfg(all(feature = "intel_pt", target_os = "linux"))] use libc::STDIN_FILENO; @@ -36,8 +36,9 @@ use nix::{ signal::Signal, wait::WaitStatus, wait::{ - waitpid, WaitPidFlag, + WaitPidFlag, WaitStatus::{Exited, PtraceEvent, Signaled, Stopped}, + waitpid, }, }, unistd::Pid, @@ -49,12 +50,12 @@ use super::HasTimeout; #[cfg(target_os = "linux")] use crate::executors::hooks::ExecutorHooksTuple; use crate::{ + Error, executors::{Executor, ExitKind, HasObservers}, inputs::HasTargetBytes, observers::{ObserversTuple, StdErrObserver, StdOutObserver}, state::HasExecutions, std::borrow::ToOwned, - Error, }; /// How to deliver input to an external program @@ -151,13 +152,18 @@ where InputLocation::StdIn => { let mut handle = self.command.stdin(Stdio::piped()).spawn()?; let mut stdin = handle.stdin.take().unwrap(); - if let Err(err) = stdin.write_all(input.target_bytes().as_slice()) { - if err.kind() != std::io::ErrorKind::BrokenPipe { - return Err(err.into()); + match stdin.write_all(input.target_bytes().as_slice()) { + Err(err) => { + if err.kind() != std::io::ErrorKind::BrokenPipe { + return Err(err.into()); + } } - } else if let Err(err) = stdin.flush() { - if err.kind() != std::io::ErrorKind::BrokenPipe { - return Err(err.into()); + _ => { + if let Err(err) = stdin.flush() { + if err.kind() != std::io::ErrorKind::BrokenPipe { + return Err(err.into()); + } + } } } drop(stdin); @@ -208,9 +214,9 @@ where use nix::{ sys::{ personality, ptrace, - signal::{raise, Signal}, + signal::{Signal, raise}, }, - unistd::{alarm, dup2, execve, fork, pipe, write, ForkResult}, + unistd::{ForkResult, alarm, dup2, execve, fork, pipe, write}, }; match unsafe { fork() } { @@ -482,9 +488,9 @@ where // Stopped(pid, Signal::SIGKILL) if pid == child => ExitKind::Oom, s => { // TODO other cases? - return Err(Error::unsupported( - format!("Target program returned an unexpected state when waiting on it. {s:?} (waiting for pid {child})") - )); + return Err(Error::unsupported(format!( + "Target program returned an unexpected state when waiting on it. {s:?} (waiting for pid {child})" + ))); } }; @@ -746,11 +752,11 @@ impl CommandExecutorBuilder { /// }; /// /// use libafl::{ +/// Error, /// corpus::Corpus, -/// executors::{command::CommandConfigurator, Executor}, +/// executors::{Executor, command::CommandConfigurator}, /// inputs::{BytesInput, HasTargetBytes, Input}, /// state::HasExecutions, -/// Error, /// }; /// use libafl_bolts::AsSlice; /// #[derive(Debug)] @@ -861,8 +867,8 @@ mod tests { use crate::{ events::SimpleEventManager, executors::{ - command::{CommandExecutor, InputLocation}, Executor, + command::{CommandExecutor, InputLocation}, }, fuzzer::NopFuzzer, inputs::{BytesInput, NopInput}, diff --git a/libafl/src/executors/differential.rs b/libafl/src/executors/differential.rs index f9406d6b9e..61e5af8d5d 100644 --- a/libafl/src/executors/differential.rs +++ b/libafl/src/executors/differential.rs @@ -18,9 +18,9 @@ use serde::{Deserialize, Serialize}; use super::HasTimeout; use crate::{ + Error, executors::{Executor, ExitKind, HasObservers}, observers::{DifferentialObserversTuple, ObserversTuple}, - Error, }; /// A [`DiffExecutor`] wraps a primary executor, forwarding its methods, and a secondary one @@ -200,23 +200,23 @@ where { #[expect(deprecated)] fn match_name(&self, name: &str) -> Option<&T> { - if let Some(t) = self.primary.as_ref().match_name::(name) { - Some(t) - } else if let Some(t) = self.secondary.as_ref().match_name::(name) { - Some(t) - } else { - self.differential.match_name::(name) + match self.primary.as_ref().match_name::(name) { + Some(t) => Some(t), + _ => match self.secondary.as_ref().match_name::(name) { + Some(t) => Some(t), + _ => self.differential.match_name::(name), + }, } } #[expect(deprecated)] fn match_name_mut(&mut self, name: &str) -> Option<&mut T> { - if let Some(t) = self.primary.as_mut().match_name_mut::(name) { - Some(t) - } else if let Some(t) = self.secondary.as_mut().match_name_mut::(name) { - Some(t) - } else { - self.differential.match_name_mut::(name) + match self.primary.as_mut().match_name_mut::(name) { + Some(t) => Some(t), + _ => match self.secondary.as_mut().match_name_mut::(name) { + Some(t) => Some(t), + _ => self.differential.match_name_mut::(name), + }, } } } diff --git a/libafl/src/executors/forkserver.rs b/libafl/src/executors/forkserver.rs index 7aa726188d..5fa4e3c237 100644 --- a/libafl/src/executors/forkserver.rs +++ b/libafl/src/executors/forkserver.rs @@ -19,18 +19,18 @@ use std::{ }; use libafl_bolts::{ - fs::{get_unique_std_input_file, InputFile}, + AsSlice, AsSliceMut, Truncate, + fs::{InputFile, get_unique_std_input_file}, os::{dup2, pipes::Pipe}, ownedref::OwnedSlice, shmem::{ShMem, ShMemProvider, UnixShMem, UnixShMemProvider}, tuples::{Handle, Handled, MatchNameRef, Prepend, RefIndexable}, - AsSlice, AsSliceMut, Truncate, }; use libc::RLIM_INFINITY; use nix::{ sys::{ - select::{pselect, FdSet}, - signal::{kill, SigSet, Signal}, + select::{FdSet, pselect}, + signal::{SigSet, Signal, kill}, time::TimeSpec, wait::waitpid, }, @@ -40,15 +40,15 @@ use nix::{ use super::HasTimeout; #[cfg(feature = "regex")] use crate::observers::{ - get_asan_runtime_flags, get_asan_runtime_flags_with_log_path, AsanBacktraceObserver, + AsanBacktraceObserver, get_asan_runtime_flags, get_asan_runtime_flags_with_log_path, }; use crate::{ + Error, executors::{Executor, ExitKind, HasObservers}, inputs::{BytesInput, HasTargetBytes, Input, NopTargetBytesConverter, TargetBytesConverter}, mutators::Tokens, observers::{MapObserver, Observer, ObserversTuple}, state::HasExecutions, - Error, }; const FORKSRV_FD: i32 = 198; @@ -365,7 +365,9 @@ impl Forkserver { kill_signal: Signal, ) -> Result { let Some(coverage_map_size) = coverage_map_size else { - return Err(Error::unknown("Coverage map size unknown. Use coverage_map_size() to tell the forkserver about the map size.")); + return Err(Error::unknown( + "Coverage map size unknown. Use coverage_map_size() to tell the forkserver about the map size.", + )); }; if env::var("AFL_MAP_SIZE").is_err() { @@ -442,7 +444,7 @@ impl Forkserver { Err(err) => { return Err(Error::illegal_state(format!( "Could not spawn the forkserver: {err:#?}" - ))) + ))); } }; @@ -648,8 +650,8 @@ where impl ForkserverExecutor<(), (), (), UnixShMem, ()> { /// Builder for `ForkserverExecutor` #[must_use] - pub fn builder( - ) -> ForkserverExecutorBuilder<'static, NopTargetBytesConverter, UnixShMemProvider> + pub fn builder() + -> ForkserverExecutorBuilder<'static, NopTargetBytesConverter, UnixShMemProvider> { ForkserverExecutorBuilder::new() } @@ -977,7 +979,11 @@ where Some(provider) => { // setup shared memory let mut shmem = provider.new_shmem(self.max_input_size + SHMEM_FUZZ_HDR_SIZE)?; - shmem.write_to_env("__AFL_SHM_FUZZ_ID")?; + // # Safety + // This is likely single threade here, we're likely fine if it's not. + unsafe { + shmem.write_to_env("__AFL_SHM_FUZZ_ID")?; + } let size_in_bytes = (self.max_input_size + SHMEM_FUZZ_HDR_SIZE).to_ne_bytes(); shmem.as_slice_mut()[..4].clone_from_slice(&size_in_bytes[..4]); @@ -1003,7 +1009,7 @@ where None => { return Err(Error::illegal_argument( "ForkserverExecutorBuilder::build: target file not found".to_string(), - )) + )); } }; @@ -1042,7 +1048,9 @@ where let version: u32 = status as u32 - 0x41464c00_u32; match version { 0 => { - return Err(Error::illegal_state("Fork server version is not assigned, this should not happen. Recompile target.")); + return Err(Error::illegal_state( + "Fork server version is not assigned, this should not happen. Recompile target.", + )); } FS_NEW_VERSION_MIN..=FS_NEW_VERSION_MAX => { // good, do nothing @@ -1101,9 +1109,9 @@ where let tokens_size_max = 0xffffff; if !(2..=tokens_size_max).contains(&autotokens_size) { - return Err(Error::illegal_state( - format!("Autotokens size is incorrect, expected 2 to {tokens_size_max} (inclusive), but got {autotokens_size}. Make sure your afl-cc verison is up to date."), - )); + return Err(Error::illegal_state(format!( + "Autotokens size is incorrect, expected 2 to {tokens_size_max} (inclusive), but got {autotokens_size}. Make sure your afl-cc verison is up to date." + ))); } log::info!("Autotokens size {autotokens_size:x}"); let buf = forkserver @@ -1223,7 +1231,7 @@ where return Err(Error::illegal_state(format!( "The target map size is {actual_map_size} but the allocated map size is {max_size}. \ Increase the initial size of the forkserver map to at least that size using the forkserver builder's `coverage_map_size`." - ))); + ))); } } else { return Err(Error::illegal_state(format!( @@ -1280,11 +1288,14 @@ where // subsequent arguments as regular arguments use_arg_0_as_program = false; } else if item.as_ref() == "@@" { - if let Some(name) = &moved.input_filename.clone() { - // If the input file name has been modified, use this one - moved = moved.arg_input_file(name); - } else { - moved = moved.arg_input_file_std(); + match &moved.input_filename.clone() { + Some(name) => { + // If the input file name has been modified, use this one + moved = moved.arg_input_file(name); + } + _ => { + moved = moved.arg_input_file_std(); + } } } else { moved = moved.arg(item); @@ -1469,8 +1480,8 @@ impl<'a> ForkserverExecutorBuilder<'a, NopTargetBytesConverter, Unix /// in case no input file is specified. /// If `debug_child` is set, the child will print to `stdout`/`stderr`. #[must_use] - pub fn new( - ) -> ForkserverExecutorBuilder<'a, NopTargetBytesConverter, UnixShMemProvider> { + pub fn new() + -> ForkserverExecutorBuilder<'a, NopTargetBytesConverter, UnixShMemProvider> { ForkserverExecutorBuilder { program: None, arguments: vec![], @@ -1623,18 +1634,18 @@ mod tests { use std::ffi::OsString; use libafl_bolts::{ + AsSliceMut, shmem::{ShMem, ShMemProvider, UnixShMemProvider}, tuples::tuple_list, - AsSliceMut, }; use serial_test::serial; use crate::{ + Error, corpus::NopCorpus, - executors::forkserver::{ForkserverExecutor, FAILED_TO_START_FORKSERVER_MSG}, + executors::forkserver::{FAILED_TO_START_FORKSERVER_MSG, ForkserverExecutor}, inputs::BytesInput, observers::{ConstMapObserver, HitcountsMapObserver}, - Error, }; #[test] @@ -1648,7 +1659,11 @@ mod tests { let mut shmem_provider = UnixShMemProvider::new().unwrap(); let mut shmem = shmem_provider.new_shmem(MAP_SIZE).unwrap(); - shmem.write_to_env("__AFL_SHM_ID").unwrap(); + // # Safety + // There's a slight chance this is racey but very unlikely in the normal use case + unsafe { + shmem.write_to_env("__AFL_SHM_ID").unwrap(); + } let shmem_buf: &mut [u8; MAP_SIZE] = shmem.as_slice_mut().try_into().unwrap(); let edges_observer = HitcountsMapObserver::new(ConstMapObserver::<_, MAP_SIZE>::new( diff --git a/libafl/src/executors/hooks/inprocess.rs b/libafl/src/executors/hooks/inprocess.rs index 03fed6b1bf..6831e1bfc1 100644 --- a/libafl/src/executors/hooks/inprocess.rs +++ b/libafl/src/executors/hooks/inprocess.rs @@ -2,7 +2,7 @@ #[cfg(all(target_os = "linux", feature = "std"))] use core::mem::zeroed; #[cfg(any(unix, all(windows, feature = "std")))] -use core::sync::atomic::{compiler_fence, Ordering}; +use core::sync::atomic::{Ordering, compiler_fence}; use core::{ ffi::c_void, marker::PhantomData, @@ -13,7 +13,7 @@ use core::{ #[cfg(all(target_os = "linux", feature = "std"))] use libafl_bolts::current_time; #[cfg(all(unix, feature = "std"))] -use libafl_bolts::minibsod::{generate_minibsod_to_vec, BsodInfo}; +use libafl_bolts::minibsod::{BsodInfo, generate_minibsod_to_vec}; #[cfg(all(unix, feature = "std", not(miri)))] use libafl_bolts::os::unix_signals::setup_signal_handler; #[cfg(all(windows, feature = "std"))] @@ -24,16 +24,16 @@ use windows::Win32::System::Threading::{CRITICAL_SECTION, PTP_TIMER}; #[cfg(feature = "std")] use crate::executors::hooks::timer::TimerStruct; use crate::{ + Error, HasObjective, events::{EventFirer, EventRestarter}, - executors::{hooks::ExecutorHook, inprocess::HasInProcessHooks, Executor, HasObservers}, + executors::{Executor, HasObservers, hooks::ExecutorHook, inprocess::HasInProcessHooks}, feedbacks::Feedback, state::{HasExecutions, HasSolutions}, - Error, HasObjective, }; #[cfg(all(unix, feature = "std"))] use crate::{ executors::{ - hooks::unix::unix_signal_handler, inprocess::run_observers_and_save_state, ExitKind, + ExitKind, hooks::unix::unix_signal_handler, inprocess::run_observers_and_save_state, }, state::HasCorpus, }; @@ -445,43 +445,45 @@ impl InProcessExecutorHandlerData { Z: HasObjective, I: Input + Clone, { - if self.is_valid() { - let executor = self.executor_mut::(); - // disarms timeout in case of timeout - let state = self.state_mut::(); - let event_mgr = self.event_mgr_mut::(); - let fuzzer = self.fuzzer_mut::(); - let input = self.take_current_input::(); + unsafe { + if self.is_valid() { + let executor = self.executor_mut::(); + // disarms timeout in case of timeout + let state = self.state_mut::(); + let event_mgr = self.event_mgr_mut::(); + let fuzzer = self.fuzzer_mut::(); + let input = self.take_current_input::(); - log::error!("Target crashed!"); + log::error!("Target crashed!"); - if let Some(bsod_info) = bsod_info { - let bsod = generate_minibsod_to_vec( - bsod_info.signal, - &bsod_info.siginfo, - bsod_info.ucontext.as_ref(), - ); + if let Some(bsod_info) = bsod_info { + let bsod = generate_minibsod_to_vec( + bsod_info.signal, + &bsod_info.siginfo, + bsod_info.ucontext.as_ref(), + ); - if let Ok(bsod) = bsod { - if let Ok(r) = std::str::from_utf8(&bsod) { - log::error!("{}", r); + if let Ok(bsod) = bsod { + if let Ok(r) = std::str::from_utf8(&bsod) { + log::error!("{}", r); + } } } + + run_observers_and_save_state::( + executor, + state, + input, + fuzzer, + event_mgr, + ExitKind::Crash, + ); + + return true; } - run_observers_and_save_state::( - executor, - state, - input, - fuzzer, - event_mgr, - ExitKind::Crash, - ); - - return true; + false } - - false } } diff --git a/libafl/src/executors/hooks/inprocess_fork.rs b/libafl/src/executors/hooks/inprocess_fork.rs index 9db361c55d..66245cced3 100644 --- a/libafl/src/executors/hooks/inprocess_fork.rs +++ b/libafl/src/executors/hooks/inprocess_fork.rs @@ -5,23 +5,22 @@ use core::{ marker::PhantomData, mem::transmute, ptr::null, - sync::atomic::{compiler_fence, Ordering}, + sync::atomic::{Ordering, compiler_fence}, }; #[cfg(not(miri))] use libafl_bolts::os::unix_signals::setup_signal_handler; -use libafl_bolts::os::unix_signals::{ucontext_t, Signal, SignalHandler}; +use libafl_bolts::os::unix_signals::{Signal, SignalHandler, ucontext_t}; use libc::siginfo_t; use crate::{ + Error, executors::{ - common_signals, + HasObservers, common_signals, hooks::ExecutorHook, - inprocess_fork::{child_signal_handlers, ForkHandlerFuncPtr}, - HasObservers, + inprocess_fork::{ForkHandlerFuncPtr, child_signal_handlers}, }, observers::ObserversTuple, - Error, }; /// The inmem fork executor's hooks. diff --git a/libafl/src/executors/hooks/timer.rs b/libafl/src/executors/hooks/timer.rs index 3fb7dd72e6..cea8edc340 100644 --- a/libafl/src/executors/hooks/timer.rs +++ b/libafl/src/executors/hooks/timer.rs @@ -10,7 +10,7 @@ pub(crate) const ITIMER_REAL: core::ffi::c_int = 0; use core::{ ffi::c_void, ptr::write_volatile, - sync::atomic::{compiler_fence, Ordering}, + sync::atomic::{Ordering, compiler_fence}, }; #[cfg(target_os = "linux")] @@ -19,9 +19,9 @@ use libafl_bolts::current_time; use windows::Win32::{ Foundation::FILETIME, System::Threading::{ - CreateThreadpoolTimer, EnterCriticalSection, InitializeCriticalSection, - LeaveCriticalSection, SetThreadpoolTimer, CRITICAL_SECTION, PTP_CALLBACK_INSTANCE, - PTP_TIMER, TP_CALLBACK_ENVIRON_V3, + CRITICAL_SECTION, CreateThreadpoolTimer, EnterCriticalSection, InitializeCriticalSection, + LeaveCriticalSection, PTP_CALLBACK_INSTANCE, PTP_TIMER, SetThreadpoolTimer, + TP_CALLBACK_ENVIRON_V3, }, }; @@ -59,7 +59,7 @@ pub(crate) struct Itimerval { } #[cfg(all(unix, not(target_os = "linux")))] -extern "C" { +unsafe extern "C" { pub(crate) fn setitimer( which: libc::c_int, new_value: *mut Itimerval, diff --git a/libafl/src/executors/hooks/unix.rs b/libafl/src/executors/hooks/unix.rs index 536e144d11..f7df4d74f5 100644 --- a/libafl/src/executors/hooks/unix.rs +++ b/libafl/src/executors/hooks/unix.rs @@ -5,16 +5,15 @@ pub mod unix_signal_handler { use core::mem::transmute; use std::{io::Write, panic}; - use libafl_bolts::os::unix_signals::{ucontext_t, Signal, SignalHandler}; + use libafl_bolts::os::unix_signals::{Signal, SignalHandler, ucontext_t}; use libc::siginfo_t; use crate::{ events::{EventFirer, EventRestarter}, executors::{ - common_signals, - hooks::inprocess::{HasTimeout, InProcessExecutorHandlerData, GLOBAL_STATE}, - inprocess::{run_observers_and_save_state, HasInProcessHooks}, - Executor, ExitKind, HasObservers, + Executor, ExitKind, HasObservers, common_signals, + hooks::inprocess::{GLOBAL_STATE, HasTimeout, InProcessExecutorHandlerData}, + inprocess::{HasInProcessHooks, run_observers_and_save_state}, }, feedbacks::Feedback, fuzzer::HasObjective, @@ -147,39 +146,41 @@ pub mod unix_signal_handler { Z: HasObjective, I: Input + Clone, { - // this stuff is for batch timeout - if !data.executor_ptr.is_null() - && data - .executor_mut::() - .inprocess_hooks_mut() - .handle_timeout(data) - { - return; + unsafe { + // this stuff is for batch timeout + if !data.executor_ptr.is_null() + && data + .executor_mut::() + .inprocess_hooks_mut() + .handle_timeout(data) + { + return; + } + + if !data.is_valid() { + log::warn!("TIMEOUT or SIGUSR2 happened, but currently not fuzzing."); + return; + } + + let executor = data.executor_mut::(); + let state = data.state_mut::(); + let event_mgr = data.event_mgr_mut::(); + let fuzzer = data.fuzzer_mut::(); + let input = data.take_current_input::(); + + log::error!("Timeout in fuzz run."); + + run_observers_and_save_state::( + executor, + state, + input, + fuzzer, + event_mgr, + ExitKind::Timeout, + ); + log::info!("Exiting"); + libc::_exit(55); } - - if !data.is_valid() { - log::warn!("TIMEOUT or SIGUSR2 happened, but currently not fuzzing."); - return; - } - - let executor = data.executor_mut::(); - let state = data.state_mut::(); - let event_mgr = data.event_mgr_mut::(); - let fuzzer = data.fuzzer_mut::(); - let input = data.take_current_input::(); - - log::error!("Timeout in fuzz run."); - - run_observers_and_save_state::( - executor, - state, - input, - fuzzer, - event_mgr, - ExitKind::Timeout, - ); - log::info!("Exiting"); - libc::_exit(55); } /// Crash-Handler for in-process fuzzing. @@ -203,68 +204,29 @@ pub mod unix_signal_handler { Z: HasObjective, I: Input + Clone, { - #[cfg(all(target_os = "android", target_arch = "aarch64"))] - let _context = _context.map(|p| { - &mut *(((core::ptr::from_mut(p) as *mut libc::c_void as usize) + 128) - as *mut libc::c_void as *mut ucontext_t) - }); + unsafe { + #[cfg(all(target_os = "android", target_arch = "aarch64"))] + let _context = _context.map(|p| { + &mut *(((core::ptr::from_mut(p) as *mut libc::c_void as usize) + 128) + as *mut libc::c_void as *mut ucontext_t) + }); - log::error!("Crashed with {signal}"); - if data.is_valid() { - let executor = data.executor_mut::(); - // disarms timeout in case of timeout - let state = data.state_mut::(); - let event_mgr = data.event_mgr_mut::(); - let fuzzer = data.fuzzer_mut::(); - let input = data.take_current_input::(); + log::error!("Crashed with {signal}"); + if data.is_valid() { + let executor = data.executor_mut::(); + // disarms timeout in case of timeout + let state = data.state_mut::(); + let event_mgr = data.event_mgr_mut::(); + let fuzzer = data.fuzzer_mut::(); + let input = data.take_current_input::(); - log::error!("Child crashed!"); - - { - let mut bsod = Vec::new(); - { - let mut writer = std::io::BufWriter::new(&mut bsod); - let _ = writeln!(writer, "input: {:?}", input.generate_name(None)); - let bsod = libafl_bolts::minibsod::generate_minibsod( - &mut writer, - signal, - _info, - _context.as_deref(), - ); - if bsod.is_err() { - log::error!("generate_minibsod failed"); - } - let _ = writer.flush(); - } - if let Ok(r) = std::str::from_utf8(&bsod) { - log::error!("{}", r); - } - } - - run_observers_and_save_state::( - executor, - state, - input, - fuzzer, - event_mgr, - ExitKind::Crash, - ); - } else { - { - log::error!("Double crash\n"); - #[cfg(target_os = "android")] - let si_addr = (_info._pad[0] as i64) | ((_info._pad[1] as i64) << 32); - #[cfg(not(target_os = "android"))] - let si_addr = { _info.si_addr() as usize }; - - log::error!( - "We crashed at addr 0x{si_addr:x}, but are not in the target... Bug in the fuzzer? Exiting." - ); + log::error!("Child crashed!"); { let mut bsod = Vec::new(); { let mut writer = std::io::BufWriter::new(&mut bsod); + let _ = writeln!(writer, "input: {:?}", input.generate_name(None)); let bsod = libafl_bolts::minibsod::generate_minibsod( &mut writer, signal, @@ -280,19 +242,60 @@ pub mod unix_signal_handler { log::error!("{}", r); } } - } - { - log::error!("Type QUIT to restart the child"); - let mut line = String::new(); - while line.trim() != "QUIT" { - let _ = std::io::stdin().read_line(&mut line); + run_observers_and_save_state::( + executor, + state, + input, + fuzzer, + event_mgr, + ExitKind::Crash, + ); + } else { + { + log::error!("Double crash\n"); + #[cfg(target_os = "android")] + let si_addr = (_info._pad[0] as i64) | ((_info._pad[1] as i64) << 32); + #[cfg(not(target_os = "android"))] + let si_addr = { _info.si_addr() as usize }; + + log::error!( + "We crashed at addr 0x{si_addr:x}, but are not in the target... Bug in the fuzzer? Exiting." + ); + + { + let mut bsod = Vec::new(); + { + let mut writer = std::io::BufWriter::new(&mut bsod); + let bsod = libafl_bolts::minibsod::generate_minibsod( + &mut writer, + signal, + _info, + _context.as_deref(), + ); + if bsod.is_err() { + log::error!("generate_minibsod failed"); + } + let _ = writer.flush(); + } + if let Ok(r) = std::str::from_utf8(&bsod) { + log::error!("{}", r); + } + } } + + { + log::error!("Type QUIT to restart the child"); + let mut line = String::new(); + while line.trim() != "QUIT" { + let _ = std::io::stdin().read_line(&mut line); + } + } + + // TODO tell the parent to not restart } - // TODO tell the parent to not restart + libc::_exit(128 + (signal as i32)); } - - libc::_exit(128 + (signal as i32)); } } diff --git a/libafl/src/executors/hooks/windows.rs b/libafl/src/executors/hooks/windows.rs index 77eccd4d92..78fc20b37a 100644 --- a/libafl/src/executors/hooks/windows.rs +++ b/libafl/src/executors/hooks/windows.rs @@ -1,18 +1,18 @@ -/// Same as `inproc_crash_handler`, but this is called when address sanitizer exits, not from the exception handler +/// In-Process crash handling for `Windows` #[cfg(all(windows, feature = "std"))] pub mod windows_asan_handler { use alloc::string::String; - use core::sync::atomic::{compiler_fence, Ordering}; + use core::sync::atomic::{Ordering, compiler_fence}; use windows::Win32::System::Threading::{ - EnterCriticalSection, ExitProcess, LeaveCriticalSection, CRITICAL_SECTION, + CRITICAL_SECTION, EnterCriticalSection, ExitProcess, LeaveCriticalSection, }; use crate::{ events::{EventFirer, EventRestarter}, executors::{ - hooks::inprocess::GLOBAL_STATE, inprocess::run_observers_and_save_state, Executor, - ExitKind, HasObservers, + Executor, ExitKind, HasObservers, hooks::inprocess::GLOBAL_STATE, + inprocess::run_observers_and_save_state, }, feedbacks::Feedback, fuzzer::HasObjective, @@ -33,75 +33,79 @@ pub mod windows_asan_handler { S: HasExecutions + HasSolutions + HasCurrentTestcase, Z: HasObjective, { - let data = &raw mut GLOBAL_STATE; - let in_handler = (*data).set_in_handler(true); + unsafe { + let data = &raw mut GLOBAL_STATE; + let in_handler = (*data).set_in_handler(true); - if in_handler { - log::error!("We crashed inside a asan death handler, but this should never happen!"); - ExitProcess(56); - } - - // Have we set a timer_before? - if (*data).ptp_timer.is_some() { - /* - We want to prevent the timeout handler being run while the main thread is executing the crash handler - Timeout handler runs if it has access to the critical section or data.in_target == 0 - Writing 0 to the data.in_target makes the timeout handler makes the timeout handler invalid. - */ - compiler_fence(Ordering::SeqCst); - EnterCriticalSection((*data).critical as *mut CRITICAL_SECTION); - compiler_fence(Ordering::SeqCst); - (*data).in_target = 0; - compiler_fence(Ordering::SeqCst); - LeaveCriticalSection((*data).critical as *mut CRITICAL_SECTION); - compiler_fence(Ordering::SeqCst); - } - - log::error!("ASAN detected crash!"); - if (*data).current_input_ptr.is_null() { - { - log::error!("Double crash\n"); + if in_handler { log::error!( - "ASAN detected crash but we're not in the target... Bug in the fuzzer? Exiting.", + "We crashed inside a asan death handler, but this should never happen!" + ); + ExitProcess(56); + } + + // Have we set a timer_before? + if (*data).ptp_timer.is_some() { + /* + We want to prevent the timeout handler being run while the main thread is executing the crash handler + Timeout handler runs if it has access to the critical section or data.in_target == 0 + Writing 0 to the data.in_target makes the timeout handler makes the timeout handler invalid. + */ + compiler_fence(Ordering::SeqCst); + EnterCriticalSection((*data).critical as *mut CRITICAL_SECTION); + compiler_fence(Ordering::SeqCst); + (*data).in_target = 0; + compiler_fence(Ordering::SeqCst); + LeaveCriticalSection((*data).critical as *mut CRITICAL_SECTION); + compiler_fence(Ordering::SeqCst); + } + + log::error!("ASAN detected crash!"); + if (*data).current_input_ptr.is_null() { + { + log::error!("Double crash\n"); + log::error!( + "ASAN detected crash but we're not in the target... Bug in the fuzzer? Exiting.", + ); + } + #[cfg(feature = "std")] + { + log::error!("Type QUIT to restart the child"); + let mut line = String::new(); + while line.trim() != "QUIT" { + let _ = std::io::stdin().read_line(&mut line); + } + } + + // TODO tell the parent to not restart + } else { + let executor = (*data).executor_mut::(); + // reset timer + if (*data).ptp_timer.is_some() { + (*data).ptp_timer = None; + } + + let state = (*data).state_mut::(); + let fuzzer = (*data).fuzzer_mut::(); + let event_mgr = (*data).event_mgr_mut::(); + + log::error!("Child crashed!"); + + // Make sure we don't crash in the crash handler forever. + let input = (*data).take_current_input::(); + + run_observers_and_save_state::( + executor, + state, + input, + fuzzer, + event_mgr, + ExitKind::Crash, ); } - #[cfg(feature = "std")] - { - log::error!("Type QUIT to restart the child"); - let mut line = String::new(); - while line.trim() != "QUIT" { - let _ = std::io::stdin().read_line(&mut line); - } - } - - // TODO tell the parent to not restart - } else { - let executor = (*data).executor_mut::(); - // reset timer - if (*data).ptp_timer.is_some() { - (*data).ptp_timer = None; - } - - let state = (*data).state_mut::(); - let fuzzer = (*data).fuzzer_mut::(); - let event_mgr = (*data).event_mgr_mut::(); - - log::error!("Child crashed!"); - - // Make sure we don't crash in the crash handler forever. - let input = (*data).take_current_input::(); - - run_observers_and_save_state::( - executor, - state, - input, - fuzzer, - event_mgr, - ExitKind::Crash, - ); + // Don't need to exit, Asan will exit for us + // ExitProcess(1); } - // Don't need to exit, Asan will exit for us - // ExitProcess(1); } } @@ -115,7 +119,7 @@ pub mod windows_exception_handler { ffi::c_void, mem::transmute, ptr, - sync::atomic::{compiler_fence, Ordering}, + sync::atomic::{Ordering, compiler_fence}, }; #[cfg(feature = "std")] use std::io::Write; @@ -123,19 +127,19 @@ pub mod windows_exception_handler { use std::panic; use libafl_bolts::os::windows_exceptions::{ - ExceptionCode, ExceptionHandler, CRASH_EXCEPTIONS, EXCEPTION_HANDLERS_SIZE, - EXCEPTION_POINTERS, + CRASH_EXCEPTIONS, EXCEPTION_HANDLERS_SIZE, EXCEPTION_POINTERS, ExceptionCode, + ExceptionHandler, }; use windows::Win32::System::Threading::{ - EnterCriticalSection, ExitProcess, LeaveCriticalSection, CRITICAL_SECTION, + CRITICAL_SECTION, EnterCriticalSection, ExitProcess, LeaveCriticalSection, }; use crate::{ events::{EventFirer, EventRestarter}, executors::{ - hooks::inprocess::{HasTimeout, InProcessExecutorHandlerData, GLOBAL_STATE}, - inprocess::{run_observers_and_save_state, HasInProcessHooks}, Executor, ExitKind, HasObservers, + hooks::inprocess::{GLOBAL_STATE, HasTimeout, InProcessExecutorHandlerData}, + inprocess::{HasInProcessHooks, run_observers_and_save_state}, }, feedbacks::Feedback, fuzzer::HasObjective, @@ -270,36 +274,41 @@ pub mod windows_exception_handler { Z: HasObjective, { let data: &mut InProcessExecutorHandlerData = - &mut *(global_state as *mut InProcessExecutorHandlerData); + unsafe { &mut *(global_state as *mut InProcessExecutorHandlerData) }; compiler_fence(Ordering::SeqCst); - EnterCriticalSection((data.critical as *mut CRITICAL_SECTION).as_mut().unwrap()); + unsafe { + EnterCriticalSection((data.critical as *mut CRITICAL_SECTION).as_mut().unwrap()); + } compiler_fence(Ordering::SeqCst); if !data.executor_ptr.is_null() - && data - .executor_mut::() - .inprocess_hooks_mut() - .handle_timeout() + && unsafe { + data.executor_mut::() + .inprocess_hooks_mut() + .handle_timeout() + } { compiler_fence(Ordering::SeqCst); - LeaveCriticalSection((data.critical as *mut CRITICAL_SECTION).as_mut().unwrap()); + unsafe { + LeaveCriticalSection((data.critical as *mut CRITICAL_SECTION).as_mut().unwrap()); + } compiler_fence(Ordering::SeqCst); return; } if data.in_target == 1 { - let executor = data.executor_mut::(); - let state = data.state_mut::(); - let fuzzer = data.fuzzer_mut::(); - let event_mgr = data.event_mgr_mut::(); + let executor = unsafe { data.executor_mut::() }; + let state = unsafe { data.state_mut::() }; + let fuzzer = unsafe { data.fuzzer_mut::() }; + let event_mgr = unsafe { data.event_mgr_mut::() }; if data.current_input_ptr.is_null() { log::error!("TIMEOUT or SIGUSR2 happened, but currently not fuzzing. Exiting"); } else { log::error!("Timeout in fuzz run."); - let input = (data.current_input_ptr as *const I).as_ref().unwrap(); + let input = unsafe { (data.current_input_ptr as *const I).as_ref().unwrap() }; data.current_input_ptr = ptr::null_mut(); run_observers_and_save_state::( @@ -313,11 +322,15 @@ pub mod windows_exception_handler { compiler_fence(Ordering::SeqCst); - ExitProcess(1); + unsafe { + ExitProcess(1); + } } } compiler_fence(Ordering::SeqCst); - LeaveCriticalSection((data.critical as *mut CRITICAL_SECTION).as_mut().unwrap()); + unsafe { + LeaveCriticalSection((data.critical as *mut CRITICAL_SECTION).as_mut().unwrap()); + } compiler_fence(Ordering::SeqCst); // log::info!("TIMER INVOKED!"); } @@ -346,37 +359,43 @@ pub mod windows_exception_handler { Writing 0 to the data.in_target makes the timeout handler makes the timeout handler invalid. */ compiler_fence(Ordering::SeqCst); - EnterCriticalSection(data.critical as *mut CRITICAL_SECTION); + unsafe { + EnterCriticalSection(data.critical as *mut CRITICAL_SECTION); + } compiler_fence(Ordering::SeqCst); data.in_target = 0; compiler_fence(Ordering::SeqCst); - LeaveCriticalSection(data.critical as *mut CRITICAL_SECTION); + unsafe { + LeaveCriticalSection(data.critical as *mut CRITICAL_SECTION); + } compiler_fence(Ordering::SeqCst); } // Is this really crash? let mut is_crash = true; #[cfg(feature = "std")] - if let Some(exception_pointers) = exception_pointers.as_mut() { - let code: ExceptionCode = ExceptionCode::from( + if let Some(exception_pointers) = unsafe { exception_pointers.as_mut() } { + let code: ExceptionCode = ExceptionCode::from(unsafe { exception_pointers .ExceptionRecord .as_mut() .unwrap() .ExceptionCode - .0, - ); + .0 + }); let exception_list = data.exceptions(); if exception_list.contains(&code) { log::error!( "Crashed with {code} at {:?} in thread {:?}", - exception_pointers - .ExceptionRecord - .as_mut() - .unwrap() - .ExceptionAddress, - winapi::um::processthreadsapi::GetCurrentThreadId() + unsafe { + exception_pointers + .ExceptionRecord + .as_mut() + .unwrap() + .ExceptionAddress + }, + unsafe { winapi::um::processthreadsapi::GetCurrentThreadId() } ); } else { // log::trace!("Exception code received, but {code} is not in CRASH_EXCEPTIONS"); @@ -389,16 +408,18 @@ pub mod windows_exception_handler { if data.current_input_ptr.is_null() { { log::error!("Double crash\n"); - let crash_addr = exception_pointers - .as_mut() - .unwrap() - .ExceptionRecord - .as_mut() - .unwrap() - .ExceptionAddress as usize; + let crash_addr = unsafe { + exception_pointers + .as_mut() + .unwrap() + .ExceptionRecord + .as_mut() + .unwrap() + .ExceptionAddress as usize + }; log::error!( - "We crashed at addr 0x{crash_addr:x}, but are not in the target... Bug in the fuzzer? Exiting." + "We crashed at addr 0x{crash_addr:x}, but are not in the target... Bug in the fuzzer? Exiting." ); } #[cfg(feature = "std")] @@ -412,15 +433,15 @@ pub mod windows_exception_handler { // TODO tell the parent to not restart } else { - let executor = data.executor_mut::(); + let executor = unsafe { data.executor_mut::() }; // reset timer if data.ptp_timer.is_some() { data.ptp_timer = None; } - let state = data.state_mut::(); - let fuzzer = data.fuzzer_mut::(); - let event_mgr = data.event_mgr_mut::(); + let state = unsafe { data.state_mut::() }; + let fuzzer = unsafe { data.fuzzer_mut::() }; + let event_mgr = unsafe { data.event_mgr_mut::() }; if is_crash { log::error!("Child crashed!"); @@ -432,7 +453,7 @@ pub mod windows_exception_handler { if is_crash { log::warn!("Running observers and exiting!"); // // I want to disable the hooks before doing anything, especially before taking a stack dump - let input = data.take_current_input::(); // log::set_max_level(log::LevelFilter::Trace); + let input = unsafe { data.take_current_input::() }; run_observers_and_save_state::( executor, state, @@ -459,7 +480,9 @@ pub mod windows_exception_handler { if is_crash { log::info!("Exiting!"); - ExitProcess(1); + unsafe { + ExitProcess(1); + } } // log::info!("Not Exiting!"); } diff --git a/libafl/src/executors/inprocess/inner.rs b/libafl/src/executors/inprocess/inner.rs index 92e23b750d..cca507dab8 100644 --- a/libafl/src/executors/inprocess/inner.rs +++ b/libafl/src/executors/inprocess/inner.rs @@ -3,11 +3,11 @@ use core::{ fmt::{self, Debug, Formatter}, marker::PhantomData, ptr::{self, null, write_volatile}, - sync::atomic::{compiler_fence, Ordering}, + sync::atomic::{Ordering, compiler_fence}, time::Duration, }; -use libafl_bolts::tuples::{tuple_list, Merge, RefIndexable}; +use libafl_bolts::tuples::{Merge, RefIndexable, tuple_list}; #[cfg(windows)] use windows::Win32::System::Threading::SetThreadStackGuarantee; @@ -16,21 +16,21 @@ use crate::executors::hooks::inprocess::HasTimeout; #[cfg(all(windows, feature = "std"))] use crate::executors::hooks::inprocess::HasTimeout; use crate::{ + Error, events::{EventFirer, EventRestarter}, executors::{ + Executor, HasObservers, hooks::{ - inprocess::{InProcessHooks, GLOBAL_STATE}, ExecutorHooksTuple, + inprocess::{GLOBAL_STATE, InProcessHooks}, }, inprocess::HasInProcessHooks, - Executor, HasObservers, }, feedbacks::Feedback, fuzzer::HasObjective, inputs::Input, observers::ObserversTuple, state::{HasCurrentTestcase, HasExecutions, HasSolutions}, - Error, }; /// The internal state of `GenericInProcessExecutor`. diff --git a/libafl/src/executors/inprocess/mod.rs b/libafl/src/executors/inprocess/mod.rs index d8450dd27e..a1eba71dd9 100644 --- a/libafl/src/executors/inprocess/mod.rs +++ b/libafl/src/executors/inprocess/mod.rs @@ -12,22 +12,22 @@ use core::{ time::Duration, }; -use libafl_bolts::tuples::{tuple_list, RefIndexable}; +use libafl_bolts::tuples::{RefIndexable, tuple_list}; use crate::{ + Error, HasMetadata, corpus::{Corpus, Testcase}, events::{Event, EventFirer, EventRestarter}, executors::{ - hooks::{inprocess::InProcessHooks, ExecutorHooksTuple}, - inprocess::inner::GenericInProcessExecutorInner, Executor, ExitKind, HasObservers, + hooks::{ExecutorHooksTuple, inprocess::InProcessHooks}, + inprocess::inner::GenericInProcessExecutorInner, }, feedbacks::Feedback, fuzzer::HasObjective, inputs::Input, observers::ObserversTuple, state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions}, - Error, HasMetadata, }; /// The inner structure of `InProcessExecutor`. @@ -271,7 +271,6 @@ where ) -> Result where EM: EventFirer + EventRestarter, - OF: Feedback, Z: HasObjective, { @@ -440,6 +439,7 @@ mod tests { use libafl_bolts::{rands::XkcdRand, tuples::tuple_list}; use crate::{ + StdFuzzer, corpus::InMemoryCorpus, events::NopEventManager, executors::{Executor, ExitKind, InProcessExecutor}, @@ -447,7 +447,6 @@ mod tests { inputs::NopInput, schedulers::RandScheduler, state::{NopState, StdState}, - StdFuzzer, }; #[test] diff --git a/libafl/src/executors/inprocess/stateful.rs b/libafl/src/executors/inprocess/stateful.rs index 26265d6028..43ab1598f1 100644 --- a/libafl/src/executors/inprocess/stateful.rs +++ b/libafl/src/executors/inprocess/stateful.rs @@ -8,21 +8,21 @@ use core::{ time::Duration, }; -use libafl_bolts::tuples::{tuple_list, RefIndexable}; +use libafl_bolts::tuples::{RefIndexable, tuple_list}; use crate::{ + Error, events::{EventFirer, EventRestarter}, executors::{ - hooks::{inprocess::InProcessHooks, ExecutorHooksTuple}, - inprocess::{GenericInProcessExecutorInner, HasInProcessHooks}, Executor, ExitKind, HasObservers, + hooks::{ExecutorHooksTuple, inprocess::InProcessHooks}, + inprocess::{GenericInProcessExecutorInner, HasInProcessHooks}, }, feedbacks::Feedback, fuzzer::HasObjective, inputs::Input, observers::ObserversTuple, state::{HasCurrentTestcase, HasExecutions, HasSolutions}, - Error, }; /// The process executor simply calls a target function, as mutable reference to a closure diff --git a/libafl/src/executors/inprocess_fork/inner.rs b/libafl/src/executors/inprocess_fork/inner.rs index 7a9bb569fa..37ad77d2cc 100644 --- a/libafl/src/executors/inprocess_fork/inner.rs +++ b/libafl/src/executors/inprocess_fork/inner.rs @@ -3,32 +3,32 @@ use core::{ fmt::{self, Debug, Formatter}, marker::PhantomData, ptr::{self, null_mut, write_volatile}, - sync::atomic::{compiler_fence, Ordering}, + sync::atomic::{Ordering, compiler_fence}, time::Duration, }; use libafl_bolts::{ os::unix_signals::Signal, shmem::ShMemProvider, - tuples::{tuple_list, Merge, RefIndexable}, + tuples::{Merge, RefIndexable, tuple_list}, }; use nix::{ - sys::wait::{waitpid, WaitStatus}, + sys::wait::{WaitStatus, waitpid}, unistd::Pid, }; #[cfg(all(unix, not(target_os = "linux")))] -use crate::executors::hooks::timer::{setitimer, Itimerval, Timeval, ITIMER_REAL}; +use crate::executors::hooks::timer::{ITIMER_REAL, Itimerval, Timeval, setitimer}; use crate::{ + Error, executors::{ - hooks::{ - inprocess_fork::{InChildProcessHooks, FORK_EXECUTOR_GLOBAL_DATA}, - ExecutorHooksTuple, - }, ExitKind, HasObservers, + hooks::{ + ExecutorHooksTuple, + inprocess_fork::{FORK_EXECUTOR_GLOBAL_DATA, InChildProcessHooks}, + }, }, observers::ObserversTuple, - Error, }; /// Inner state of GenericInProcessExecutor-like structures. @@ -117,32 +117,34 @@ where mgr: &mut EM, input: &I, ) -> Result<(), Error> { - self.shmem_provider.post_fork(true)?; + unsafe { + self.shmem_provider.post_fork(true)?; - self.enter_target(fuzzer, state, mgr, input); - self.hooks.pre_exec_all(state, input); + self.enter_target(fuzzer, state, mgr, input); + self.hooks.pre_exec_all(state, input); - self.observers - .pre_exec_child_all(state, input) - .expect("Failed to run post_exec on observers"); + self.observers + .pre_exec_child_all(state, input) + .expect("Failed to run post_exec on observers"); - #[cfg(target_os = "linux")] - { - let mut timerid: libc::timer_t = null_mut(); - // creates a new per-process interval timer - // we can't do this from the parent, timerid is unique to each process. - libc::timer_create(libc::CLOCK_MONOTONIC, null_mut(), &raw mut timerid); + #[cfg(target_os = "linux")] + { + let mut timerid: libc::timer_t = null_mut(); + // creates a new per-process interval timer + // we can't do this from the parent, timerid is unique to each process. + libc::timer_create(libc::CLOCK_MONOTONIC, null_mut(), &raw mut timerid); - // log::info!("Set timer! {:#?} {timerid:#?}", self.itimerspec); - let _: i32 = libc::timer_settime(timerid, 0, &raw mut self.itimerspec, null_mut()); + // log::info!("Set timer! {:#?} {timerid:#?}", self.itimerspec); + let _: i32 = libc::timer_settime(timerid, 0, &raw mut self.itimerspec, null_mut()); + } + #[cfg(not(target_os = "linux"))] + { + setitimer(ITIMER_REAL, &mut self.itimerval, null_mut()); + } + // log::trace!("{v:#?} {}", nix::errno::errno()); + + Ok(()) } - #[cfg(not(target_os = "linux"))] - { - setitimer(ITIMER_REAL, &mut self.itimerval, null_mut()); - } - // log::trace!("{v:#?} {}", nix::errno::errno()); - - Ok(()) } pub(super) unsafe fn post_run_target_child( @@ -152,14 +154,16 @@ where mgr: &mut EM, input: &I, ) { - self.observers - .post_exec_child_all(state, input, &ExitKind::Ok) - .expect("Failed to run post_exec on observers"); + unsafe { + self.observers + .post_exec_child_all(state, input, &ExitKind::Ok) + .expect("Failed to run post_exec on observers"); - self.hooks.post_exec_all(state, input); - self.leave_target(fuzzer, state, mgr, input); + self.hooks.post_exec_all(state, input); + self.leave_target(fuzzer, state, mgr, input); - libc::_exit(0); + libc::_exit(0); + } } pub(super) fn parent(&mut self, child: Pid) -> Result { diff --git a/libafl/src/executors/inprocess_fork/mod.rs b/libafl/src/executors/inprocess_fork/mod.rs index 9144a0d14a..20f0e7fb5a 100644 --- a/libafl/src/executors/inprocess_fork/mod.rs +++ b/libafl/src/executors/inprocess_fork/mod.rs @@ -5,22 +5,22 @@ use core::{ }; use libafl_bolts::{ - os::unix_signals::{ucontext_t, Signal}, + os::unix_signals::{Signal, ucontext_t}, shmem::ShMemProvider, - tuples::{tuple_list, RefIndexable}, + tuples::{RefIndexable, tuple_list}, }; use libc::siginfo_t; -use nix::unistd::{fork, ForkResult}; +use nix::unistd::{ForkResult, fork}; use super::hooks::ExecutorHooksTuple; use crate::{ + Error, executors::{ - hooks::inprocess_fork::InProcessForkExecutorGlobalData, - inprocess_fork::inner::GenericInProcessForkExecutorInner, Executor, ExitKind, HasObservers, + Executor, ExitKind, HasObservers, hooks::inprocess_fork::InProcessForkExecutorGlobalData, + inprocess_fork::inner::GenericInProcessForkExecutorInner, }, observers::ObserversTuple, state::HasExecutions, - Error, }; /// The signature of the crash handler function @@ -206,13 +206,13 @@ pub mod child_signal_handlers { use alloc::boxed::Box; use std::panic; - use libafl_bolts::os::unix_signals::{ucontext_t, Signal}; + use libafl_bolts::os::unix_signals::{Signal, ucontext_t}; use libc::siginfo_t; use crate::{ executors::{ - hooks::inprocess_fork::{InProcessForkExecutorGlobalData, FORK_EXECUTOR_GLOBAL_DATA}, ExitKind, HasObservers, + hooks::inprocess_fork::{FORK_EXECUTOR_GLOBAL_DATA, InProcessForkExecutorGlobalData}, }, observers::ObserversTuple, }; @@ -259,17 +259,19 @@ pub mod child_signal_handlers { E: HasObservers, E::Observers: ObserversTuple, { - if data.is_valid() { - let executor = data.executor_mut::(); - let mut observers = executor.observers_mut(); - let state = data.state_mut::(); - let input = data.take_current_input::(); - observers - .post_exec_child_all(state, input, &ExitKind::Crash) - .expect("Failed to run post_exec on observers"); - } + unsafe { + if data.is_valid() { + let executor = data.executor_mut::(); + let mut observers = executor.observers_mut(); + let state = data.state_mut::(); + let input = data.take_current_input::(); + observers + .post_exec_child_all(state, input, &ExitKind::Crash) + .expect("Failed to run post_exec on observers"); + } - libc::_exit(128 + (_signal as i32)); + libc::_exit(128 + (_signal as i32)); + } } #[cfg(unix)] @@ -283,16 +285,18 @@ pub mod child_signal_handlers { E: HasObservers, E::Observers: ObserversTuple, { - if data.is_valid() { - let executor = data.executor_mut::(); - let mut observers = executor.observers_mut(); - let state = data.state_mut::(); - let input = data.take_current_input::(); - observers - .post_exec_child_all(state, input, &ExitKind::Timeout) - .expect("Failed to run post_exec on observers"); + unsafe { + if data.is_valid() { + let executor = data.executor_mut::(); + let mut observers = executor.observers_mut(); + let state = data.state_mut::(); + let input = data.take_current_input::(); + observers + .post_exec_child_all(state, input, &ExitKind::Timeout) + .expect("Failed to run post_exec on observers"); + } + libc::_exit(128 + (_signal as i32)); } - libc::_exit(128 + (_signal as i32)); } } @@ -303,7 +307,7 @@ mod tests { use serial_test::serial; use crate::{ - executors::{inprocess_fork::GenericInProcessForkExecutorInner, Executor, ExitKind}, + executors::{Executor, ExitKind, inprocess_fork::GenericInProcessForkExecutorInner}, inputs::NopInput, }; diff --git a/libafl/src/executors/inprocess_fork/stateful.rs b/libafl/src/executors/inprocess_fork/stateful.rs index 306d0caaec..55e311fbe8 100644 --- a/libafl/src/executors/inprocess_fork/stateful.rs +++ b/libafl/src/executors/inprocess_fork/stateful.rs @@ -9,18 +9,18 @@ use core::{ use libafl_bolts::{ shmem::ShMemProvider, - tuples::{tuple_list, RefIndexable}, + tuples::{RefIndexable, tuple_list}, }; -use nix::unistd::{fork, ForkResult}; +use nix::unistd::{ForkResult, fork}; use crate::{ + Error, executors::{ - hooks::ExecutorHooksTuple, inprocess_fork::GenericInProcessForkExecutorInner, Executor, - ExitKind, HasObservers, + Executor, ExitKind, HasObservers, hooks::ExecutorHooksTuple, + inprocess_fork::GenericInProcessForkExecutorInner, }, observers::ObserversTuple, state::HasExecutions, - Error, }; /// The `StatefulInProcessForkExecutor` with no user hooks diff --git a/libafl/src/executors/shadow.rs b/libafl/src/executors/shadow.rs index 4679b5625d..a0ce486e1a 100644 --- a/libafl/src/executors/shadow.rs +++ b/libafl/src/executors/shadow.rs @@ -10,9 +10,9 @@ use libafl_bolts::tuples::RefIndexable; use super::HasTimeout; use crate::{ + Error, executors::{Executor, ExitKind, HasObservers}, observers::ObserversTuple, - Error, }; /// A [`ShadowExecutor`] wraps an executor and a set of shadow observers diff --git a/libafl/src/executors/with_observers.rs b/libafl/src/executors/with_observers.rs index ecd6719d76..d4e7009154 100644 --- a/libafl/src/executors/with_observers.rs +++ b/libafl/src/executors/with_observers.rs @@ -5,9 +5,9 @@ use core::{fmt::Debug, marker::PhantomData}; use libafl_bolts::tuples::RefIndexable; use crate::{ + Error, executors::{Executor, ExitKind, HasObservers}, observers::ObserversTuple, - Error, }; /// A wrapper for any [`Executor`] to make it implement [`HasObservers`] using a given [`ObserversTuple`]. diff --git a/libafl/src/feedbacks/bool.rs b/libafl/src/feedbacks/bool.rs index 74a6ba577b..fc9335da95 100644 --- a/libafl/src/feedbacks/bool.rs +++ b/libafl/src/feedbacks/bool.rs @@ -3,14 +3,14 @@ use alloc::borrow::Cow; use libafl_bolts::{ - tuples::{Handle, MatchNameRef}, Error, Named, + tuples::{Handle, MatchNameRef}, }; use crate::{ + HasNamedMetadata, feedbacks::{Feedback, StateInitializer}, observers::{ObserversTuple, ValueObserver}, - HasNamedMetadata, }; /// This feedback returns `true` or `false` as the `is_interesting` value. diff --git a/libafl/src/feedbacks/capture_feedback.rs b/libafl/src/feedbacks/capture_feedback.rs index 26fa58f2c9..7d538c3b11 100644 --- a/libafl/src/feedbacks/capture_feedback.rs +++ b/libafl/src/feedbacks/capture_feedback.rs @@ -2,15 +2,15 @@ use std::{borrow::Cow, cell::RefCell, fmt::Debug, rc::Rc}; use libafl_bolts::{Error, Named}; -use serde::{de::DeserializeOwned, Serialize}; +use serde::{Serialize, de::DeserializeOwned}; use crate::{ + HasMetadata, corpus::Testcase, executors::ExitKind, feedbacks::{Feedback, StateInitializer}, stages::verify_timeouts::TimeoutsToVerify, state::HasCorpus, - HasMetadata, }; /// A Feedback that captures all timeouts and stores them in State for re-evaluation later. diff --git a/libafl/src/feedbacks/concolic.rs b/libafl/src/feedbacks/concolic.rs index 79b99ba99a..56b29e064b 100644 --- a/libafl/src/feedbacks/concolic.rs +++ b/libafl/src/feedbacks/concolic.rs @@ -8,15 +8,15 @@ use alloc::borrow::Cow; use core::fmt::Debug; use libafl_bolts::{ - tuples::{Handle, Handled, MatchName, MatchNameRef}, Named, + tuples::{Handle, Handled, MatchName, MatchNameRef}, }; use crate::{ + Error, HasMetadata, corpus::Testcase, feedbacks::{Feedback, StateInitializer}, observers::concolic::ConcolicObserver, - Error, HasMetadata, }; /// The concolic feedback. It is used to attach concolic tracing metadata to the testcase. diff --git a/libafl/src/feedbacks/custom_filename.rs b/libafl/src/feedbacks/custom_filename.rs index df20ad23d4..96cd72e4e0 100644 --- a/libafl/src/feedbacks/custom_filename.rs +++ b/libafl/src/feedbacks/custom_filename.rs @@ -5,9 +5,9 @@ use libafl_bolts::Named; use serde::{Deserialize, Serialize}; use crate::{ + Error, corpus::Testcase, feedbacks::{Feedback, FeedbackFactory, StateInitializer}, - Error, }; /// Type which can generate a custom filename for a given input/state pair diff --git a/libafl/src/feedbacks/differential.rs b/libafl/src/feedbacks/differential.rs index 90db0cdb07..f994e136dd 100644 --- a/libafl/src/feedbacks/differential.rs +++ b/libafl/src/feedbacks/differential.rs @@ -4,17 +4,17 @@ use alloc::borrow::Cow; use core::fmt::{self, Debug, Formatter}; use libafl_bolts::{ - tuples::{Handle, Handled, MatchName, MatchNameRef}, Named, + tuples::{Handle, Handled, MatchName, MatchNameRef}, }; use serde::{Deserialize, Serialize}; #[cfg(feature = "track_hit_feedbacks")] use crate::feedbacks::premature_last_result_err; use crate::{ + Error, executors::ExitKind, feedbacks::{Feedback, FeedbackFactory, StateInitializer}, - Error, }; /// The result of a differential test between two observers. @@ -179,12 +179,12 @@ where mod tests { use alloc::borrow::Cow; - use libafl_bolts::{tuples::tuple_list, Named}; + use libafl_bolts::{Named, tuples::tuple_list}; use crate::{ events::NopEventManager, executors::ExitKind, - feedbacks::{differential::DiffResult, DiffFeedback, Feedback}, + feedbacks::{DiffFeedback, Feedback, differential::DiffResult}, inputs::BytesInput, observers::Observer, state::NopState, diff --git a/libafl/src/feedbacks/list.rs b/libafl/src/feedbacks/list.rs index 6ca99d35da..f6d6f88e80 100644 --- a/libafl/src/feedbacks/list.rs +++ b/libafl/src/feedbacks/list.rs @@ -3,16 +3,16 @@ use core::{fmt::Debug, hash::Hash}; use hashbrown::HashSet; use libafl_bolts::{ - tuples::{Handle, Handled, MatchName, MatchNameRef}, Error, HasRefCnt, Named, + tuples::{Handle, Handled, MatchName, MatchNameRef}, }; -use serde::{de::DeserializeOwned, Deserialize, Serialize}; +use serde::{Deserialize, Serialize, de::DeserializeOwned}; use crate::{ + HasNamedMetadata, executors::ExitKind, feedbacks::{Feedback, StateInitializer}, observers::ListObserver, - HasNamedMetadata, }; /// The metadata to remember past observed value diff --git a/libafl/src/feedbacks/map.rs b/libafl/src/feedbacks/map.rs index 0509e7dc7c..e9e4c90232 100644 --- a/libafl/src/feedbacks/map.rs +++ b/libafl/src/feedbacks/map.rs @@ -12,22 +12,22 @@ use core::{ #[rustversion::nightly] use libafl_bolts::AsSlice; use libafl_bolts::{ - tuples::{Handle, Handled, MatchName, MatchNameRef}, AsIter, HasRefCnt, Named, + tuples::{Handle, Handled, MatchName, MatchNameRef}, }; use num_traits::PrimInt; -use serde::{de::DeserializeOwned, Deserialize, Serialize}; +use serde::{Deserialize, Serialize, de::DeserializeOwned}; #[cfg(feature = "track_hit_feedbacks")] use crate::feedbacks::premature_last_result_err; use crate::{ + Error, HasMetadata, HasNamedMetadata, corpus::Testcase, events::{Event, EventFirer}, executors::ExitKind, feedbacks::{Feedback, HasObserverHandle, StateInitializer}, monitors::stats::{AggregatorOps, UserStats, UserStatsValue}, observers::{CanTrack, MapObserver}, - Error, HasMetadata, HasNamedMetadata, }; /// A [`MapFeedback`] that implements the AFL algorithm using an [`OrReducer`] combining the bits for the history map and the bit from (`HitcountsMapObserver`)[`crate::observers::HitcountsMapObserver`]. @@ -103,11 +103,7 @@ where { #[inline] fn reduce(first: T, second: T) -> T { - if first > second { - first - } else { - second - } + if first > second { first } else { second } } } @@ -121,11 +117,7 @@ where { #[inline] fn reduce(first: T, second: T) -> T { - if first < second { - first - } else { - second - } + if first < second { first } else { second } } } diff --git a/libafl/src/feedbacks/mod.rs b/libafl/src/feedbacks/mod.rs index 9402f18f60..5c24d87856 100644 --- a/libafl/src/feedbacks/mod.rs +++ b/libafl/src/feedbacks/mod.rs @@ -12,8 +12,8 @@ use core::{fmt::Debug, marker::PhantomData}; pub use concolic::ConcolicFeedback; pub use differential::DiffFeedback; use libafl_bolts::{ - tuples::{Handle, Handled, MatchName, MatchNameRef}, Named, + tuples::{Handle, Handled, MatchName, MatchNameRef}, }; pub use list::*; pub use map::*; @@ -25,7 +25,7 @@ pub use new_hash_feedback::NewHashFeedback; pub use new_hash_feedback::NewHashFeedbackMetadata; use serde::{Deserialize, Serialize}; -use crate::{corpus::Testcase, executors::ExitKind, observers::TimeObserver, Error}; +use crate::{Error, corpus::Testcase, executors::ExitKind, observers::TimeObserver}; #[cfg(feature = "std")] pub mod capture_feedback; @@ -1016,11 +1016,7 @@ impl ConstFeedback { impl From for ConstFeedback { fn from(val: bool) -> Self { - if val { - Self::True - } else { - Self::False - } + if val { Self::True } else { Self::False } } } diff --git a/libafl/src/feedbacks/nautilus.rs b/libafl/src/feedbacks/nautilus.rs index f5754122a3..cea4f282f5 100644 --- a/libafl/src/feedbacks/nautilus.rs +++ b/libafl/src/feedbacks/nautilus.rs @@ -7,6 +7,7 @@ use libafl_bolts::Named; use serde::{Deserialize, Serialize}; use crate::{ + Error, HasMetadata, common::nautilus::grammartec::{chunkstore::ChunkStore, context::Context}, corpus::{Corpus, Testcase}, executors::ExitKind, @@ -14,7 +15,6 @@ use crate::{ generators::NautilusContext, inputs::NautilusInput, state::HasCorpus, - Error, HasMetadata, }; /// Metadata for Nautilus grammar mutator chunks diff --git a/libafl/src/feedbacks/new_hash_feedback.rs b/libafl/src/feedbacks/new_hash_feedback.rs index cb2039979c..fa91c50d7a 100644 --- a/libafl/src/feedbacks/new_hash_feedback.rs +++ b/libafl/src/feedbacks/new_hash_feedback.rs @@ -5,18 +5,18 @@ use std::fmt::Debug; use hashbrown::HashSet; use libafl_bolts::{ - tuples::{Handle, Handled, MatchName, MatchNameRef}, Named, + tuples::{Handle, Handled, MatchName, MatchNameRef}, }; use serde::{Deserialize, Serialize}; #[cfg(feature = "track_hit_feedbacks")] use crate::feedbacks::premature_last_result_err; use crate::{ + Error, HasNamedMetadata, executors::ExitKind, feedbacks::{Feedback, HasObserverHandle, StateInitializer}, observers::ObserverWithHashField, - Error, HasNamedMetadata, }; /// The prefix of the metadata names diff --git a/libafl/src/feedbacks/stdio.rs b/libafl/src/feedbacks/stdio.rs index 3f4998de8e..4da5765ef5 100644 --- a/libafl/src/feedbacks/stdio.rs +++ b/libafl/src/feedbacks/stdio.rs @@ -3,17 +3,16 @@ use alloc::{borrow::Cow, string::String}; use libafl_bolts::{ - impl_serdeany, + Named, impl_serdeany, tuples::{Handle, Handled, MatchName, MatchNameRef}, - Named, }; use serde::{Deserialize, Serialize}; use crate::{ + Error, HasMetadata, corpus::Testcase, feedbacks::{Feedback, StateInitializer}, observers::{StdErrObserver, StdOutObserver}, - Error, HasMetadata, }; /// Metadata for [`StdOutToMetadataFeedback`]. diff --git a/libafl/src/feedbacks/transferred.rs b/libafl/src/feedbacks/transferred.rs index 83ae83da24..3e4fceffed 100644 --- a/libafl/src/feedbacks/transferred.rs +++ b/libafl/src/feedbacks/transferred.rs @@ -3,15 +3,15 @@ use alloc::borrow::Cow; -use libafl_bolts::{impl_serdeany, Error, Named}; +use libafl_bolts::{Error, Named, impl_serdeany}; use serde::{Deserialize, Serialize}; #[cfg(feature = "track_hit_feedbacks")] use crate::feedbacks::premature_last_result_err; use crate::{ + HasMetadata, executors::ExitKind, feedbacks::{Feedback, StateInitializer}, - HasMetadata, }; /// Constant name of the [`TransferringMetadata`]. diff --git a/libafl/src/feedbacks/value_bloom.rs b/libafl/src/feedbacks/value_bloom.rs index 7f70112284..9c87cd24cc 100644 --- a/libafl/src/feedbacks/value_bloom.rs +++ b/libafl/src/feedbacks/value_bloom.rs @@ -5,17 +5,16 @@ use core::hash::Hash; use fastbloom::BloomFilter; use libafl_bolts::{ - impl_serdeany, + Error, Named, impl_serdeany, tuples::{Handle, MatchNameRef}, - Error, Named, }; use serde::{Deserialize, Serialize}; use crate::{ + HasNamedMetadata, executors::ExitKind, feedbacks::{Feedback, StateInitializer}, observers::{ObserversTuple, ValueObserver}, - HasNamedMetadata, }; impl_serdeany!(ValueBloomFeedbackMetadata); diff --git a/libafl/src/fuzzer/mod.rs b/libafl/src/fuzzer/mod.rs index 2c5d700273..6b84208c26 100644 --- a/libafl/src/fuzzer/mod.rs +++ b/libafl/src/fuzzer/mod.rs @@ -8,11 +8,12 @@ use std::hash::Hash; #[cfg(feature = "std")] use fastbloom::BloomFilter; use libafl_bolts::{current_time, tuples::MatchName}; -use serde::{de::DeserializeOwned, Serialize}; +use serde::{Serialize, de::DeserializeOwned}; #[cfg(feature = "introspection")] use crate::monitors::stats::PerfFeature; use crate::{ + Error, HasMetadata, corpus::{Corpus, CorpusId, HasCurrentCorpusId, HasTestcase, Testcase}, events::{ CanSerializeObserver, Event, EventConfig, EventFirer, EventReceiver, ProgressReporter, @@ -30,7 +31,6 @@ use crate::{ HasCorpus, HasCurrentStageId, HasCurrentTestcase, HasExecutions, HasImported, HasLastFoundTime, HasLastReportTime, HasSolutions, MaybeHasClientPerfMonitor, Stoppable, }, - Error, HasMetadata, }; /// Send a monitor update all 15 (or more) seconds @@ -1129,24 +1129,32 @@ mod tests { InProcessExecutor::new(&mut harness, (), &mut fuzzer, &mut state, &mut manager) .unwrap(); let input = BytesInput::new(vec![1, 2, 3]); - assert!(fuzzer - .evaluate_input(&mut state, &mut executor, &mut manager, &input) - .is_ok()); + assert!( + fuzzer + .evaluate_input(&mut state, &mut executor, &mut manager, &input) + .is_ok() + ); assert_eq!(1, *execution_count.borrow()); // evaluate_input does not add it to the filter - assert!(fuzzer - .evaluate_filtered(&mut state, &mut executor, &mut manager, &input) - .is_ok()); + assert!( + fuzzer + .evaluate_filtered(&mut state, &mut executor, &mut manager, &input) + .is_ok() + ); assert_eq!(2, *execution_count.borrow()); // at to the filter - assert!(fuzzer - .evaluate_filtered(&mut state, &mut executor, &mut manager, &input) - .is_ok()); + assert!( + fuzzer + .evaluate_filtered(&mut state, &mut executor, &mut manager, &input) + .is_ok() + ); assert_eq!(2, *execution_count.borrow()); // the harness is not called - assert!(fuzzer - .evaluate_input(&mut state, &mut executor, &mut manager, &input) - .is_ok()); + assert!( + fuzzer + .evaluate_input(&mut state, &mut executor, &mut manager, &input) + .is_ok() + ); assert_eq!(3, *execution_count.borrow()); // evaluate_input ignores filters } } diff --git a/libafl/src/generators/gramatron.rs b/libafl/src/generators/gramatron.rs index f8677e0fcf..b3d3dcfe85 100644 --- a/libafl/src/generators/gramatron.rs +++ b/libafl/src/generators/gramatron.rs @@ -6,10 +6,10 @@ use libafl_bolts::rands::Rand; use serde::{Deserialize, Serialize}; use crate::{ + Error, generators::Generator, inputs::{GramatronInput, Terminal}, state::HasRand, - Error, }; /// A trigger diff --git a/libafl/src/generators/mod.rs b/libafl/src/generators/mod.rs index ce0ce4607f..fded881958 100644 --- a/libafl/src/generators/mod.rs +++ b/libafl/src/generators/mod.rs @@ -5,7 +5,7 @@ use core::{marker::PhantomData, num::NonZeroUsize}; use libafl_bolts::rands::Rand; -use crate::{inputs::bytes::BytesInput, nonzero, state::HasRand, Error}; +use crate::{Error, inputs::bytes::BytesInput, nonzero, state::HasRand}; pub mod gramatron; use core::cmp::max; @@ -44,16 +44,16 @@ where /// An [`Iterator`] built from a [`Generator`]. #[derive(Debug)] pub struct GeneratorIter<'a, I, S, G> { - gen: G, + generator: G, state: &'a mut S, phantom: PhantomData, } impl<'a, I, S, G> GeneratorIter<'a, I, S, G> { /// Create a new [`GeneratorIter`] - pub fn new(gen: G, state: &'a mut S) -> Self { + pub fn new(generator: G, state: &'a mut S) -> Self { Self { - gen, + generator, state, phantom: PhantomData, } @@ -67,7 +67,7 @@ where type Item = I; fn next(&mut self) -> Option { - self.gen.generate(self.state).ok() + self.generator.generate(self.state).ok() } } diff --git a/libafl/src/generators/nautilus.rs b/libafl/src/generators/nautilus.rs index 1b4b870996..2691761d59 100644 --- a/libafl/src/generators/nautilus.rs +++ b/libafl/src/generators/nautilus.rs @@ -10,9 +10,8 @@ use libafl_bolts::rands::Rand; pub use crate::common::nautilus::grammartec::newtypes::NTermId; use crate::{ - common::nautilus::grammartec::context::Context, generators::Generator, + Error, common::nautilus::grammartec::context::Context, generators::Generator, inputs::nautilus::NautilusInput, nautilus::grammartec::python_grammar_loader, state::HasRand, - Error, }; /// The nautilus context for a generator diff --git a/libafl/src/inputs/bytes.rs b/libafl/src/inputs/bytes.rs index 8839a79de6..c352c9305d 100644 --- a/libafl/src/inputs/bytes.rs +++ b/libafl/src/inputs/bytes.rs @@ -8,7 +8,7 @@ use alloc::{ }; use core::cell::RefCell; -use libafl_bolts::{ownedref::OwnedSlice, HasLen}; +use libafl_bolts::{HasLen, ownedref::OwnedSlice}; use super::ValueInput; use crate::inputs::{HasMutatorBytes, HasTargetBytes, ResizableMutator}; diff --git a/libafl/src/inputs/bytessub.rs b/libafl/src/inputs/bytessub.rs index fb4a97bc02..eabca1cd53 100644 --- a/libafl/src/inputs/bytessub.rs +++ b/libafl/src/inputs/bytessub.rs @@ -7,8 +7,8 @@ use core::{ }; use libafl_bolts::{ - subrange::{end_index, start_index, sub_range}, HasLen, + subrange::{end_index, start_index, sub_range}, }; use crate::inputs::{HasMutatorBytes, ResizableMutator}; @@ -24,7 +24,7 @@ use crate::inputs::{HasMutatorBytes, ResizableMutator}; /// # use alloc::vec::Vec; /// # /// # #[cfg(not(feature = "std"))] -/// # #[no_mangle] +/// # #[unsafe(no_mangle)] /// # pub extern "C" fn external_current_millis() -> u64 { 0 } /// /// let mut bytes_input = BytesInput::new(vec![1, 2, 3]); @@ -49,7 +49,7 @@ use crate::inputs::{HasMutatorBytes, ResizableMutator}; /// # use alloc::vec::Vec; /// # /// # #[cfg(not(feature = "std"))] -/// # #[no_mangle] +/// # #[unsafe(no_mangle)] /// # pub extern "C" fn external_current_millis() -> u64 { 0 } /// /// let mut bytes_input = BytesInput::new(vec![1, 2, 3, 4, 5]); @@ -215,7 +215,7 @@ mod tests { use crate::{ inputs::{BytesInput, HasMutatorBytes, NopInput, ResizableMutator}, - mutators::{havoc_mutations_no_crossover, MutatorsTuple}, + mutators::{MutatorsTuple, havoc_mutations_no_crossover}, state::NopState, }; diff --git a/libafl/src/inputs/generalized.rs b/libafl/src/inputs/generalized.rs index 56f6d4ec09..02b9d09bd2 100644 --- a/libafl/src/inputs/generalized.rs +++ b/libafl/src/inputs/generalized.rs @@ -6,10 +6,10 @@ use libafl_bolts::impl_serdeany; use serde::{Deserialize, Serialize}; use crate::{ + Error, HasMetadata, corpus::Testcase, inputs::BytesInput, stages::mutational::{MutatedTransform, MutatedTransformPost}, - Error, HasMetadata, }; /// An item of the generalized input diff --git a/libafl/src/inputs/list.rs b/libafl/src/inputs/list.rs index 38a51996c7..6c25f6afcd 100644 --- a/libafl/src/inputs/list.rs +++ b/libafl/src/inputs/list.rs @@ -13,9 +13,9 @@ use core::num::NonZero; use arrayvec::ArrayVec; use libafl_bolts::{ + Error, Named, rands::Rand as _, tuples::{Map, MappingFunctor}, - Error, Named, }; use serde::{Deserialize, Serialize}; @@ -326,7 +326,7 @@ mod tests { use super::ListInput; use crate::{ inputs::ValueInput, - mutators::{numeric::IncMutator, MutationResult, MutatorsTuple as _}, + mutators::{MutationResult, MutatorsTuple as _, numeric::IncMutator}, state::NopState, }; diff --git a/libafl/src/inputs/mod.rs b/libafl/src/inputs/mod.rs index a349649b74..67626ca7fc 100644 --- a/libafl/src/inputs/mod.rs +++ b/libafl/src/inputs/mod.rs @@ -48,10 +48,9 @@ use std::{fs::File, io::Read, path::Path}; #[cfg(feature = "std")] use libafl_bolts::fs::write_file_atomic; use libafl_bolts::{ - generic_hash_std, + Error, HasLen, generic_hash_std, ownedref::{OwnedMutSlice, OwnedSlice}, subrange::{SubRangeMutSlice, SubRangeSlice}, - Error, HasLen, }; #[cfg(feature = "nautilus")] pub use nautilus::*; diff --git a/libafl/src/inputs/multi.rs b/libafl/src/inputs/multi.rs index 89ce8efbd5..db1f2c2c5e 100644 --- a/libafl/src/inputs/multi.rs +++ b/libafl/src/inputs/multi.rs @@ -3,7 +3,7 @@ use alloc::{fmt::Debug, string::String, vec::Vec}; use core::hash::Hash; -use serde::{de::DeserializeOwned, Serialize}; +use serde::{Serialize, de::DeserializeOwned}; use crate::{ corpus::CorpusId, diff --git a/libafl/src/inputs/nautilus.rs b/libafl/src/inputs/nautilus.rs index 17965b9123..f120b9e797 100644 --- a/libafl/src/inputs/nautilus.rs +++ b/libafl/src/inputs/nautilus.rs @@ -3,11 +3,12 @@ use alloc::{rc::Rc, vec::Vec}; use core::cell::RefCell; use std::hash::{Hash, Hasher}; -use libafl_bolts::{ownedref::OwnedSlice, HasLen}; +use libafl_bolts::{HasLen, ownedref::OwnedSlice}; use serde::{Deserialize, Serialize}; use super::TargetBytesConverter; use crate::{ + Error, common::nautilus::grammartec::{ newtypes::NodeId, rule::RuleIdOrCustom, @@ -15,7 +16,6 @@ use crate::{ }, generators::nautilus::NautilusContext, inputs::{BytesInput, Input, InputConverter}, - Error, }; /// An [`Input`] implementation for `Nautilus` grammar. diff --git a/libafl/src/inputs/value.rs b/libafl/src/inputs/value.rs index 68ce3645fb..0a1e255e68 100644 --- a/libafl/src/inputs/value.rs +++ b/libafl/src/inputs/value.rs @@ -8,7 +8,7 @@ use libafl_bolts::rands::Rand; use serde::{Deserialize, Serialize}; #[cfg(feature = "std")] use { - libafl_bolts::{fs::write_file_atomic, Error}, + libafl_bolts::{Error, fs::write_file_atomic}, std::{fs::File, io::Read, path::Path}, }; diff --git a/libafl/src/lib.rs b/libafl/src/lib.rs index aaedf63ec7..a6082407bd 100644 --- a/libafl/src/lib.rs +++ b/libafl/src/lib.rs @@ -81,7 +81,7 @@ pub mod stages; pub mod state; pub use fuzzer::*; -pub use libafl_bolts::{nonzero, Error}; +pub use libafl_bolts::{Error, nonzero}; /// The purpose of this module is to alleviate imports of many components by adding a glob import. #[cfg(feature = "prelude")] @@ -96,7 +96,7 @@ pub mod prelude { #[cfg(all(any(doctest, test), not(feature = "std")))] /// Provide custom time in `no_std` tests. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn external_current_millis() -> u64 { // TODO: use "real" time here 1000 @@ -116,6 +116,7 @@ mod tests { #[cfg(miri)] use crate::stages::ExecutionCountRestartHelperMetadata; use crate::{ + StdFuzzer, corpus::{Corpus, InMemoryCorpus, Testcase}, events::NopEventManager, executors::{ExitKind, InProcessExecutor}, @@ -123,11 +124,10 @@ mod tests { fuzzer::Fuzzer, inputs::BytesInput, monitors::SimpleMonitor, - mutators::{mutations::BitFlipMutator, StdScheduledMutator}, + mutators::{StdScheduledMutator, mutations::BitFlipMutator}, schedulers::RandScheduler, stages::StdMutationalStage, state::{HasCorpus, StdState}, - StdFuzzer, }; #[test] diff --git a/libafl/src/monitors/disk.rs b/libafl/src/monitors/disk.rs index 7a14959680..cbb6be4227 100644 --- a/libafl/src/monitors/disk.rs +++ b/libafl/src/monitors/disk.rs @@ -8,10 +8,10 @@ use std::{ path::PathBuf, }; -use libafl_bolts::{current_time, ClientId}; +use libafl_bolts::{ClientId, current_time}; use serde_json::json; -use crate::monitors::{stats::ClientStatsManager, Monitor}; +use crate::monitors::{Monitor, stats::ClientStatsManager}; /// Wrap a monitor and log the current state of the monitor into a Toml file. #[derive(Debug, Clone)] diff --git a/libafl/src/monitors/disk_aggregate.rs b/libafl/src/monitors/disk_aggregate.rs index d315a08bf8..4d5a92628b 100644 --- a/libafl/src/monitors/disk_aggregate.rs +++ b/libafl/src/monitors/disk_aggregate.rs @@ -6,10 +6,10 @@ use core::{ }; use std::{fs::OpenOptions, io::Write, path::PathBuf}; -use libafl_bolts::{current_time, ClientId}; +use libafl_bolts::{ClientId, current_time}; use serde_json::json; -use crate::monitors::{stats::ClientStatsManager, Monitor}; +use crate::monitors::{Monitor, stats::ClientStatsManager}; /// A monitor that logs aggregated stats to a JSON file. #[derive(Clone)] diff --git a/libafl/src/monitors/logics.rs b/libafl/src/monitors/logics.rs index fefd254a39..86b785c413 100644 --- a/libafl/src/monitors/logics.rs +++ b/libafl/src/monitors/logics.rs @@ -2,7 +2,7 @@ use libafl_bolts::ClientId; -use crate::monitors::{stats::ClientStatsManager, Monitor}; +use crate::monitors::{Monitor, stats::ClientStatsManager}; /// The wrapped monitor will keep displaying until the closure evaluates to false #[derive(Debug)] diff --git a/libafl/src/monitors/mod.rs b/libafl/src/monitors/mod.rs index 226920432b..ae38aeece9 100644 --- a/libafl/src/monitors/mod.rs +++ b/libafl/src/monitors/mod.rs @@ -297,7 +297,7 @@ mod test { use libafl_bolts::ClientId; use tuple_list::tuple_list; - use super::{stats::ClientStatsManager, Monitor, NopMonitor, SimpleMonitor}; + use super::{Monitor, NopMonitor, SimpleMonitor, stats::ClientStatsManager}; #[test] fn test_monitor_tuple_list() { diff --git a/libafl/src/monitors/multi.rs b/libafl/src/monitors/multi.rs index 906db2ab33..f57e2781a3 100644 --- a/libafl/src/monitors/multi.rs +++ b/libafl/src/monitors/multi.rs @@ -6,9 +6,9 @@ use core::{ time::Duration, }; -use libafl_bolts::{current_time, ClientId}; +use libafl_bolts::{ClientId, current_time}; -use crate::monitors::{stats::ClientStatsManager, Monitor}; +use crate::monitors::{Monitor, stats::ClientStatsManager}; /// Tracking monitor during fuzzing and display both per-client and cumulative info. #[derive(Clone)] diff --git a/libafl/src/monitors/prometheus.rs b/libafl/src/monitors/prometheus.rs index 072158770e..ebecb50122 100644 --- a/libafl/src/monitors/prometheus.rs +++ b/libafl/src/monitors/prometheus.rs @@ -31,16 +31,16 @@ use alloc::{borrow::Cow, fmt::Debug, string::String}; use core::{fmt, fmt::Write, time::Duration}; use std::{ string::ToString, - sync::{atomic::AtomicU64, Arc}, + sync::{Arc, atomic::AtomicU64}, thread, }; // using thread in order to start the HTTP server in a separate thread use futures::executor::block_on; -use libafl_bolts::{current_time, ClientId}; +use libafl_bolts::{ClientId, current_time}; // using the official rust client library for Prometheus: https://github.com/prometheus/client_rust use prometheus_client::{ - encoding::{text::encode, EncodeLabelSet}, + encoding::{EncodeLabelSet, text::encode}, metrics::{family::Family, gauge::Gauge}, registry::Registry, }; @@ -48,8 +48,8 @@ use prometheus_client::{ use tide::Request; use crate::monitors::{ - stats::{manager::ClientStatsManager, user_stats::UserStatsValue}, Monitor, + stats::{manager::ClientStatsManager, user_stats::UserStatsValue}, }; /// Prometheus metrics for global and each client. diff --git a/libafl/src/monitors/stats/manager.rs b/libafl/src/monitors/stats/manager.rs index d5f99284cd..4ea640c525 100644 --- a/libafl/src/monitors/stats/manager.rs +++ b/libafl/src/monitors/stats/manager.rs @@ -6,15 +6,15 @@ use alloc::{borrow::Cow, string::String, vec::Vec}; use core::time::Duration; use hashbrown::HashMap; -use libafl_bolts::{current_time, format_duration_hms, ClientId}; +use libafl_bolts::{ClientId, current_time, format_duration_hms}; #[cfg(feature = "std")] use serde_json::Value; -use super::{user_stats::UserStatsValue, ClientStats, EdgeCoverage, ProcessTiming}; +use super::{ClientStats, EdgeCoverage, ProcessTiming, user_stats::UserStatsValue}; #[cfg(feature = "std")] use super::{ - user_stats::{AggregatorOps, UserStats}, ItemGeometry, + user_stats::{AggregatorOps, UserStats}, }; /// Manager of all client's statistics diff --git a/libafl/src/monitors/statsd.rs b/libafl/src/monitors/statsd.rs index 5a1fc6fd73..9e474dc456 100644 --- a/libafl/src/monitors/statsd.rs +++ b/libafl/src/monitors/statsd.rs @@ -17,8 +17,8 @@ use cadence::{BufferedUdpMetricSink, Gauged, QueuingMetricSink, StatsdClient}; use libafl_bolts::ClientId; use super::{ - stats::{manager::GlobalStats, ClientStatsManager, EdgeCoverage, ItemGeometry}, Monitor, + stats::{ClientStatsManager, EdgeCoverage, ItemGeometry, manager::GlobalStats}, }; const METRIC_PREFIX: &str = "fuzzing"; diff --git a/libafl/src/monitors/tui/mod.rs b/libafl/src/monitors/tui/mod.rs index ead6722bf5..f251056ef2 100644 --- a/libafl/src/monitors/tui/mod.rs +++ b/libafl/src/monitors/tui/mod.rs @@ -19,21 +19,21 @@ use crossterm::{ cursor::{EnableBlinking, Show}, event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode}, execute, - terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, + terminal::{EnterAlternateScreen, LeaveAlternateScreen, disable_raw_mode, enable_raw_mode}, }; use hashbrown::HashMap; -use libafl_bolts::{current_time, format_duration_hms, ClientId}; -use ratatui::{backend::CrosstermBackend, Terminal}; +use libafl_bolts::{ClientId, current_time, format_duration_hms}; +use ratatui::{Terminal, backend::CrosstermBackend}; use typed_builder::TypedBuilder; #[cfg(feature = "introspection")] use crate::monitors::stats::perf_stats::{ClientPerfStats, PerfFeature}; use crate::monitors::{ - stats::{ - manager::ClientStatsManager, user_stats::UserStats, ClientStats, EdgeCoverage, - ItemGeometry, ProcessTiming, - }, Monitor, + stats::{ + ClientStats, EdgeCoverage, ItemGeometry, ProcessTiming, manager::ClientStatsManager, + user_stats::UserStats, + }, }; #[expect(missing_docs)] @@ -568,7 +568,9 @@ fn run_tui_thread( )?; terminal.show_cursor()?; - println!("\nPress Control-C to stop the fuzzers, otherwise press Enter to resume the visualization\n"); + println!( + "\nPress Control-C to stop the fuzzers, otherwise press Enter to resume the visualization\n" + ); let mut line = String::new(); io::stdin().lock().read_line(&mut line)?; diff --git a/libafl/src/monitors/tui/ui.rs b/libafl/src/monitors/tui/ui.rs index 2e5f71ef99..b7ba91b8e7 100644 --- a/libafl/src/monitors/tui/ui.rs +++ b/libafl/src/monitors/tui/ui.rs @@ -6,6 +6,7 @@ use std::{ }; use ratatui::{ + Frame, layout::{Alignment, Constraint, Direction, Layout, Rect}, style::{Color, Modifier, Style}, symbols, @@ -13,12 +14,11 @@ use ratatui::{ widgets::{ Axis, Block, Borders, Cell, Chart, Dataset, List, ListItem, Paragraph, Row, Table, Tabs, }, - Frame, }; use super::{ - current_time, format_duration_hms, Duration, ItemGeometry, ProcessTiming, String, TimedStats, - TuiContext, + Duration, ItemGeometry, ProcessTiming, String, TimedStats, TuiContext, current_time, + format_duration_hms, }; #[derive(Default, Debug)] @@ -368,19 +368,21 @@ impl TuiUi { //log::trace!("max_x: {}, len: {}", max_x, self.graph_data.len()); - let datasets = vec![Dataset::default() - //.name("data") - .marker(if self.enhanced_graphics { - symbols::Marker::Braille - } else { - symbols::Marker::Dot - }) - .style( - Style::default() - .fg(Color::LightYellow) - .add_modifier(Modifier::BOLD), - ) - .data(&self.graph_data)]; + let datasets = vec![ + Dataset::default() + //.name("data") + .marker(if self.enhanced_graphics { + symbols::Marker::Braille + } else { + symbols::Marker::Dot + }) + .style( + Style::default() + .fg(Color::LightYellow) + .add_modifier(Modifier::BOLD), + ) + .data(&self.graph_data), + ]; let chart = Chart::new(datasets) .block( Block::default() diff --git a/libafl/src/mutators/encoded_mutations.rs b/libafl/src/mutators/encoded_mutations.rs index b3410f01bc..a3a02c9657 100644 --- a/libafl/src/mutators/encoded_mutations.rs +++ b/libafl/src/mutators/encoded_mutations.rs @@ -11,15 +11,15 @@ use libafl_bolts::{ }; use crate::{ + Error, corpus::Corpus, inputs::EncodedInput, mutators::{ - mutations::{buffer_copy, buffer_self_copy, ARITH_MAX}, MutationResult, Mutator, Named, + mutations::{ARITH_MAX, buffer_copy, buffer_self_copy}, }, nonzero, random_corpus_id_with_disabled, state::{HasCorpus, HasMaxSize, HasRand}, - Error, }; /// Set a code in the input as a random value diff --git a/libafl/src/mutators/gramatron.rs b/libafl/src/mutators/gramatron.rs index 26c77144dd..58412723fa 100644 --- a/libafl/src/mutators/gramatron.rs +++ b/libafl/src/mutators/gramatron.rs @@ -6,19 +6,19 @@ use core::{cmp::max, num::NonZero}; use hashbrown::HashMap; use libafl_bolts::{ - rands::{choose, Rand}, Named, + rands::{Rand, choose}, }; use serde::{Deserialize, Serialize}; use crate::{ + Error, HasMetadata, corpus::Corpus, generators::GramatronGenerator, inputs::{GramatronInput, Terminal}, mutators::{MutationResult, Mutator}, nonzero, random_corpus_id, state::{HasCorpus, HasRand}, - Error, HasMetadata, }; const RECUR_THRESHOLD: usize = 5; @@ -201,15 +201,18 @@ where self.states.clear(); for i in 0..input.terminals().len() { let s = input.terminals()[i].state; - if let Some(entry) = self.counters.get_mut(&s) { - if entry.0 == 1 { - // Keep track only of states with more than one node - self.states.push(s); + match self.counters.get_mut(&s) { + Some(entry) => { + if entry.0 == 1 { + // Keep track only of states with more than one node + self.states.push(s); + } + entry.0 += 1; + entry.2 = max(entry.2, i); + } + _ => { + self.counters.insert(s, (1, i, i)); } - entry.0 += 1; - entry.2 = max(entry.2, i); - } else { - self.counters.insert(s, (1, i, i)); } } diff --git a/libafl/src/mutators/grimoire.rs b/libafl/src/mutators/grimoire.rs index b82e5356e8..0ccc31395b 100644 --- a/libafl/src/mutators/grimoire.rs +++ b/libafl/src/mutators/grimoire.rs @@ -9,17 +9,17 @@ use core::{ }; use libafl_bolts::{ - rands::{choose, fast_bound, Rand}, Named, + rands::{Rand, choose, fast_bound}, }; use crate::{ + Error, HasMetadata, corpus::Corpus, inputs::{GeneralizedInputMetadata, GeneralizedItem}, - mutators::{token_mutations::Tokens, MutationResult, Mutator}, + mutators::{MutationResult, Mutator, token_mutations::Tokens}, random_corpus_id, state::{HasCorpus, HasRand}, - Error, HasMetadata, }; const RECURSIVE_REPLACEMENT_DEPTH: [usize; 6] = [2, 4, 8, 16, 32, 64]; @@ -46,9 +46,9 @@ where .metadata_map() .get::() { - let gen = other.generalized(); + let generalized = other.generalized(); - for (i, _) in gen + for (i, _) in generalized .iter() .enumerate() .filter(|&(_, x)| *x == GeneralizedItem::Gap) @@ -64,7 +64,7 @@ where if items.last() == Some(&GeneralizedItem::Gap) { min_idx += 1; } - items.extend_from_slice(&gen[min_idx..=max_idx]); + items.extend_from_slice(&generalized[min_idx..=max_idx]); debug_assert!(items.first() == Some(&GeneralizedItem::Gap)); debug_assert!(items.last() == Some(&GeneralizedItem::Gap)); @@ -93,25 +93,27 @@ where } let other_testcase = state.corpus().get(id)?.borrow(); - if let Some(other) = other_testcase + match other_testcase .metadata_map() .get::() { - let gen = other.generalized(); + Some(other) => { + let generalized = other.generalized(); - if items.last() == Some(&GeneralizedItem::Gap) && gen.first() == Some(&GeneralizedItem::Gap) - { - items.extend_from_slice(&gen[1..]); - } else { - items.extend_from_slice(gen); + if items.last() == Some(&GeneralizedItem::Gap) + && generalized.first() == Some(&GeneralizedItem::Gap) + { + items.extend_from_slice(&generalized[1..]); + } else { + items.extend_from_slice(generalized); + } + + debug_assert!(items.first() == Some(&GeneralizedItem::Gap)); + debug_assert!(items.last() == Some(&GeneralizedItem::Gap)); + + Ok(MutationResult::Mutated) } - - debug_assert!(items.first() == Some(&GeneralizedItem::Gap)); - debug_assert!(items.last() == Some(&GeneralizedItem::Gap)); - - Ok(MutationResult::Mutated) - } else { - Ok(MutationResult::Skipped) + _ => Ok(MutationResult::Skipped), } } @@ -185,9 +187,9 @@ where break; } - let gen = generalised_meta.generalized_mut(); + let generalized = generalised_meta.generalized_mut(); - for (i, _) in gen + for (i, _) in generalized .iter() .enumerate() .filter(|&(_, x)| *x == GeneralizedItem::Gap) @@ -200,16 +202,16 @@ where let selected = *state.rand_mut().choose(&self.gap_indices).unwrap(); self.gap_indices.clear(); - self.scratch.extend_from_slice(&gen[selected + 1..]); - gen.truncate(selected); + self.scratch.extend_from_slice(&generalized[selected + 1..]); + generalized.truncate(selected); - if extend_with_random_generalized(state, gen, &mut self.gap_indices)? + if extend_with_random_generalized(state, generalized, &mut self.gap_indices)? == MutationResult::Skipped { - gen.push(GeneralizedItem::Gap); + generalized.push(GeneralizedItem::Gap); } - gen.extend_from_slice(&self.scratch); + generalized.extend_from_slice(&self.scratch); self.scratch.clear(); mutated = MutationResult::Mutated; @@ -266,8 +268,8 @@ where } }; - let gen = generalised_meta.generalized_mut(); - let Some(_) = NonZero::new(gen.len()) else { + let generalized = generalised_meta.generalized_mut(); + let Some(_) = NonZero::new(generalized.len()) else { return Err(Error::illegal_state("No generalized metadata found.")); }; @@ -289,10 +291,10 @@ where // # Safety // gen.len() is positive. let rand_idx = fast_bound(rand_idx, unsafe { - NonZero::new(gen.len()).unwrap_unchecked() + NonZero::new(generalized.len()).unwrap_unchecked() }); - 'first: for item in &mut gen[..rand_idx] { + 'first: for item in &mut generalized[..rand_idx] { if let GeneralizedItem::Bytes(bytes) = item { let mut i = 0; while bytes @@ -315,7 +317,7 @@ where } } if mutated == MutationResult::Skipped || !stop_at_first { - 'second: for item in &mut gen[rand_idx..] { + 'second: for item in &mut generalized[rand_idx..] { if let GeneralizedItem::Bytes(bytes) = item { let mut i = 0; while bytes @@ -376,9 +378,9 @@ where state: &mut S, generalised_meta: &mut GeneralizedInputMetadata, ) -> Result { - let gen = generalised_meta.generalized_mut(); + let generalized = generalised_meta.generalized_mut(); - for i in gen + for i in generalized .iter() .enumerate() .filter_map(|(i, x)| (*x == GeneralizedItem::Gap).then_some(i)) @@ -402,7 +404,7 @@ where let result = if min_idx == max_idx { MutationResult::Skipped } else { - gen.drain(min_idx..max_idx); + generalized.drain(min_idx..max_idx); MutationResult::Mutated }; diff --git a/libafl/src/mutators/hash.rs b/libafl/src/mutators/hash.rs index 8b231b7d75..5faa20b1a4 100644 --- a/libafl/src/mutators/hash.rs +++ b/libafl/src/mutators/hash.rs @@ -2,7 +2,7 @@ //! by hashing pre- and post-mutation use std::{borrow::Cow, hash::Hash}; -use libafl_bolts::{generic_hash_std, Error, Named}; +use libafl_bolts::{Error, Named, generic_hash_std}; use super::{MutationResult, Mutator}; diff --git a/libafl/src/mutators/havoc_mutations.rs b/libafl/src/mutators/havoc_mutations.rs index 38df927083..f03b5e903b 100644 --- a/libafl/src/mutators/havoc_mutations.rs +++ b/libafl/src/mutators/havoc_mutations.rs @@ -2,7 +2,7 @@ use libafl_bolts::{ map_tuple_list_type, merge_tuple_list_type, - tuples::{tuple_list, tuple_list_type, Map, Merge}, + tuples::{Map, Merge, tuple_list, tuple_list_type}, }; use crate::mutators::{ diff --git a/libafl/src/mutators/list.rs b/libafl/src/mutators/list.rs index 4c1e122846..f84e5d7144 100644 --- a/libafl/src/mutators/list.rs +++ b/libafl/src/mutators/list.rs @@ -3,13 +3,13 @@ use alloc::borrow::Cow; use core::num::NonZero; -use libafl_bolts::{rands::Rand, Error, Named}; +use libafl_bolts::{Error, Named, rands::Rand}; use tuple_list::{tuple_list, tuple_list_type}; use crate::{ corpus::Corpus, generators::Generator, - inputs::{multi::MultipartInput, Input, ListInput}, + inputs::{Input, ListInput, multi::MultipartInput}, mutators::{MutationResult, Mutator}, random_corpus_id, state::{HasCorpus, HasMaxSize, HasRand}, diff --git a/libafl/src/mutators/mapping.rs b/libafl/src/mutators/mapping.rs index 2d5a6d1ebe..fed396ea57 100644 --- a/libafl/src/mutators/mapping.rs +++ b/libafl/src/mutators/mapping.rs @@ -1,11 +1,11 @@ //! Allowing mixing and matching between [`Mutator`] and [`crate::inputs::Input`] types. use alloc::borrow::Cow; -use libafl_bolts::{tuples::MappingFunctor, Named}; +use libafl_bolts::{Named, tuples::MappingFunctor}; use crate::{ - mutators::{MutationResult, Mutator}, Error, + mutators::{MutationResult, Mutator}, }; /// Mapping [`Mutator`] using a function returning a reference. diff --git a/libafl/src/mutators/mod.rs b/libafl/src/mutators/mod.rs index 01d972aa90..6b4bd35bc6 100644 --- a/libafl/src/mutators/mod.rs +++ b/libafl/src/mutators/mod.rs @@ -48,12 +48,12 @@ pub mod nautilus; use alloc::{borrow::Cow, boxed::Box, vec::Vec}; -use libafl_bolts::{tuples::IntoVec, HasLen, Named}; +use libafl_bolts::{HasLen, Named, tuples::IntoVec}; #[cfg(feature = "nautilus")] pub use nautilus::*; use tuple_list::NonEmptyTuple; -use crate::{corpus::CorpusId, Error}; +use crate::{Error, corpus::CorpusId}; // TODO mutator stats method that produces something that can be sent with the NewTestcase event // We can use it to report which mutations generated the testcase in the broker logs diff --git a/libafl/src/mutators/mopt_mutator.rs b/libafl/src/mutators/mopt_mutator.rs index 19ea88f263..14837287bc 100644 --- a/libafl/src/mutators/mopt_mutator.rs +++ b/libafl/src/mutators/mopt_mutator.rs @@ -6,18 +6,18 @@ use alloc::{borrow::Cow, string::ToString, vec::Vec}; use core::fmt::{self, Debug}; use libafl_bolts::{ + Named, rands::{Rand, StdRand}, tuples::NamedTuple, - Named, }; use serde::{Deserialize, Serialize}; use super::MutationId; use crate::{ + Error, HasMetadata, corpus::{Corpus, CorpusId}, mutators::{ComposedByMutations, MutationResult, Mutator, MutatorsTuple, ScheduledMutator}, state::{HasCorpus, HasRand, HasSolutions}, - Error, HasMetadata, }; /// A Struct for managing MOpt-mutator parameters. diff --git a/libafl/src/mutators/multi.rs b/libafl/src/mutators/multi.rs index f17c64bb61..79ec049929 100644 --- a/libafl/src/mutators/multi.rs +++ b/libafl/src/mutators/multi.rs @@ -1,28 +1,29 @@ //! Mutator definitions for [`MultipartInput`]s. See [`crate::inputs::multi`] for details. use core::{ - cmp::{min, Ordering}, + cmp::{Ordering, min}, num::NonZero, }; -use libafl_bolts::{rands::Rand, Error}; +use libafl_bolts::{Error, rands::Rand}; use crate::{ corpus::{Corpus, CorpusId}, impl_default_multipart, - inputs::{multi::MultipartInput, HasMutatorBytes, Input, Keyed as _, ResizableMutator}, + inputs::{HasMutatorBytes, Input, Keyed as _, ResizableMutator, multi::MultipartInput}, mutators::{ + MutationResult, Mutator, mutations::{ - rand_range, BitFlipMutator, ByteAddMutator, ByteDecMutator, ByteFlipMutator, - ByteIncMutator, ByteInterestingMutator, ByteNegMutator, ByteRandMutator, - BytesCopyMutator, BytesDeleteMutator, BytesExpandMutator, BytesInsertCopyMutator, - BytesInsertMutator, BytesRandInsertMutator, BytesRandSetMutator, BytesSetMutator, - BytesSwapMutator, CrossoverInsertMutator as BytesInputCrossoverInsertMutator, + BitFlipMutator, ByteAddMutator, ByteDecMutator, ByteFlipMutator, ByteIncMutator, + ByteInterestingMutator, ByteNegMutator, ByteRandMutator, BytesCopyMutator, + BytesDeleteMutator, BytesExpandMutator, BytesInsertCopyMutator, BytesInsertMutator, + BytesRandInsertMutator, BytesRandSetMutator, BytesSetMutator, BytesSwapMutator, + CrossoverInsertMutator as BytesInputCrossoverInsertMutator, CrossoverReplaceMutator as BytesInputCrossoverReplaceMutator, DwordAddMutator, DwordInterestingMutator, QwordAddMutator, WordAddMutator, WordInterestingMutator, + rand_range, }, token_mutations::{I2SRandReplace, TokenInsert, TokenReplace}, - MutationResult, Mutator, }, random_corpus_id, state::{HasCorpus, HasMaxSize, HasRand}, diff --git a/libafl/src/mutators/mutations.rs b/libafl/src/mutators/mutations.rs index 8d60225b35..5b3d1373de 100644 --- a/libafl/src/mutators/mutations.rs +++ b/libafl/src/mutators/mutations.rs @@ -12,15 +12,15 @@ use core::{ ops::Range, }; -use libafl_bolts::{rands::Rand, Named}; +use libafl_bolts::{Named, rands::Rand}; use crate::{ + Error, corpus::Corpus, inputs::{HasMutatorBytes, ResizableMutator}, mutators::{MutationResult, Mutator}, nonzero, random_corpus_id_with_disabled, state::{HasCorpus, HasMaxSize, HasRand}, - Error, }; /// Mem move in the own vec @@ -1628,13 +1628,13 @@ pub fn str_decode(item: &str) -> Result, Error> { mod tests { use libafl_bolts::{ rands::StdRand, - tuples::{tuple_list, tuple_list_type, HasConstLen}, + tuples::{HasConstLen, tuple_list, tuple_list_type}, }; use super::*; use crate::{ - corpus::InMemoryCorpus, feedbacks::ConstFeedback, inputs::BytesInput, - mutators::MutatorsTuple, state::StdState, HasMetadata, + HasMetadata, corpus::InMemoryCorpus, feedbacks::ConstFeedback, inputs::BytesInput, + mutators::MutatorsTuple, state::StdState, }; type TestMutatorsTupleType = tuple_list_type!( @@ -1796,11 +1796,13 @@ mod tests { } let average = counts.iter().copied().sum::() / counts.len(); - assert!(counts.into_iter().all(|count| count - .checked_sub(average) - .or_else(|| average.checked_sub(count)) - .unwrap() - < 500)); + assert!(counts.into_iter().all(|count| { + count + .checked_sub(average) + .or_else(|| average.checked_sub(count)) + .unwrap() + < 500 + })); Ok(()) } @@ -1844,11 +1846,13 @@ mod tests { } let average = counts.iter().copied().sum::() / counts.len(); - assert!(counts.into_iter().all(|count| count - .checked_sub(average) - .or_else(|| average.checked_sub(count)) - .unwrap() - < 500)); + assert!(counts.into_iter().all(|count| { + count + .checked_sub(average) + .or_else(|| average.checked_sub(count)) + .unwrap() + < 500 + })); Ok(()) } @@ -1888,17 +1892,21 @@ mod tests { } let average = counts.iter().copied().sum::() / counts.len(); - assert!(counts.into_iter().all(|count| count - .checked_sub(average) - .or_else(|| average.checked_sub(count)) - .unwrap() - < 500)); + assert!(counts.into_iter().all(|count| { + count + .checked_sub(average) + .or_else(|| average.checked_sub(count)) + .unwrap() + < 500 + })); let average = insertions.iter().copied().sum::() / insertions.len(); - assert!(insertions.into_iter().all(|count| count - .checked_sub(average) - .or_else(|| average.checked_sub(count)) - .unwrap() - < 500)); + assert!(insertions.into_iter().all(|count| { + count + .checked_sub(average) + .or_else(|| average.checked_sub(count)) + .unwrap() + < 500 + })); Ok(()) } @@ -1941,17 +1949,21 @@ mod tests { } let average = counts.iter().copied().sum::() / counts.len(); - assert!(counts.iter().all(|&count| count - .checked_sub(average) - .or_else(|| average.checked_sub(count)) - .unwrap() - < 500),); + assert!(counts.iter().all(|&count| { + count + .checked_sub(average) + .or_else(|| average.checked_sub(count)) + .unwrap() + < 500 + }),); let average = insertions.iter().copied().sum::() / insertions.len(); - assert!(insertions.into_iter().all(|count| count - .checked_sub(average) - .or_else(|| average.checked_sub(count)) - .unwrap() - < 500)); + assert!(insertions.into_iter().all(|count| { + count + .checked_sub(average) + .or_else(|| average.checked_sub(count)) + .unwrap() + < 500 + })); Ok(()) } } diff --git a/libafl/src/mutators/nautilus.rs b/libafl/src/mutators/nautilus.rs index 494a75abcb..42e9829743 100644 --- a/libafl/src/mutators/nautilus.rs +++ b/libafl/src/mutators/nautilus.rs @@ -4,11 +4,12 @@ use alloc::borrow::Cow; use core::fmt::Debug; use libafl_bolts::{ - rands::{Rand, RomuDuoJrRand}, Named, + rands::{Rand, RomuDuoJrRand}, }; use crate::{ + Error, HasMetadata, common::nautilus::grammartec::{ context::Context, mutator::Mutator as BackingMutator, @@ -19,7 +20,6 @@ use crate::{ inputs::nautilus::NautilusInput, mutators::{MutationResult, Mutator}, state::{HasCorpus, HasRand}, - Error, HasMetadata, }; /// The randomic mutator for `Nautilus` grammar. diff --git a/libafl/src/mutators/numeric.rs b/libafl/src/mutators/numeric.rs index f0ed541671..6a4c92e93b 100644 --- a/libafl/src/mutators/numeric.rs +++ b/libafl/src/mutators/numeric.rs @@ -4,9 +4,9 @@ use alloc::borrow::Cow; use core::marker::PhantomData; use libafl_bolts::{ + Error, Named, rands::Rand, tuples::{Map as _, Merge}, - Error, Named, }; use tuple_list::{tuple_list, tuple_list_type}; @@ -442,7 +442,7 @@ mod tests { }; use serde::{Deserialize, Serialize}; - use super::{int_mutators, Numeric}; + use super::{Numeric, int_mutators}; use crate::{ corpus::{Corpus as _, InMemoryCorpus, Testcase}, inputs::value::I16Input, diff --git a/libafl/src/mutators/scheduled.rs b/libafl/src/mutators/scheduled.rs index 30395e34b1..4124d46dc5 100644 --- a/libafl/src/mutators/scheduled.rs +++ b/libafl/src/mutators/scheduled.rs @@ -8,22 +8,22 @@ use core::{ }; use libafl_bolts::{ - rands::Rand, - tuples::{tuple_list, tuple_list_type, HasConstLen, NamedTuple}, Named, + rands::Rand, + tuples::{HasConstLen, NamedTuple, tuple_list, tuple_list_type}, }; use serde::{Deserialize, Serialize}; use super::MutationId; use crate::{ + Error, HasMetadata, corpus::{Corpus, CorpusId}, mutators::{ - token_mutations::{TokenInsert, TokenReplace}, MutationResult, Mutator, MutatorsTuple, + token_mutations::{TokenInsert, TokenReplace}, }, nonzero, state::{HasCorpus, HasRand}, - Error, HasMetadata, }; /// The metadata placed in a [`crate::corpus::Testcase`] by a [`LoggerScheduledMutator`]. @@ -317,8 +317,8 @@ mod tests { feedbacks::ConstFeedback, inputs::{BytesInput, HasMutatorBytes}, mutators::{ - havoc_mutations::havoc_mutations, mutations::SpliceMutator, - scheduled::StdScheduledMutator, Mutator, + Mutator, havoc_mutations::havoc_mutations, mutations::SpliceMutator, + scheduled::StdScheduledMutator, }, state::StdState, }; diff --git a/libafl/src/mutators/token_mutations.rs b/libafl/src/mutators/token_mutations.rs index 9b9f6b5c9c..eaebcb960d 100644 --- a/libafl/src/mutators/token_mutations.rs +++ b/libafl/src/mutators/token_mutations.rs @@ -18,21 +18,21 @@ use std::{ }; use hashbrown::HashSet; -use libafl_bolts::{rands::Rand, AsSlice, HasLen}; +use libafl_bolts::{AsSlice, HasLen, rands::Rand}; use serde::{Deserialize, Serialize}; #[cfg(feature = "std")] use crate::mutators::str_decode; use crate::{ + Error, HasMetadata, corpus::{CorpusId, HasCurrentCorpusId}, inputs::{HasMutatorBytes, ResizableMutator}, mutators::{ - buffer_self_copy, mutations::buffer_copy, MultiMutator, MutationResult, Mutator, Named, + MultiMutator, MutationResult, Mutator, Named, buffer_self_copy, mutations::buffer_copy, }, observers::cmp::{AFLppCmpValuesMetadata, CmpValues, CmpValuesMetadata}, stages::TaintMetadata, state::{HasCorpus, HasMaxSize, HasRand}, - Error, HasMetadata, }; /// A state metadata holding a list of tokens @@ -113,23 +113,25 @@ impl Tokens { token_start: *const u8, token_stop: *const u8, ) -> Result { - let mut ret = Self::default(); - if token_start.is_null() || token_stop.is_null() { - return Ok(Self::new()); - } - if token_stop < token_start { - return Err(Error::illegal_argument(format!( - "Tried to create tokens from illegal section: stop < start ({token_stop:?} < {token_start:?})" - ))); - } - let section_size: usize = token_stop.offset_from(token_start).try_into().unwrap(); - // log::info!("size: {}", section_size); - let slice = from_raw_parts(token_start, section_size); + unsafe { + let mut ret = Self::default(); + if token_start.is_null() || token_stop.is_null() { + return Ok(Self::new()); + } + if token_stop < token_start { + return Err(Error::illegal_argument(format!( + "Tried to create tokens from illegal section: stop < start ({token_stop:?} < {token_start:?})" + ))); + } + let section_size: usize = token_stop.offset_from(token_start).try_into().unwrap(); + // log::info!("size: {}", section_size); + let slice = from_raw_parts(token_start, section_size); - // Now we know the beginning and the end of the token section.. let's parse them into tokens - ret.parse_autodict(slice, section_size); + // Now we know the beginning and the end of the token section.. let's parse them into tokens + ret.parse_autodict(slice, section_size); - Ok(ret) + Ok(ret) + } } /// Creates a new instance from a file @@ -195,7 +197,7 @@ impl Tokens { Err(_) => { return Err(Error::illegal_argument(format!( "Illegal line (hex decoding): {line}" - ))) + ))); } }; diff --git a/libafl/src/mutators/tuneable.rs b/libafl/src/mutators/tuneable.rs index 885f5732bc..d980e651fd 100644 --- a/libafl/src/mutators/tuneable.rs +++ b/libafl/src/mutators/tuneable.rs @@ -7,18 +7,18 @@ use alloc::{borrow::Cow, vec::Vec}; use core::{fmt::Debug, num::NonZero}; use libafl_bolts::{ - impl_serdeany, math::calculate_cumulative_distribution_in_place, rands::Rand, - tuples::NamedTuple, Named, + Named, impl_serdeany, math::calculate_cumulative_distribution_in_place, rands::Rand, + tuples::NamedTuple, }; use serde::{Deserialize, Serialize}; pub use crate::mutators::{mutations::*, token_mutations::*}; use crate::{ + Error, HasMetadata, mutators::{ ComposedByMutations, MutationId, MutationResult, Mutator, MutatorsTuple, ScheduledMutator, }, state::HasRand, - Error, HasMetadata, }; /// Metadata in the state, that controls the behavior of the [`TuneableScheduledMutator`] at runtime @@ -404,36 +404,52 @@ mod test { let input = BytesInput::new(vec![42]); // Basic tests over the probability distribution. - assert!(tuneable - .set_mutation_probabilities(&mut state, vec![0.0]) - .is_err()); - assert!(tuneable - .set_mutation_probabilities(&mut state, vec![1.0; 3]) - .is_err()); - assert!(tuneable - .set_mutation_probabilities(&mut state, vec![-1.0, 1.0, 1.0]) - .is_err()); - assert!(tuneable - .set_mutation_probabilities(&mut state, vec![]) - .is_err()); + assert!( + tuneable + .set_mutation_probabilities(&mut state, vec![0.0]) + .is_err() + ); + assert!( + tuneable + .set_mutation_probabilities(&mut state, vec![1.0; 3]) + .is_err() + ); + assert!( + tuneable + .set_mutation_probabilities(&mut state, vec![-1.0, 1.0, 1.0]) + .is_err() + ); + assert!( + tuneable + .set_mutation_probabilities(&mut state, vec![]) + .is_err() + ); - assert!(tuneable - .set_mutation_probabilities(&mut state, vec![0.0, 0.0, 1.0]) - .is_ok()); + assert!( + tuneable + .set_mutation_probabilities(&mut state, vec![0.0, 0.0, 1.0]) + .is_ok() + ); assert_eq!(tuneable.schedule(&mut state, &input), 2.into()); - assert!(tuneable - .set_mutation_probabilities(&mut state, vec![0.0, 1.0, 0.0]) - .is_ok()); + assert!( + tuneable + .set_mutation_probabilities(&mut state, vec![0.0, 1.0, 0.0]) + .is_ok() + ); assert_eq!(tuneable.schedule(&mut state, &input), 1.into()); - assert!(tuneable - .set_mutation_probabilities(&mut state, vec![1.0, 0.0, 0.0]) - .is_ok()); + assert!( + tuneable + .set_mutation_probabilities(&mut state, vec![1.0, 0.0, 0.0]) + .is_ok() + ); assert_eq!(tuneable.schedule(&mut state, &input), 0.into()); // We should not choose a mutation with p=0. - assert!(tuneable - .set_mutation_probabilities(&mut state, vec![0.5, 0.0, 0.5]) - .is_ok()); + assert!( + tuneable + .set_mutation_probabilities(&mut state, vec![0.5, 0.0, 0.5]) + .is_ok() + ); assert!(tuneable.schedule(&mut state, &input) != 1.into()); } } diff --git a/libafl/src/mutators/unicode/mod.rs b/libafl/src/mutators/unicode/mod.rs index 3edae9317e..66d3e22132 100644 --- a/libafl/src/mutators/unicode/mod.rs +++ b/libafl/src/mutators/unicode/mod.rs @@ -7,20 +7,19 @@ use core::{ ops::Range, }; -use libafl_bolts::{rands::Rand, Error, HasLen, Named}; +use libafl_bolts::{Error, HasLen, Named, rands::Rand}; use crate::{ + HasMetadata, corpus::{CorpusId, HasTestcase, Testcase}, inputs::{BytesInput, HasMutatorBytes, ResizableMutator}, - mutators::{rand_range, MutationResult, Mutator, Tokens}, + mutators::{MutationResult, Mutator, Tokens, rand_range}, nonzero, stages::{ - extract_metadata, + UnicodeIdentificationMetadata, extract_metadata, mutational::{MutatedTransform, MutatedTransformPost}, - UnicodeIdentificationMetadata, }, state::{HasCorpus, HasMaxSize, HasRand}, - HasMetadata, }; /// Unicode category data, as used by string analysis and mutators. @@ -508,7 +507,7 @@ where #[cfg(test)] mod test { - use libafl_bolts::{rands::StdRand, Error}; + use libafl_bolts::{Error, rands::StdRand}; use crate::{ corpus::NopCorpus, diff --git a/libafl/src/observers/cmp.rs b/libafl/src/observers/cmp.rs index 58fb3dd738..283c4e5016 100644 --- a/libafl/src/observers/cmp.rs +++ b/libafl/src/observers/cmp.rs @@ -8,10 +8,10 @@ use core::{ use arbitrary_int::{u1, u4, u5, u6}; use bitbybit::bitfield; use hashbrown::HashMap; -use libafl_bolts::{ownedref::OwnedRefMut, AsSlice, HasLen, Named}; +use libafl_bolts::{AsSlice, HasLen, Named, ownedref::OwnedRefMut}; use serde::{Deserialize, Serialize}; -use crate::{executors::ExitKind, observers::Observer, Error, HasMetadata}; +use crate::{Error, HasMetadata, executors::ExitKind, observers::Observer}; /// A bytes string for cmplog with up to 32 elements. #[derive(Debug, Copy, Clone, Serialize, Deserialize, Eq, PartialEq)] diff --git a/libafl/src/observers/concolic/metadata.rs b/libafl/src/observers/concolic/metadata.rs index 624baf66e6..c55c54858f 100644 --- a/libafl/src/observers/concolic/metadata.rs +++ b/libafl/src/observers/concolic/metadata.rs @@ -2,7 +2,7 @@ use alloc::vec::Vec; use serde::{Deserialize, Serialize}; -use crate::observers::concolic::{serialization_format::MessageFileReader, SymExpr, SymExprRef}; +use crate::observers::concolic::{SymExpr, SymExprRef, serialization_format::MessageFileReader}; /// A metadata holding a buffer of a concolic trace. #[derive(Default, Serialize, Deserialize, Debug)] diff --git a/libafl/src/observers/concolic/observer.rs b/libafl/src/observers/concolic/observer.rs index 8365cc014e..b36a9f1297 100644 --- a/libafl/src/observers/concolic/observer.rs +++ b/libafl/src/observers/concolic/observer.rs @@ -4,8 +4,8 @@ use libafl_bolts::Named; use serde::{Deserialize, Serialize}; use crate::observers::{ - concolic::{serialization_format::MessageFileReader, ConcolicMetadata}, Observer, + concolic::{ConcolicMetadata, serialization_format::MessageFileReader}, }; /// A standard [`ConcolicObserver`] observer, observing constraints written into a memory buffer. diff --git a/libafl/src/observers/list.rs b/libafl/src/observers/list.rs index 125e7db064..6f352ca388 100644 --- a/libafl/src/observers/list.rs +++ b/libafl/src/observers/list.rs @@ -1,7 +1,7 @@ use alloc::{borrow::Cow, vec::Vec}; use core::fmt::Debug; -use libafl_bolts::{ownedref::OwnedMutPtr, Error, Named}; +use libafl_bolts::{Error, Named, ownedref::OwnedMutPtr}; use serde::{Deserialize, Serialize}; use crate::observers::Observer; diff --git a/libafl/src/observers/map/const_map.rs b/libafl/src/observers/map/const_map.rs index 10e2cee368..12637d8fc7 100644 --- a/libafl/src/observers/map/const_map.rs +++ b/libafl/src/observers/map/const_map.rs @@ -8,12 +8,12 @@ use core::{ ptr::NonNull, }; -use libafl_bolts::{ownedref::OwnedMutSizedSlice, HasLen, Named}; -use serde::{de::DeserializeOwned, Deserialize, Serialize}; +use libafl_bolts::{HasLen, Named, ownedref::OwnedMutSizedSlice}; +use serde::{Deserialize, Serialize, de::DeserializeOwned}; use crate::{ - observers::{map::MapObserver, ConstLenMapObserver, Observer}, Error, + observers::{ConstLenMapObserver, Observer, map::MapObserver}, }; /// Use a const size to speedup `Feedback::is_interesting` when the user can @@ -194,10 +194,12 @@ where /// Will dereference the `map_ptr` with up to len elements. #[must_use] pub unsafe fn from_mut_ptr(name: &'static str, map_ptr: NonNull<[T; N]>) -> Self { - ConstMapObserver { - map: OwnedMutSizedSlice::from_raw_mut(map_ptr), - name: Cow::from(name), - initial: T::default(), + unsafe { + ConstMapObserver { + map: OwnedMutSizedSlice::from_raw_mut(map_ptr), + name: Cow::from(name), + initial: T::default(), + } } } diff --git a/libafl/src/observers/map/hitcount_map.rs b/libafl/src/observers/map/hitcount_map.rs index 7eddb77723..4ac600bb2f 100644 --- a/libafl/src/observers/map/hitcount_map.rs +++ b/libafl/src/observers/map/hitcount_map.rs @@ -12,11 +12,11 @@ use libafl_bolts::{AsIter, AsIterMut, AsSlice, AsSliceMut, HasLen, Named, Trunca use serde::{Deserialize, Serialize}; use crate::{ + Error, executors::ExitKind, observers::{ - map::MapObserver, ConstLenMapObserver, DifferentialObserver, Observer, VarLenMapObserver, + ConstLenMapObserver, DifferentialObserver, Observer, VarLenMapObserver, map::MapObserver, }, - Error, }; /// Hitcounts class lookup diff --git a/libafl/src/observers/map/mod.rs b/libafl/src/observers/map/mod.rs index 7fe70b0d4b..89ea01ea9d 100644 --- a/libafl/src/observers/map/mod.rs +++ b/libafl/src/observers/map/mod.rs @@ -7,13 +7,13 @@ use core::{ ops::{Deref, DerefMut}, }; -use libafl_bolts::{ownedref::OwnedMutSlice, AsSlice, AsSliceMut, HasLen, Named, Truncate}; -use serde::{de::DeserializeOwned, Deserialize, Serialize}; +use libafl_bolts::{AsSlice, AsSliceMut, HasLen, Named, Truncate, ownedref::OwnedMutSlice}; +use serde::{Deserialize, Serialize, de::DeserializeOwned}; use crate::{ + Error, executors::ExitKind, observers::{DifferentialObserver, Observer}, - Error, }; pub mod const_map; @@ -57,7 +57,7 @@ pub use owned_map::*; /// # #[cfg(any(not(feature = "serdeany_autoreg"), miri))] /// # unsafe { MapFeedbackMetadata::::register() } /// # #[cfg(not(feature = "std"))] -/// # #[no_mangle] +/// # #[unsafe(no_mangle)] /// # pub extern "C" fn external_current_millis() -> u64 { 0 } /// /// use libafl_bolts::ownedref::OwnedMutSlice; @@ -203,7 +203,7 @@ impl AsMut for ExplicitTracking>, { - let len = map.len(); - let ptr = map.as_mut_ptr(); - Self::maybe_differential_from_mut_ptr(name, ptr, len) + unsafe { + let len = map.len(); + let ptr = map.as_mut_ptr(); + Self::maybe_differential_from_mut_ptr(name, ptr, len) + } } /// Creates a new [`MapObserver`] from an [`OwnedMutSlice`] @@ -650,10 +652,12 @@ where where S: Into>, { - Self::maybe_differential_from_mut_slice( - name, - OwnedMutSlice::from_raw_parts_mut(map_ptr, len), - ) + unsafe { + Self::maybe_differential_from_mut_slice( + name, + OwnedMutSlice::from_raw_parts_mut(map_ptr, len), + ) + } } /// Gets the initial value for this map, mutably @@ -686,7 +690,7 @@ where where S: Into>, { - Self::maybe_differential(name, map) + unsafe { Self::maybe_differential(name, map) } } /// Creates a new [`MapObserver`] from an [`OwnedMutSlice`] @@ -726,7 +730,7 @@ where where S: Into>, { - Self::maybe_differential_from_mut_ptr(name, map_ptr, len) + unsafe { Self::maybe_differential_from_mut_ptr(name, map_ptr, len) } } } @@ -744,7 +748,7 @@ where where S: Into>, { - Self::maybe_differential(name, map) + unsafe { Self::maybe_differential(name, map) } } /// Creates a new [`MapObserver`] with an owned map in differential mode @@ -776,7 +780,7 @@ where where S: Into>, { - Self::maybe_differential_from_mut_ptr(name, map_ptr, len) + unsafe { Self::maybe_differential_from_mut_ptr(name, map_ptr, len) } } } diff --git a/libafl/src/observers/map/multi_map.rs b/libafl/src/observers/map/multi_map.rs index bb002f9235..4391340211 100644 --- a/libafl/src/observers/map/multi_map.rs +++ b/libafl/src/observers/map/multi_map.rs @@ -9,14 +9,14 @@ use core::{ }; use libafl_bolts::{ - ownedref::OwnedMutSlice, AsIter, AsIterMut, AsSlice, AsSliceMut, HasLen, Named, + AsIter, AsIterMut, AsSlice, AsSliceMut, HasLen, Named, ownedref::OwnedMutSlice, }; use meminterval::IntervalTree; -use serde::{de::DeserializeOwned, Deserialize, Serialize}; +use serde::{Deserialize, Serialize, de::DeserializeOwned}; use crate::{ - observers::{map::MapObserver, DifferentialObserver, Observer}, Error, + observers::{DifferentialObserver, Observer, map::MapObserver}, }; /// The Multi Map Observer merge different maps into one observer diff --git a/libafl/src/observers/map/owned_map.rs b/libafl/src/observers/map/owned_map.rs index 6689201098..905708d9d2 100644 --- a/libafl/src/observers/map/owned_map.rs +++ b/libafl/src/observers/map/owned_map.rs @@ -8,11 +8,11 @@ use core::{ }; use libafl_bolts::{AsSlice, AsSliceMut, HasLen, Named}; -use serde::{de::DeserializeOwned, Deserialize, Serialize}; +use serde::{Deserialize, Serialize, de::DeserializeOwned}; use crate::{ - observers::{map::MapObserver, Observer}, Error, + observers::{Observer, map::MapObserver}, }; /// Exact copy of `StdMapObserver` that owns its map diff --git a/libafl/src/observers/map/variable_map.rs b/libafl/src/observers/map/variable_map.rs index cfd3cf21eb..19b36cc22c 100644 --- a/libafl/src/observers/map/variable_map.rs +++ b/libafl/src/observers/map/variable_map.rs @@ -8,14 +8,14 @@ use core::{ }; use libafl_bolts::{ - ownedref::{OwnedMutPtr, OwnedMutSlice}, AsSlice, AsSliceMut, HasLen, Named, + ownedref::{OwnedMutPtr, OwnedMutSlice}, }; -use serde::{de::DeserializeOwned, Deserialize, Serialize}; +use serde::{Deserialize, Serialize, de::DeserializeOwned}; use crate::{ - observers::{map::MapObserver, Observer, VarLenMapObserver}, Error, + observers::{Observer, VarLenMapObserver, map::MapObserver}, }; /// Overlooking a variable bitmap @@ -212,10 +212,12 @@ where max_len: usize, size: *mut usize, ) -> Self { - Self::from_mut_slice( - name, - OwnedMutSlice::from_raw_parts_mut(map_ptr, max_len), - size, - ) + unsafe { + Self::from_mut_slice( + name, + OwnedMutSlice::from_raw_parts_mut(map_ptr, max_len), + size, + ) + } } } diff --git a/libafl/src/observers/mod.rs b/libafl/src/observers/mod.rs index 6cd5c103ab..266237730b 100644 --- a/libafl/src/observers/mod.rs +++ b/libafl/src/observers/mod.rs @@ -34,12 +34,12 @@ use std::time::Instant; #[cfg(not(feature = "std"))] use libafl_bolts::current_time; -use libafl_bolts::{tuples::MatchName, Named}; +use libafl_bolts::{Named, tuples::MatchName}; pub use list::*; use serde::{Deserialize, Serialize}; pub use value::*; -use crate::{executors::ExitKind, Error}; +use crate::{Error, executors::ExitKind}; /// Observers observe different information about the target. /// They can then be used by various sorts of feedback. @@ -402,9 +402,9 @@ impl DifferentialObserver for TimeObserver {} mod tests { use libafl_bolts::{ + Named, ownedref::OwnedMutSlice, tuples::{tuple_list, tuple_list_type}, - Named, }; use crate::observers::{StdMapObserver, TimeObserver}; diff --git a/libafl/src/observers/profiling.rs b/libafl/src/observers/profiling.rs index 8f73169f26..3938b6d4bd 100644 --- a/libafl/src/observers/profiling.rs +++ b/libafl/src/observers/profiling.rs @@ -2,10 +2,10 @@ use alloc::{borrow::Cow, string::String}; use std::{fs::File, io::BufReader, path::Path}; use hashbrown::HashMap; -use libafl_bolts::{ownedref::OwnedMutPtr, Named}; +use libafl_bolts::{Named, ownedref::OwnedMutPtr}; use serde::{Deserialize, Serialize}; -use crate::{observers::Observer, Error}; +use crate::{Error, observers::Observer}; #[derive(Debug, Serialize, Deserialize)] /// The json data pub struct FunctionData { diff --git a/libafl/src/observers/stacktrace.rs b/libafl/src/observers/stacktrace.rs index 456a31120f..7ec365b18e 100644 --- a/libafl/src/observers/stacktrace.rs +++ b/libafl/src/observers/stacktrace.rs @@ -16,7 +16,7 @@ use std::{ }; use backtrace::Backtrace; -use libafl_bolts::{ownedref::OwnedRefMut, Named}; +use libafl_bolts::{Named, ownedref::OwnedRefMut}; #[allow(unused_imports)] // expect breaks here for some reason #[cfg(feature = "casr")] use libcasr::{ @@ -30,8 +30,8 @@ use libcasr::{ }, init_ignored_frames, stacktrace::{ - Filter, ParseStacktrace, Stacktrace, StacktraceEntry, STACK_FRAME_FILEPATH_IGNORE_REGEXES, - STACK_FRAME_FUNCTION_IGNORE_REGEXES, + Filter, ParseStacktrace, STACK_FRAME_FILEPATH_IGNORE_REGEXES, + STACK_FRAME_FUNCTION_IGNORE_REGEXES, Stacktrace, StacktraceEntry, }, }; #[cfg(not(feature = "casr"))] @@ -39,7 +39,7 @@ use regex::Regex; use serde::{Deserialize, Serialize}; use super::ObserverWithHashField; -use crate::{executors::ExitKind, observers::Observer, Error}; +use crate::{Error, executors::ExitKind, observers::Observer}; #[cfg(not(feature = "casr"))] /// Collects the backtrace via [`Backtrace`] and [`Debug`] diff --git a/libafl/src/observers/stdio.rs b/libafl/src/observers/stdio.rs index 9cb20418a1..853db0a67b 100644 --- a/libafl/src/observers/stdio.rs +++ b/libafl/src/observers/stdio.rs @@ -14,7 +14,7 @@ use std::vec::Vec; use libafl_bolts::Named; use serde::{Deserialize, Serialize}; -use crate::{observers::Observer, Error}; +use crate::{Error, observers::Observer}; /// An observer that captures stdout of a target. /// Only works for supported executors. @@ -23,8 +23,8 @@ use crate::{observers::Observer, Error}; #[cfg_attr(all(target_os = "linux", not(miri)), doc = " ```")] // miri doesn't like the Command crate, linux as a shorthand for the availability of base64 #[cfg_attr(not(all(target_os = "linux", not(miri))), doc = " ```ignore")] /// use std::borrow::Cow; -/// /// use libafl::{ +/// Error, Fuzzer, StdFuzzer, /// corpus::{Corpus, InMemoryCorpus, Testcase}, /// events::{EventFirer, NopEventManager}, /// executors::{CommandExecutor, ExitKind}, @@ -33,16 +33,12 @@ use crate::{observers::Observer, Error}; /// mutators::{MutationResult, NopMutator}, /// observers::{ObserversTuple, StdErrObserver, StdOutObserver}, /// schedulers::QueueScheduler, -/// stages::StdMutationalStage, -/// state::{HasCorpus, StdState}, -/// Error, Fuzzer, StdFuzzer, +/// stages::StdMutationalStage, state::{HasCorpus, StdState}, /// }; -/// /// use libafl_bolts::{ -/// current_nanos, +/// Named, current_nanos, /// rands::StdRand, -/// tuples::{tuple_list, Handle, Handled, MatchNameRef}, -/// Named, +/// tuples::{Handle, Handled, MatchNameRef, tuple_list}, /// }; /// /// static mut STDOUT: Option> = None; @@ -56,118 +52,124 @@ use crate::{observers::Observer, Error}; /// /// impl StateInitializer for ExportStdXObserver {} /// -/// /// impl Feedback for ExportStdXObserver /// where -/// OT: MatchNameRef +/// OT: MatchNameRef, /// { -/// fn is_interesting( -/// &mut self, -/// _state: &mut S, -/// _manager: &mut EM, -/// _input: &I, -/// observers: &OT, -/// _exit_kind: &ExitKind, -/// ) -> Result -/// { -/// unsafe { -/// STDOUT = observers.get(&self.stdout_observer).unwrap().output.clone(); -/// STDERR = observers.get(&self.stderr_observer).unwrap().output.clone(); -/// } -/// Ok(true) -/// } +/// fn is_interesting( +/// &mut self, +/// _state: &mut S, +/// _manager: &mut EM, +/// _input: &I, +/// observers: &OT, +/// _exit_kind: &ExitKind, +/// ) -> Result { +/// unsafe { +/// STDOUT = observers.get(&self.stdout_observer).unwrap().output.clone(); +/// STDERR = observers.get(&self.stderr_observer).unwrap().output.clone(); +/// } +/// Ok(true) +/// } /// -/// #[cfg(feature = "track_hit_feedbacks")] -/// fn last_result(&self) -> Result { -/// Ok(true) -/// } -/// } +/// #[cfg(feature = "track_hit_feedbacks")] +/// fn last_result(&self) -> Result { +/// Ok(true) +/// } +/// } /// /// impl Named for ExportStdXObserver { -/// fn name(&self) -> &Cow<'static, str> { -/// &Cow::Borrowed("ExportStdXObserver") -/// } -/// } +/// fn name(&self) -> &Cow<'static, str> { +/// &Cow::Borrowed("ExportStdXObserver") +/// } +/// } /// -/// fn main() { -/// let input_text = "Hello, World!"; -/// let encoded_input_text = "SGVsbG8sIFdvcmxkIQo="; +/// fn main() { +/// let input_text = "Hello, World!"; +/// let encoded_input_text = "SGVsbG8sIFdvcmxkIQo="; /// -/// let stdout_observer = StdOutObserver::new("stdout-observer"); -/// let stderr_observer = StdErrObserver::new("stderr-observer"); +/// let stdout_observer = StdOutObserver::new("stdout-observer"); +/// let stderr_observer = StdErrObserver::new("stderr-observer"); /// -/// let mut feedback = ExportStdXObserver { -/// stdout_observer: stdout_observer.handle(), -/// stderr_observer: stderr_observer.handle(), -/// }; +/// let mut feedback = ExportStdXObserver { +/// stdout_observer: stdout_observer.handle(), +/// stderr_observer: stderr_observer.handle(), +/// }; /// -/// let mut objective = (); +/// let mut objective = (); /// -/// let mut executor = CommandExecutor::builder() -/// .program("base64") -/// .arg("--decode") -/// .stdout_observer(stdout_observer.handle()) -/// .stderr_observer(stderr_observer.handle()) -/// .build(tuple_list!(stdout_observer, stderr_observer)) -/// .unwrap(); +/// let mut executor = CommandExecutor::builder() +/// .program("base64") +/// .arg("--decode") +/// .stdout_observer(stdout_observer.handle()) +/// .stderr_observer(stderr_observer.handle()) +/// .build(tuple_list!(stdout_observer, stderr_observer)) +/// .unwrap(); /// -/// let mut state = StdState::new( -/// StdRand::with_seed(current_nanos()), -/// InMemoryCorpus::new(), -/// InMemoryCorpus::new(), -/// &mut feedback, -/// &mut objective, -/// ) -/// .unwrap(); +/// let mut state = StdState::new( +/// StdRand::with_seed(current_nanos()), +/// InMemoryCorpus::new(), +/// InMemoryCorpus::new(), +/// &mut feedback, +/// &mut objective, +/// ) +/// .unwrap(); /// -/// let scheduler = QueueScheduler::new(); -/// let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); -/// let mut manager = NopEventManager::new(); +/// let scheduler = QueueScheduler::new(); +/// let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); +/// let mut manager = NopEventManager::new(); /// -/// let mut stages = tuple_list!(StdMutationalStage::new(NopMutator::new( -/// MutationResult::Mutated -/// ))); +/// let mut stages = tuple_list!(StdMutationalStage::new(NopMutator::new( +/// MutationResult::Mutated +/// ))); /// -/// state -/// .corpus_mut() -/// .add(Testcase::new(BytesInput::from( -/// encoded_input_text.as_bytes().to_vec(), -/// ))) -/// .unwrap(); +/// state +/// .corpus_mut() +/// .add(Testcase::new(BytesInput::from( +/// encoded_input_text.as_bytes().to_vec(), +/// ))) +/// .unwrap(); /// -/// let corpus_id = fuzzer -/// .fuzz_one(&mut stages, &mut executor, &mut state, &mut manager) -/// .unwrap(); +/// let corpus_id = fuzzer +/// .fuzz_one(&mut stages, &mut executor, &mut state, &mut manager) +/// .unwrap(); /// -/// unsafe { -/// assert!(input_text -/// .as_bytes() -/// .iter() -/// .zip(STDOUT.as_ref().unwrap().iter().filter(|e| **e != 10)) // ignore newline chars -/// .all(|(&a, &b)| a == b)); -/// assert!(STDERR.as_ref().unwrap().is_empty()); -/// } +/// unsafe { +/// assert!( +/// input_text +/// .as_bytes() +/// .iter() +/// .zip( +/// (&*(&raw const STDOUT)) +/// .as_ref() +/// .unwrap() +/// .iter() +/// .filter(|e| **e != 10) +/// ) // ignore newline chars +/// .all(|(&a, &b)| a == b) +/// ); +/// assert!((&*(&raw const STDERR)).as_ref().unwrap().is_empty()); +/// } /// -/// state -/// .corpus() -/// .get(corpus_id) -/// .unwrap() -/// .replace(Testcase::new(BytesInput::from( -/// encoded_input_text.bytes().skip(1).collect::>(), // skip one char to make it invalid code -/// ))); +/// state +/// .corpus() +/// .get(corpus_id) +/// .unwrap() +/// .replace(Testcase::new(BytesInput::from( +/// encoded_input_text.bytes().skip(1).collect::>(), // skip one char to make it invalid code +/// ))); /// -/// fuzzer -/// .fuzz_one(&mut stages, &mut executor, &mut state, &mut manager) -/// .unwrap(); +/// fuzzer +/// .fuzz_one(&mut stages, &mut executor, &mut state, &mut manager) +/// .unwrap(); /// -/// unsafe { -/// let compare_vec: Vec = Vec::new(); -/// assert_eq!(compare_vec, *STDERR.as_ref().unwrap()); -/// // stdout will still contain data, we're just checking that there is an error message -/// } +/// unsafe { +/// let compare_vec: Vec = Vec::new(); +/// assert_eq!(compare_vec, *(&*(&raw const STDERR)).clone().unwrap()); +/// // stdout will still contain data, we're just checking that there is an error message +/// } /// } /// ``` - +/// #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct OutputObserver { /// The name of the observer. diff --git a/libafl/src/observers/value.rs b/libafl/src/observers/value.rs index 8db0bc9a58..ff857ad43a 100644 --- a/libafl/src/observers/value.rs +++ b/libafl/src/observers/value.rs @@ -9,12 +9,12 @@ use core::{ }; use ahash::RandomState; -use libafl_bolts::{ownedref::OwnedRef, AsIter, AsIterMut, AsSlice, AsSliceMut, HasLen, Named}; -use serde::{de::DeserializeOwned, Deserialize, Serialize}; +use libafl_bolts::{AsIter, AsIterMut, AsSlice, AsSliceMut, HasLen, Named, ownedref::OwnedRef}; +use serde::{Deserialize, Serialize, de::DeserializeOwned}; use crate::{ - observers::{MapObserver, Observer, ObserverWithHashField}, Error, + observers::{MapObserver, Observer, ObserverWithHashField}, }; /// A simple observer with a single value. @@ -234,17 +234,18 @@ impl<'it, T: 'it> Iterator for RefCellValueObserverIterMut<'it, T> { type Item = RefMut<'it, T>; fn next(&mut self) -> Option { - if let Some(v) = self.v.take() { - let next_slice = if v.len() > 1 { - let (next, remainder) = RefMut::map_split(v, |v| v.split_at_mut(1)); - self.v = Some(remainder); - next - } else { - v - }; - Some(RefMut::map(next_slice, |v| &mut v[0])) - } else { - None + match self.v.take() { + Some(v) => { + let next_slice = if v.len() > 1 { + let (next, remainder) = RefMut::map_split(v, |v| v.split_at_mut(1)); + self.v = Some(remainder); + next + } else { + v + }; + Some(RefMut::map(next_slice, |v| &mut v[0])) + } + _ => None, } } } diff --git a/libafl/src/schedulers/accounting.rs b/libafl/src/schedulers/accounting.rs index cd3e4b96a1..e85d5336fb 100644 --- a/libafl/src/schedulers/accounting.rs +++ b/libafl/src/schedulers/accounting.rs @@ -7,19 +7,19 @@ use core::{ }; use hashbrown::HashMap; -use libafl_bolts::{rands::Rand, tuples::MatchName, HasLen, HasRefCnt}; +use libafl_bolts::{HasLen, HasRefCnt, rands::Rand, tuples::MatchName}; use serde::{Deserialize, Serialize}; use super::IndexesLenTimeMinimizerScheduler; use crate::{ + Error, HasMetadata, corpus::{Corpus, CorpusId}, observers::CanTrack, schedulers::{ - minimizer::{IsFavoredMetadata, MinimizerScheduler, DEFAULT_SKIP_NON_FAVORED_PROB}, Scheduler, + minimizer::{DEFAULT_SKIP_NON_FAVORED_PROB, IsFavoredMetadata, MinimizerScheduler}, }, state::{HasCorpus, HasRand}, - Error, HasMetadata, }; /// A testcase metadata holding a list of indexes of a map diff --git a/libafl/src/schedulers/minimizer.rs b/libafl/src/schedulers/minimizer.rs index c6488cbee3..53dccf25ff 100644 --- a/libafl/src/schedulers/minimizer.rs +++ b/libafl/src/schedulers/minimizer.rs @@ -5,18 +5,18 @@ use alloc::vec::Vec; use core::{any::type_name, cmp::Ordering, marker::PhantomData}; use hashbrown::{HashMap, HashSet}; -use libafl_bolts::{rands::Rand, serdeany::SerdeAny, tuples::MatchName, AsIter, HasRefCnt}; +use libafl_bolts::{AsIter, HasRefCnt, rands::Rand, serdeany::SerdeAny, tuples::MatchName}; use serde::{Deserialize, Serialize}; use super::HasQueueCycles; use crate::{ + Error, HasMetadata, corpus::{Corpus, CorpusId, Testcase}, feedbacks::MapIndexesMetadata, observers::CanTrack, require_index_tracking, schedulers::{LenTimeMulTestcaseScore, RemovableScheduler, Scheduler, TestcaseScore}, state::{HasCorpus, HasRand}, - Error, HasMetadata, }; /// Default probability to skip the non-favored values @@ -129,30 +129,33 @@ where let mut entry = e_iter.next(); let mut map_entry = map_iter.next(); while let Some(e) = entry { - if let Some(ref me) = map_entry { - match e.cmp(me) { - Ordering::Less => { - entry = e_iter.next(); - } - Ordering::Equal => { - // if we found a better factor, prefer it - map.entry(*e) - .and_modify(|(f, id)| { - if *f > factor { - *f = factor; - *id = current_id; - } - }) - .or_insert((factor, current_id)); - entry = e_iter.next(); - map_entry = map_iter.next(); - } - Ordering::Greater => { - map_entry = map_iter.next(); + match map_entry { + Some(ref me) => { + match e.cmp(me) { + Ordering::Less => { + entry = e_iter.next(); + } + Ordering::Equal => { + // if we found a better factor, prefer it + map.entry(*e) + .and_modify(|(f, id)| { + if *f > factor { + *f = factor; + *id = current_id; + } + }) + .or_insert((factor, current_id)); + entry = e_iter.next(); + map_entry = map_iter.next(); + } + Ordering::Greater => { + map_entry = map_iter.next(); + } } } - } else { - break; + _ => { + break; + } } } } diff --git a/libafl/src/schedulers/mod.rs b/libafl/src/schedulers/mod.rs index f340703ba7..870204c98c 100644 --- a/libafl/src/schedulers/mod.rs +++ b/libafl/src/schedulers/mod.rs @@ -35,10 +35,10 @@ use libafl_bolts::{ pub use tuneable::*; use crate::{ + Error, HasMetadata, corpus::{Corpus, CorpusId, HasTestcase, SchedulerTestcaseMetadata, Testcase}, random_corpus_id, state::{HasCorpus, HasRand}, - Error, HasMetadata, }; /// The scheduler also implements `on_remove` and `on_replace` if it implements this stage. diff --git a/libafl/src/schedulers/powersched.rs b/libafl/src/schedulers/powersched.rs index 5bb646398b..7012e29522 100644 --- a/libafl/src/schedulers/powersched.rs +++ b/libafl/src/schedulers/powersched.rs @@ -4,19 +4,19 @@ use alloc::vec::Vec; use core::{hash::Hash, marker::PhantomData, time::Duration}; use libafl_bolts::{ - tuples::{Handle, Handled, MatchName}, Named, + tuples::{Handle, Handled, MatchName}, }; use serde::{Deserialize, Serialize}; use crate::{ + Error, HasMetadata, corpus::{Corpus, CorpusId, HasTestcase, Testcase}, schedulers::{ - on_add_metadata_default, on_evaluation_metadata_default, on_next_metadata_default, - AflScheduler, HasQueueCycles, RemovableScheduler, Scheduler, + AflScheduler, HasQueueCycles, RemovableScheduler, Scheduler, on_add_metadata_default, + on_evaluation_metadata_default, on_next_metadata_default, }, state::HasCorpus, - Error, HasMetadata, }; /// The n fuzz size diff --git a/libafl/src/schedulers/probabilistic_sampling.rs b/libafl/src/schedulers/probabilistic_sampling.rs index dccc63e082..9906af7436 100644 --- a/libafl/src/schedulers/probabilistic_sampling.rs +++ b/libafl/src/schedulers/probabilistic_sampling.rs @@ -9,10 +9,10 @@ use libafl_bolts::rands::Rand; use serde::{Deserialize, Serialize}; use crate::{ + Error, HasMetadata, corpus::{Corpus, CorpusId, Testcase}, schedulers::{RemovableScheduler, Scheduler, TestcaseScore}, state::{HasCorpus, HasRand}, - Error, HasMetadata, }; /// Conduct reservoir sampling (probabilistic sampling) over all corpus elements. @@ -189,12 +189,12 @@ mod tests { use libafl_bolts::rands::StdRand; use crate::{ + Error, corpus::{Corpus, InMemoryCorpus, Testcase}, feedbacks::ConstFeedback, inputs::bytes::BytesInput, schedulers::{ProbabilitySamplingScheduler, Scheduler, TestcaseScore}, state::{HasCorpus, StdState}, - Error, }; const FACTOR: f64 = 1337.0; diff --git a/libafl/src/schedulers/queue.rs b/libafl/src/schedulers/queue.rs index 640228d2a7..aaf8c0efad 100644 --- a/libafl/src/schedulers/queue.rs +++ b/libafl/src/schedulers/queue.rs @@ -3,10 +3,10 @@ use alloc::borrow::ToOwned; use crate::{ + Error, corpus::{Corpus, CorpusId}, schedulers::{HasQueueCycles, RemovableScheduler, Scheduler}, state::HasCorpus, - Error, }; /// Walk the corpus in a queue-like fashion diff --git a/libafl/src/schedulers/testcase_score.rs b/libafl/src/schedulers/testcase_score.rs index 2bbc068554..7b3162a237 100644 --- a/libafl/src/schedulers/testcase_score.rs +++ b/libafl/src/schedulers/testcase_score.rs @@ -4,6 +4,7 @@ use alloc::string::{String, ToString}; use libafl_bolts::{HasLen, HasRefCnt}; use crate::{ + Error, HasMetadata, corpus::{Corpus, SchedulerTestcaseMetadata, Testcase}, feedbacks::MapIndexesMetadata, schedulers::{ @@ -11,7 +12,6 @@ use crate::{ powersched::{BaseSchedule, SchedulerMetadata}, }, state::HasCorpus, - Error, HasMetadata, }; /// Compute the favor factor of a [`Testcase`]. Higher is better. @@ -317,7 +317,7 @@ where Err(e) => { return Err(Error::key_not_found(format!( "{e:?} You have to use Minimizer scheduler with this.", - ))) + ))); } }; diff --git a/libafl/src/schedulers/tuneable.rs b/libafl/src/schedulers/tuneable.rs index fb6dc11c39..cfdb57943c 100644 --- a/libafl/src/schedulers/tuneable.rs +++ b/libafl/src/schedulers/tuneable.rs @@ -9,10 +9,10 @@ use serde::{Deserialize, Serialize}; use super::RemovableScheduler; use crate::{ + Error, HasMetadata, corpus::{Corpus, CorpusId}, schedulers::Scheduler, state::HasCorpus, - Error, HasMetadata, }; #[derive(Default, Clone, Copy, Eq, PartialEq, Debug, Serialize, Deserialize)] diff --git a/libafl/src/schedulers/weighted.rs b/libafl/src/schedulers/weighted.rs index ff652e7456..578211004a 100644 --- a/libafl/src/schedulers/weighted.rs +++ b/libafl/src/schedulers/weighted.rs @@ -7,23 +7,23 @@ use core::{hash::Hash, marker::PhantomData}; use hashbrown::HashMap; use libafl_bolts::{ + Named, rands::Rand, tuples::{Handle, Handled, MatchName}, - Named, }; use serde::{Deserialize, Serialize}; use crate::{ + Error, HasMetadata, corpus::{Corpus, CorpusId, HasTestcase, Testcase}, random_corpus_id, schedulers::{ - on_add_metadata_default, on_evaluation_metadata_default, on_next_metadata_default, + AflScheduler, HasQueueCycles, RemovableScheduler, Scheduler, on_add_metadata_default, + on_evaluation_metadata_default, on_next_metadata_default, powersched::{BaseSchedule, PowerSchedule, SchedulerMetadata}, testcase_score::{CorpusWeightTestcaseScore, TestcaseScore}, - AflScheduler, HasQueueCycles, RemovableScheduler, Scheduler, }, state::{HasCorpus, HasRand}, - Error, HasMetadata, }; /// The Metadata for `WeightedScheduler` diff --git a/libafl/src/stages/afl_stats.rs b/libafl/src/stages/afl_stats.rs index 2efe98e67b..6ab18113c8 100644 --- a/libafl/src/stages/afl_stats.rs +++ b/libafl/src/stages/afl_stats.rs @@ -13,27 +13,27 @@ use std::{ #[cfg(unix)] use libafl_bolts::os::peak_rss_mb_child_processes; use libafl_bolts::{ + Named, core_affinity::CoreId, current_time, tuples::{Handle, Handled, MatchNameRef}, - Named, }; use serde::{Deserialize, Serialize}; #[cfg(feature = "track_hit_feedbacks")] use crate::feedbacks::{CRASH_FEEDBACK_NAME, TIMEOUT_FEEDBACK_NAME}; use crate::{ + Error, HasMetadata, HasNamedMetadata, HasScheduler, corpus::{Corpus, HasCurrentCorpusId, SchedulerTestcaseMetadata, Testcase}, events::{Event, EventFirer}, executors::HasObservers, monitors::stats::{AggregatorOps, UserStats, UserStatsValue}, mutators::Tokens, observers::MapObserver, - schedulers::{minimizer::IsFavoredMetadata, HasQueueCycles}, - stages::{calibrate::UnstableEntriesMetadata, Restartable, Stage}, + schedulers::{HasQueueCycles, minimizer::IsFavoredMetadata}, + stages::{Restartable, Stage, calibrate::UnstableEntriesMetadata}, state::{HasCorpus, HasExecutions, HasImported, HasStartTime, Stoppable}, std::string::ToString, - Error, HasMetadata, HasNamedMetadata, HasScheduler, }; /// AFL++'s default stats update interval diff --git a/libafl/src/stages/calibrate.rs b/libafl/src/stages/calibrate.rs index 2203d8b556..de9199c568 100644 --- a/libafl/src/stages/calibrate.rs +++ b/libafl/src/stages/calibrate.rs @@ -8,15 +8,16 @@ use alloc::{ use core::{fmt::Debug, marker::PhantomData, time::Duration}; use hashbrown::HashSet; -use libafl_bolts::{current_time, impl_serdeany, tuples::Handle, AsIter, Named}; +use libafl_bolts::{AsIter, Named, current_time, impl_serdeany, tuples::Handle}; use num_traits::Bounded; use serde::{Deserialize, Serialize}; use crate::{ + Error, HasMetadata, HasNamedMetadata, corpus::{Corpus, HasCurrentCorpusId, SchedulerTestcaseMetadata}, events::{Event, EventFirer, LogSeverity}, executors::{Executor, ExitKind, HasObservers}, - feedbacks::{map::MapFeedbackMetadata, HasObserverHandle}, + feedbacks::{HasObserverHandle, map::MapFeedbackMetadata}, fuzzer::Evaluator, inputs::Input, monitors::stats::{AggregatorOps, UserStats, UserStatsValue}, @@ -24,7 +25,6 @@ use crate::{ schedulers::powersched::SchedulerMetadata, stages::{Restartable, RetryCountRestartHelper, Stage}, state::{HasCorpus, HasCurrentTestcase, HasExecutions}, - Error, HasMetadata, HasNamedMetadata, }; /// AFL++'s `CAL_CYCLES_FAST` + 1 @@ -294,18 +294,18 @@ where let data = if let Ok(metadata) = testcase.metadata_mut::() { metadata } else { - let depth = if let Some(parent_id) = testcase.parent_id() { - if let Some(parent_metadata) = (*state.corpus().get(parent_id)?) - .borrow() - .metadata_map() - .get::() - { - parent_metadata.depth() + 1 - } else { - 0 + let depth = match testcase.parent_id() { + Some(parent_id) => { + match (*state.corpus().get(parent_id)?) + .borrow() + .metadata_map() + .get::() + { + Some(parent_metadata) => parent_metadata.depth() + 1, + _ => 0, + } } - } else { - 0 + _ => 0, }; testcase.add_metadata(SchedulerTestcaseMetadata::new(depth)); testcase diff --git a/libafl/src/stages/colorization.rs b/libafl/src/stages/colorization.rs index 4af91aaf5e..7c15b35ca2 100644 --- a/libafl/src/stages/colorization.rs +++ b/libafl/src/stages/colorization.rs @@ -7,14 +7,14 @@ use alloc::{ use core::{cmp::Ordering, fmt::Debug, hash::Hash, marker::PhantomData, ops::Range}; use libafl_bolts::{ - generic_hash_std, + Named, generic_hash_std, rands::Rand, tuples::{Handle, Handled}, - Named, }; use serde::{Deserialize, Serialize}; use crate::{ + Error, HasMetadata, HasNamedMetadata, corpus::HasCurrentCorpusId, events::EventFirer, executors::{Executor, HasObservers}, @@ -24,7 +24,6 @@ use crate::{ observers::ObserversTuple, stages::{Restartable, RetryCountRestartHelper, Stage}, state::{HasCorpus, HasCurrentTestcase, HasRand}, - Error, HasMetadata, HasNamedMetadata, }; // Bigger range is better diff --git a/libafl/src/stages/concolic.rs b/libafl/src/stages/concolic.rs index aabd5cb835..15c52675a6 100644 --- a/libafl/src/stages/concolic.rs +++ b/libafl/src/stages/concolic.rs @@ -7,26 +7,27 @@ use alloc::{string::ToString, vec::Vec}; use core::marker::PhantomData; use libafl_bolts::{ - tuples::{Handle, MatchNameRef}, Named, + tuples::{Handle, MatchNameRef}, }; #[cfg(all(feature = "concolic_mutation", feature = "introspection"))] use crate::monitors::stats::PerfFeature; use crate::{ + Error, HasMetadata, HasNamedMetadata, corpus::HasCurrentCorpusId, executors::{Executor, HasObservers}, - observers::{concolic::ConcolicObserver, ObserversTuple}, + observers::{ObserversTuple, concolic::ConcolicObserver}, stages::{Restartable, RetryCountRestartHelper, Stage, TracingStage}, state::{HasCorpus, HasCurrentTestcase, HasExecutions, MaybeHasClientPerfMonitor}, - Error, HasMetadata, HasNamedMetadata, }; #[cfg(feature = "concolic_mutation")] use crate::{ + Evaluator, inputs::HasMutatorBytes, mark_feature_time, observers::concolic::{ConcolicMetadata, SymExpr, SymExprRef}, - start_timer, Evaluator, + start_timer, }; /// Wraps a [`TracingStage`] to add concolic observing. @@ -116,8 +117,8 @@ impl<'a, EM, I, TE, S, Z> ConcolicTracingStage<'a, EM, I, TE, S, Z> { fn generate_mutations(iter: impl Iterator) -> Vec> { use hashbrown::HashMap; use z3::{ - ast::{Ast, Bool, Dynamic, BV}, Config, Context, Solver, Symbol, + ast::{Ast, BV, Bool, Dynamic}, }; fn build_extract<'ctx>( bv: &BV<'ctx>, diff --git a/libafl/src/stages/dump.rs b/libafl/src/stages/dump.rs index 62ff6163be..7b417e8fdd 100644 --- a/libafl/src/stages/dump.rs +++ b/libafl/src/stages/dump.rs @@ -13,11 +13,11 @@ use libafl_bolts::impl_serdeany; use serde::{Deserialize, Serialize}; use crate::{ + Error, HasMetadata, corpus::{Corpus, CorpusId, Testcase}, inputs::Input, stages::{Restartable, Stage}, state::{HasCorpus, HasRand, HasSolutions}, - Error, HasMetadata, }; /// Metadata used to store information about disk dump indexes for names diff --git a/libafl/src/stages/generalization.rs b/libafl/src/stages/generalization.rs index d1d6a289fe..55f4a923ec 100644 --- a/libafl/src/stages/generalization.rs +++ b/libafl/src/stages/generalization.rs @@ -7,13 +7,14 @@ use alloc::{ use core::{fmt::Debug, marker::PhantomData}; use libafl_bolts::{ - tuples::{Handle, Handled}, AsSlice, Named, + tuples::{Handle, Handled}, }; #[cfg(feature = "introspection")] use crate::monitors::stats::PerfFeature; use crate::{ + Error, HasMetadata, HasNamedMetadata, corpus::{Corpus, HasCurrentCorpusId}, executors::{Executor, HasObservers}, feedbacks::map::MapNoveltiesMetadata, @@ -26,7 +27,6 @@ use crate::{ stages::{Restartable, RetryCountRestartHelper, Stage}, start_timer, state::{HasCorpus, HasExecutions, MaybeHasClientPerfMonitor}, - Error, HasMetadata, HasNamedMetadata, }; const MAX_GENERALIZED_LEN: usize = 8192; diff --git a/libafl/src/stages/generation.rs b/libafl/src/stages/generation.rs index ac312f48f1..71e6a097bb 100644 --- a/libafl/src/stages/generation.rs +++ b/libafl/src/stages/generation.rs @@ -7,10 +7,10 @@ use core::marker::PhantomData; use crate::{ + Error, Evaluator, generators::Generator, stages::{Restartable, Stage}, state::HasRand, - Error, Evaluator, }; /// A [`Stage`] that generates a single input via a [`Generator`] and evaluates diff --git a/libafl/src/stages/logics.rs b/libafl/src/stages/logics.rs index 00adc546f1..7decb3a78b 100644 --- a/libafl/src/stages/logics.rs +++ b/libafl/src/stages/logics.rs @@ -3,9 +3,9 @@ use core::marker::PhantomData; use crate::{ + Error, stages::{Restartable, Stage, StageId, StagesTuple}, state::HasNestedStage, - Error, }; /// Progress for nested stages. This merely enters/exits the inner stage's scope. @@ -247,10 +247,9 @@ where state: &mut S, manager: &mut EM, ) -> Result<(), Error> { - if let Some(stages) = &mut self.stages { - stages.perform_all(fuzzer, executor, state, manager) - } else { - Ok(()) + match &mut self.stages { + Some(stages) => stages.perform_all(fuzzer, executor, state, manager), + _ => Ok(()), } } } @@ -303,15 +302,15 @@ mod test { use core::{cell::RefCell, marker::PhantomData}; use libafl_bolts::{ - impl_serdeany, + Error, impl_serdeany, tuples::{tuple_list, tuple_list_type}, - Error, }; use serde::{Deserialize, Serialize}; #[cfg(any(not(feature = "serdeany_autoreg"), miri))] use crate::stages::RetryCountRestartHelper; use crate::{ + HasMetadata, NopFuzzer, events::NopEventManager, executors::test::NopExecutor, stages::{ @@ -319,7 +318,6 @@ mod test { StagesTuple, WhileStage, }, state::{HasCurrentStageId, StdState}, - HasMetadata, NopFuzzer, }; #[derive(Debug)] diff --git a/libafl/src/stages/mod.rs b/libafl/src/stages/mod.rs index 538e54c6f8..77320e898a 100644 --- a/libafl/src/stages/mod.rs +++ b/libafl/src/stages/mod.rs @@ -25,9 +25,8 @@ pub use dump::*; pub use generalization::GeneralizationStage; use hashbrown::HashSet; use libafl_bolts::{ - impl_serdeany, + Named, impl_serdeany, tuples::{HasConstLen, IntoVec}, - Named, }; pub use logics::*; pub use mutational::{MutationalStage, StdMutationalStage}; @@ -47,10 +46,10 @@ pub use unicode::*; pub use verify_timeouts::{TimeoutsToVerify, VerifyTimeoutsStage}; use crate::{ + Error, HasNamedMetadata, corpus::{CorpusId, HasCurrentCorpusId}, events::SendExiting, state::{HasCurrentStageId, HasExecutions, MaybeHasClientPerfMonitor, Stoppable}, - Error, HasNamedMetadata, }; /// Mutational stage is the normal fuzzing stage. @@ -522,7 +521,10 @@ impl ExecutionCountRestartHelper { { self.started_at_execs = None; let _metadata = state.remove_named_metadata::(name); - debug_assert!(_metadata.is_some(), "Called clear_progress, but should_restart was not called before (or did mutational stages get nested?)"); + debug_assert!( + _metadata.is_some(), + "Called clear_progress, but should_restart was not called before (or did mutational stages get nested?)" + ); Ok(()) } } diff --git a/libafl/src/stages/mutational.rs b/libafl/src/stages/mutational.rs index b6900e98b3..4c756fb835 100644 --- a/libafl/src/stages/mutational.rs +++ b/libafl/src/stages/mutational.rs @@ -7,11 +7,12 @@ use alloc::{ }; use core::{marker::PhantomData, num::NonZeroUsize}; -use libafl_bolts::{rands::Rand, Named}; +use libafl_bolts::{Named, rands::Rand}; #[cfg(feature = "introspection")] use crate::monitors::stats::PerfFeature; use crate::{ + Error, HasMetadata, HasNamedMetadata, corpus::{Corpus, CorpusId, HasCurrentCorpusId, Testcase}, fuzzer::Evaluator, inputs::Input, @@ -21,7 +22,6 @@ use crate::{ stages::{Restartable, RetryCountRestartHelper, Stage}, start_timer, state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasRand, MaybeHasClientPerfMonitor}, - Error, HasMetadata, HasNamedMetadata, }; // TODO multi mutators stage diff --git a/libafl/src/stages/power.rs b/libafl/src/stages/power.rs index e19cfe0a9e..0e0ea58b37 100644 --- a/libafl/src/stages/power.rs +++ b/libafl/src/stages/power.rs @@ -11,19 +11,19 @@ use libafl_bolts::Named; #[cfg(feature = "introspection")] use crate::monitors::stats::PerfFeature; use crate::{ + Error, HasMetadata, HasNamedMetadata, corpus::HasCurrentCorpusId, executors::{Executor, HasObservers}, fuzzer::Evaluator, mark_feature_time, mutators::{MutationResult, Mutator}, - schedulers::{testcase_score::CorpusPowerTestcaseScore, TestcaseScore}, + schedulers::{TestcaseScore, testcase_score::CorpusPowerTestcaseScore}, stages::{ - mutational::{MutatedTransform, MutatedTransformPost}, MutationalStage, Restartable, RetryCountRestartHelper, Stage, + mutational::{MutatedTransform, MutatedTransformPost}, }, start_timer, state::{HasCurrentTestcase, HasExecutions, HasRand, MaybeHasClientPerfMonitor}, - Error, HasMetadata, HasNamedMetadata, }; /// The unique id for this stage diff --git a/libafl/src/stages/push/mod.rs b/libafl/src/stages/push/mod.rs index c1b51881ec..a54a13ff80 100644 --- a/libafl/src/stages/push/mod.rs +++ b/libafl/src/stages/push/mod.rs @@ -21,6 +21,7 @@ use libafl_bolts::Named; pub use mutational::StdMutationalPushStage; use crate::{ + Error, EvaluatorObservers, ExecutesInput, ExecutionProcessor, HasMetadata, HasScheduler, common::HasNamedMetadata, corpus::{CorpusId, HasCurrentCorpusId}, events::{EventFirer, EventRestarter, HasEventManagerId, ProgressReporter}, @@ -29,7 +30,6 @@ use crate::{ schedulers::Scheduler, stages::{Restartable, RetryCountRestartHelper, Stage}, state::{HasCorpus, HasExecutions, HasLastReportTime, HasRand}, - Error, EvaluatorObservers, ExecutesInput, ExecutionProcessor, HasMetadata, HasScheduler, }; // The shared state for all [`PushStage`]s diff --git a/libafl/src/stages/push/mutational.rs b/libafl/src/stages/push/mutational.rs index e471e47c44..c4a0940f54 100644 --- a/libafl/src/stages/push/mutational.rs +++ b/libafl/src/stages/push/mutational.rs @@ -14,6 +14,7 @@ use super::{PushStage, PushStageHelper, PushStageSharedState}; #[cfg(feature = "introspection")] use crate::monitors::stats::PerfFeature; use crate::{ + Error, ExecutionProcessor, HasMetadata, HasScheduler, corpus::{Corpus, CorpusId}, events::{EventFirer, ProgressReporter}, executors::ExitKind, @@ -26,7 +27,6 @@ use crate::{ schedulers::Scheduler, start_timer, state::{HasCorpus, HasExecutions, HasLastReportTime, HasRand, MaybeHasClientPerfMonitor}, - Error, ExecutionProcessor, HasMetadata, HasScheduler, }; /// The default maximum number of mutations to perform per input. diff --git a/libafl/src/stages/replay.rs b/libafl/src/stages/replay.rs index cbbb68c92c..8addf86688 100644 --- a/libafl/src/stages/replay.rs +++ b/libafl/src/stages/replay.rs @@ -8,14 +8,14 @@ use alloc::{ use core::marker::PhantomData; use hashbrown::HashSet; -use libafl_bolts::{impl_serdeany, Named}; +use libafl_bolts::{Named, impl_serdeany}; use serde::{Deserialize, Serialize}; use crate::{ + Error, Evaluator, HasMetadata, corpus::{Corpus, CorpusId}, stages::{Restartable, Stage}, state::{HasCorpus, HasSolutions}, - Error, Evaluator, HasMetadata, }; /// Replay all inputs diff --git a/libafl/src/stages/sync.rs b/libafl/src/stages/sync.rs index b9a88b78a3..8a7a1cfe29 100644 --- a/libafl/src/stages/sync.rs +++ b/libafl/src/stages/sync.rs @@ -8,16 +8,16 @@ use core::{marker::PhantomData, time::Duration}; use std::path::{Path, PathBuf}; use libafl_bolts::{ - current_time, + Named, current_time, fs::find_new_files_rec, shmem::{ShMem, ShMemProvider}, - Named, }; use serde::{Deserialize, Serialize}; use crate::{ + Error, HasMetadata, HasNamedMetadata, corpus::{Corpus, CorpusId, HasCurrentCorpusId}, - events::{llmp::LlmpEventConverter, Event, EventConfig, EventFirer}, + events::{Event, EventConfig, EventFirer, llmp::LlmpEventConverter}, executors::{Executor, ExitKind, HasObservers}, fuzzer::{Evaluator, EvaluatorObservers, ExecutionProcessor}, inputs::{Input, InputConverter}, @@ -26,7 +26,6 @@ use crate::{ HasCorpus, HasCurrentTestcase, HasExecutions, HasRand, HasSolutions, MaybeHasClientPerfMonitor, Stoppable, }, - Error, HasMetadata, HasNamedMetadata, }; /// Default name for `SyncFromDiskStage`; derived from AFL++ diff --git a/libafl/src/stages/time_tracker.rs b/libafl/src/stages/time_tracker.rs index 1e6d75df3f..0e95e8af9a 100644 --- a/libafl/src/stages/time_tracker.rs +++ b/libafl/src/stages/time_tracker.rs @@ -1,11 +1,11 @@ //! Stage that wraps another stage and tracks it's execution time in `State` use std::{marker::PhantomData, time::Duration}; -use libafl_bolts::{current_time, Error}; +use libafl_bolts::{Error, current_time}; use crate::{ - stages::{Restartable, Stage}, HasMetadata, + stages::{Restartable, Stage}, }; /// Track an inner Stage's execution time #[derive(Debug)] diff --git a/libafl/src/stages/tmin.rs b/libafl/src/stages/tmin.rs index 01806b1391..2153da064d 100644 --- a/libafl/src/stages/tmin.rs +++ b/libafl/src/stages/tmin.rs @@ -8,9 +8,8 @@ use core::{borrow::BorrowMut, fmt::Debug, hash::Hash, marker::PhantomData}; use ahash::RandomState; use libafl_bolts::{ - generic_hash_std, + HasLen, Named, generic_hash_std, tuples::{Handle, Handled, MatchName, MatchNameRef}, - HasLen, Named, }; use serde::Serialize; @@ -19,6 +18,8 @@ use crate::feedbacks::premature_last_result_err; #[cfg(feature = "introspection")] use crate::monitors::stats::PerfFeature; use crate::{ + Error, ExecutesInput, ExecutionProcessor, HasFeedback, HasMetadata, HasNamedMetadata, + HasScheduler, corpus::{Corpus, HasCurrentCorpusId, Testcase}, events::EventFirer, executors::{ExitKind, HasObservers}, @@ -29,16 +30,14 @@ use crate::{ observers::ObserversTuple, schedulers::RemovableScheduler, stages::{ - mutational::{MutatedTransform, MutatedTransformPost}, ExecutionCountRestartHelper, Restartable, Stage, + mutational::{MutatedTransform, MutatedTransformPost}, }, start_timer, state::{ HasCorpus, HasCurrentTestcase, HasExecutions, HasMaxSize, HasSolutions, MaybeHasClientPerfMonitor, }, - Error, ExecutesInput, ExecutionProcessor, HasFeedback, HasMetadata, HasNamedMetadata, - HasScheduler, }; /// The default corpus entry minimising mutational stage diff --git a/libafl/src/stages/tracing.rs b/libafl/src/stages/tracing.rs index 7430358ba4..457b69c0dc 100644 --- a/libafl/src/stages/tracing.rs +++ b/libafl/src/stages/tracing.rs @@ -11,6 +11,7 @@ use libafl_bolts::Named; #[cfg(feature = "introspection")] use crate::monitors::stats::PerfFeature; use crate::{ + Error, HasNamedMetadata, corpus::HasCurrentCorpusId, executors::{Executor, HasObservers, ShadowExecutor}, inputs::Input, @@ -19,7 +20,6 @@ use crate::{ stages::{Restartable, RetryCountRestartHelper, Stage}, start_timer, state::{HasCorpus, HasCurrentTestcase, HasExecutions, MaybeHasClientPerfMonitor}, - Error, HasNamedMetadata, }; /// A stage that runs a tracer executor diff --git a/libafl/src/stages/tuneable.rs b/libafl/src/stages/tuneable.rs index 4a5e86143a..2aa053d861 100644 --- a/libafl/src/stages/tuneable.rs +++ b/libafl/src/stages/tuneable.rs @@ -9,16 +9,15 @@ use serde::{Deserialize, Serialize}; #[cfg(feature = "introspection")] use crate::monitors::stats::PerfFeature; use crate::{ - mark_feature_time, + Error, Evaluator, HasMetadata, HasNamedMetadata, mark_feature_time, mutators::{MutationResult, Mutator}, nonzero, stages::{ - mutational::{MutatedTransform, MutatedTransformPost, DEFAULT_MUTATIONAL_MAX_ITERATIONS}, ExecutionCountRestartHelper, MutationalStage, Restartable, Stage, + mutational::{DEFAULT_MUTATIONAL_MAX_ITERATIONS, MutatedTransform, MutatedTransformPost}, }, start_timer, state::{HasCurrentTestcase, HasExecutions, HasRand, MaybeHasClientPerfMonitor}, - Error, Evaluator, HasMetadata, HasNamedMetadata, }; #[cfg_attr( diff --git a/libafl/src/stages/unicode.rs b/libafl/src/stages/unicode.rs index 79ff778164..a4aa905110 100644 --- a/libafl/src/stages/unicode.rs +++ b/libafl/src/stages/unicode.rs @@ -4,14 +4,14 @@ use alloc::{collections::VecDeque, rc::Rc, vec::Vec}; use core::marker::PhantomData; use bitvec::{bitvec, vec::BitVec}; -use libafl_bolts::{impl_serdeany, Error}; +use libafl_bolts::{Error, impl_serdeany}; use serde::{Deserialize, Serialize}; use crate::{ + HasMetadata, inputs::{BytesInput, HasTargetBytes}, stages::{Restartable, Stage}, state::{HasCorpus, HasCurrentTestcase}, - HasMetadata, }; /// Metadata which stores the list of pre-computed string-like ranges in the input diff --git a/libafl/src/stages/verify_timeouts.rs b/libafl/src/stages/verify_timeouts.rs index bad419487e..e4b7267491 100644 --- a/libafl/src/stages/verify_timeouts.rs +++ b/libafl/src/stages/verify_timeouts.rs @@ -7,14 +7,14 @@ use core::time::Duration; use std::{cell::RefCell, collections::VecDeque, fmt::Debug, marker::PhantomData, rc::Rc}; use libafl_bolts::Error; -use serde::{de::DeserializeOwned, Deserialize, Serialize}; +use serde::{Deserialize, Serialize, de::DeserializeOwned}; use crate::{ + Evaluator, HasMetadata, executors::{Executor, HasObservers, HasTimeout}, inputs::BytesInput, observers::ObserversTuple, stages::{Restartable, Stage}, - Evaluator, HasMetadata, }; /// Stage that re-runs inputs deemed as timeouts with double the timeout to assert that they are diff --git a/libafl/src/state/mod.rs b/libafl/src/state/mod.rs index 1ed86ebaef..c441c960a8 100644 --- a/libafl/src/state/mod.rs +++ b/libafl/src/state/mod.rs @@ -21,7 +21,7 @@ use libafl_bolts::{ rands::{Rand, StdRand}, serdeany::{NamedSerdeAnyMap, SerdeAnyMap}, }; -use serde::{de::DeserializeOwned, Deserialize, Serialize}; +use serde::{Deserialize, Serialize, de::DeserializeOwned}; mod stack; pub use stack::StageStack; @@ -29,6 +29,7 @@ pub use stack::StageStack; #[cfg(feature = "introspection")] use crate::monitors::stats::ClientPerfStats; use crate::{ + Error, HasMetadata, HasNamedMetadata, corpus::{Corpus, CorpusId, HasCurrentCorpusId, HasTestcase, InMemoryCorpus, Testcase}, events::{Event, EventFirer, LogSeverity}, feedbacks::StateInitializer, @@ -36,7 +37,6 @@ use crate::{ generators::Generator, inputs::{Input, NopInput}, stages::StageId, - Error, HasMetadata, HasNamedMetadata, }; /// The maximum size of a testcase diff --git a/libafl_bolts/Cargo.toml b/libafl_bolts/Cargo.toml index 199c81fdd9..03978dede0 100644 --- a/libafl_bolts/Cargo.toml +++ b/libafl_bolts/Cargo.toml @@ -11,8 +11,8 @@ repository = "https://github.com/AFLplusplus/LibAFL/" readme = "./README.md" license = "MIT OR Apache-2.0" keywords = ["fuzzing", "testing", "security"] -edition = "2021" -rust-version = "1.82" +edition = "2024" +rust-version = "1.85" categories = [ "development-tools::testing", "emulators", diff --git a/libafl_bolts/examples/llmp_test/main.rs b/libafl_bolts/examples/llmp_test/main.rs index 8c5d0777a1..a4a9fa2d84 100644 --- a/libafl_bolts/examples/llmp_test/main.rs +++ b/libafl_bolts/examples/llmp_test/main.rs @@ -12,9 +12,9 @@ use std::{num::NonZeroUsize, thread, time}; use libafl_bolts::llmp::{LlmpBrokerInner, LlmpMsgHookResult}; #[cfg(all(feature = "std", not(target_os = "haiku")))] use libafl_bolts::{ + ClientId, Error, SimpleStderrLogger, llmp::{self, Flags, LlmpHook, Tag}, shmem::{ShMemProvider, StdShMemProvider}, - ClientId, Error, SimpleStderrLogger, }; use tuple_list::tuple_list; diff --git a/libafl_bolts/src/compress.rs b/libafl_bolts/src/compress.rs index e4e261ac0a..3cf189638e 100644 --- a/libafl_bolts/src/compress.rs +++ b/libafl_bolts/src/compress.rs @@ -5,7 +5,7 @@ use alloc::vec::Vec; use core::fmt::Debug; use miniz_oxide::{ - deflate::{compress_to_vec, CompressionLevel}, + deflate::{CompressionLevel, compress_to_vec}, inflate::decompress_to_vec, }; diff --git a/libafl_bolts/src/core_affinity.rs b/libafl_bolts/src/core_affinity.rs index e9dca26af1..b23d705a78 100644 --- a/libafl_bolts/src/core_affinity.rs +++ b/libafl_bolts/src/core_affinity.rs @@ -242,10 +242,10 @@ mod linux { use libc::cpu_set_t; #[cfg(target_os = "freebsd")] use libc::cpuset_t as cpu_set_t; - #[cfg(target_os = "dragonfly")] - use libc::{sched_getaffinity, sched_setaffinity, CPU_ISSET, CPU_SET}; #[cfg(not(target_os = "dragonfly"))] - use libc::{sched_getaffinity, sched_setaffinity, CPU_ISSET, CPU_SET, CPU_SETSIZE}; + use libc::{CPU_ISSET, CPU_SET, CPU_SETSIZE, sched_getaffinity, sched_setaffinity}; + #[cfg(target_os = "dragonfly")] + use libc::{CPU_ISSET, CPU_SET, sched_getaffinity, sched_setaffinity}; #[cfg(target_os = "dragonfly")] const CPU_SETSIZE: libc::c_int = 256; @@ -494,7 +494,7 @@ mod windows { processor: PROCESSOR_RELATIONSHIP, } - extern "system" { + unsafe extern "system" { fn GetLogicalProcessorInformationEx( relationship: u32, data: *mut u8, @@ -595,9 +595,9 @@ mod apple { #[cfg(target_arch = "x86_64")] use libc::{ - integer_t, kern_return_t, mach_msg_type_number_t, pthread_mach_thread_np, pthread_self, - thread_policy_flavor_t, thread_policy_t, thread_t, KERN_SUCCESS, THREAD_AFFINITY_POLICY, - THREAD_AFFINITY_POLICY_COUNT, + KERN_SUCCESS, THREAD_AFFINITY_POLICY, THREAD_AFFINITY_POLICY_COUNT, integer_t, + kern_return_t, mach_msg_type_number_t, pthread_mach_thread_np, pthread_self, + thread_policy_flavor_t, thread_policy_t, thread_t, }; #[cfg(all(target_arch = "aarch64", not(miri)))] use libc::{pthread_set_qos_class_self_np, qos_class_t::QOS_CLASS_USER_INITIATED}; @@ -613,7 +613,7 @@ mod apple { #[cfg(target_arch = "x86_64")] #[link(name = "System", kind = "framework")] - extern "C" { + unsafe extern "C" { fn thread_policy_set( thread: thread_t, flavor: thread_policy_flavor_t, diff --git a/libafl_bolts/src/fs.rs b/libafl_bolts/src/fs.rs index ce362f2bf2..f85e09bff8 100644 --- a/libafl_bolts/src/fs.rs +++ b/libafl_bolts/src/fs.rs @@ -11,7 +11,7 @@ use std::os::unix::prelude::{AsRawFd, RawFd}; #[cfg(feature = "std")] use std::time::SystemTime; use std::{ - fs::{self, remove_file, File, OpenOptions}, + fs::{self, File, OpenOptions, remove_file}, io::{Seek, Write}, path::{Path, PathBuf}, string::String, @@ -138,10 +138,9 @@ impl InputFile { /// Rewinds the file to the beginning #[inline] pub fn rewind(&mut self) -> Result<(), Error> { - if let Err(err) = self.file.rewind() { - Err(err.into()) - } else { - Ok(()) + match self.file.rewind() { + Err(err) => Err(err.into()), + _ => Ok(()), } } } @@ -201,7 +200,7 @@ impl Drop for InputFile { mod test { use std::fs; - use crate::fs::{write_file_atomic, InputFile}; + use crate::fs::{InputFile, write_file_atomic}; #[test] fn test_atomic_file_write() { diff --git a/libafl_bolts/src/lib.rs b/libafl_bolts/src/lib.rs index 7281353058..155f6c0900 100644 --- a/libafl_bolts/src/lib.rs +++ b/libafl_bolts/src/lib.rs @@ -62,9 +62,7 @@ type String = &'static str; /// Good enough for simple errors, for anything else, use the `alloc` feature. #[cfg(not(feature = "alloc"))] macro_rules! format { - ($fmt:literal) => {{ - $fmt - }}; + ($fmt:literal) => {{ $fmt }}; } #[cfg(feature = "std")] @@ -152,7 +150,7 @@ use std::time::{SystemTime, UNIX_EPOCH}; #[cfg(all(unix, feature = "std"))] use std::{ fs::File, - io::{stderr, stdout, Write}, + io::{Write, stderr, stdout}, mem, os::fd::{AsRawFd, FromRawFd, RawFd}, panic, @@ -700,7 +698,7 @@ pub mod prelude { #[cfg(all(any(doctest, test), not(feature = "std")))] /// Provide custom time in `no_std` tests. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn external_current_millis() -> u64 { // TODO: use "real" time here 1000 @@ -910,8 +908,8 @@ pub fn current_time() -> time::Duration { // Define your own `external_current_millis()` function via `extern "C"` // which is linked into the binary and called from here. #[cfg(all(not(any(doctest, test)), not(feature = "std")))] -extern "C" { - //#[no_mangle] +unsafe extern "C" { + //#[unsafe(no_mangle)] fn external_current_millis() -> u64; } @@ -1014,7 +1012,7 @@ pub fn get_thread_id() -> u64 { #[allow(clippy::cast_sign_loss)] /// Return thread ID without using TLS pub fn get_thread_id() -> u64 { - use libc::{syscall, SYS_gettid}; + use libc::{SYS_gettid, syscall}; unsafe { syscall(SYS_gettid) as u64 } } @@ -1367,7 +1365,7 @@ macro_rules! nonnull_raw_mut { #[allow(missing_docs)] // expect somehow breaks here pub mod pybind { - use pyo3::{pymodule, types::PyModule, Bound, PyResult}; + use pyo3::{Bound, PyResult, pymodule, types::PyModule}; #[macro_export] macro_rules! unwrap_me_body { @@ -1518,12 +1516,14 @@ pub unsafe fn vec_init(nb_elts: usize, init_fn: F) -> Result, E> where F: FnOnce(&mut Vec) -> Result<(), E>, { - let mut new_vec: Vec = Vec::with_capacity(nb_elts); - new_vec.set_len(nb_elts); + unsafe { + let mut new_vec: Vec = Vec::with_capacity(nb_elts); + new_vec.set_len(nb_elts); - init_fn(&mut new_vec)?; + init_fn(&mut new_vec)?; - Ok(new_vec) + Ok(new_vec) + } } #[cfg(test)] diff --git a/libafl_bolts/src/llmp.rs b/libafl_bolts/src/llmp.rs index 0794403151..75d1919ad5 100644 --- a/libafl_bolts/src/llmp.rs +++ b/libafl_bolts/src/llmp.rs @@ -72,7 +72,7 @@ use core::{ num::NonZeroUsize, ops::{BitAnd, BitOr, Not}, ptr, slice, - sync::atomic::{fence, AtomicU16, Ordering}, + sync::atomic::{AtomicU16, Ordering, fence}, time::Duration, }; #[cfg(feature = "std")] @@ -97,15 +97,15 @@ use tuple_list::tuple_list; #[cfg(all(unix, not(miri)))] use crate::os::unix_signals::setup_signal_handler; #[cfg(unix)] -use crate::os::unix_signals::{siginfo_t, ucontext_t, Signal, SignalHandler}; +use crate::os::unix_signals::{Signal, SignalHandler, siginfo_t, ucontext_t}; #[cfg(all(windows, feature = "std"))] -use crate::os::windows_exceptions::{setup_ctrl_handler, CtrlHandler}; -#[cfg(feature = "std")] -use crate::{current_time, IP_LOCALHOST}; +use crate::os::windows_exceptions::{CtrlHandler, setup_ctrl_handler}; use crate::{ - shmem::{ShMem, ShMemDescription, ShMemId, ShMemProvider}, ClientId, Error, + shmem::{ShMem, ShMemDescription, ShMemId, ShMemProvider}, }; +#[cfg(feature = "std")] +use crate::{IP_LOCALHOST, current_time}; /// The max number of pages a [`client`] may have mapped that were not yet read by the [`broker`] /// Usually, this value should not exceed `1`, else the broker cannot keep up with the amount of incoming messages. @@ -412,9 +412,11 @@ unsafe fn shmem2page(afl_shmem: &SHM) -> *const LlmpPage { /// Return, if a msg is contained in the current page #[inline] unsafe fn llmp_msg_in_page(page: *const LlmpPage, msg: *const LlmpMsg) -> bool { - /* DBG("llmp_msg_in_page %p within %p-%p\n", msg, page, page + page->size_total); */ - (page as *const u8) < msg as *const u8 - && (page as *const u8).add((*page).size_total) > msg as *const u8 + unsafe { + /* DBG("llmp_msg_in_page %p within %p-%p\n", msg, page, page + page->size_total); */ + (page as *const u8) < msg as *const u8 + && (page as *const u8).add((*page).size_total) > msg as *const u8 + } } /// Align the page to `LLMP_CFG_ALIGNNMENT=64` bytes @@ -530,32 +532,34 @@ fn next_shmem_size(max_alloc: usize) -> usize { /// # Safety /// Will write to the raw SHM page header, should be safe for correct [`ShMem`] implementations unsafe fn llmp_page_init(shmem: &mut SHM, sender_id: ClientId, allow_reinit: bool) { - #[cfg(feature = "llmp_debug")] - log::trace!("llmp_page_init: shmem {:?}", &shmem); - let map_size = shmem.len(); - let page = shmem2page_mut(shmem); - #[cfg(feature = "llmp_debug")] - log::trace!("llmp_page_init: page {:?}", &(*page)); + unsafe { + #[cfg(feature = "llmp_debug")] + log::trace!("llmp_page_init: shmem {:?}", &shmem); + let map_size = shmem.len(); + let page = shmem2page_mut(shmem); + #[cfg(feature = "llmp_debug")] + log::trace!("llmp_page_init: page {:?}", &(*page)); - if !allow_reinit { - assert!( - (*page).magic != PAGE_INITIALIZED_MAGIC, - "Tried to initialize page {page:?} twice (for shmem {shmem:?})" - ); + if !allow_reinit { + assert!( + (*page).magic != PAGE_INITIALIZED_MAGIC, + "Tried to initialize page {page:?} twice (for shmem {shmem:?})" + ); + } + + (*page).magic = PAGE_INITIALIZED_MAGIC; + (*page).sender_id = sender_id; + (*page).current_msg_id.store(0, Ordering::Relaxed); + (*page).max_alloc_size = 0; + // Don't forget to subtract our own header size + (*page).size_total = map_size - LLMP_PAGE_HEADER_LEN; + (*page).size_used = 0; + (*(*page).messages.as_mut_ptr()).message_id = MessageId(0); + (*(*page).messages.as_mut_ptr()).tag = LLMP_TAG_UNSET; + (*page).receivers_joined_count.store(0, Ordering::Release); + (*page).receivers_left_count.store(0, Ordering::Relaxed); + assert!((*page).size_total != 0); } - - (*page).magic = PAGE_INITIALIZED_MAGIC; - (*page).sender_id = sender_id; - (*page).current_msg_id.store(0, Ordering::Relaxed); - (*page).max_alloc_size = 0; - // Don't forget to subtract our own header size - (*page).size_total = map_size - LLMP_PAGE_HEADER_LEN; - (*page).size_used = 0; - (*(*page).messages.as_mut_ptr()).message_id = MessageId(0); - (*(*page).messages.as_mut_ptr()).tag = LLMP_TAG_UNSET; - (*page).receivers_joined_count.store(0, Ordering::Release); - (*page).receivers_left_count.store(0, Ordering::Relaxed); - assert!((*page).size_total != 0); } /// Get the next pointer and make sure it's in the current page, and has enough space. @@ -568,20 +572,22 @@ unsafe fn llmp_next_msg_ptr_checked( last_msg: *const LlmpMsg, alloc_size: usize, ) -> Result<*mut LlmpMsg, Error> { - let page = map.page_mut(); - let map_size = map.shmem.len(); - let msg_begin_min = (page as *const u8).add(size_of::()); - // We still need space for this msg (alloc_size). - let msg_begin_max = (page as *const u8).add(map_size - alloc_size); - let next = llmp_next_msg_ptr(last_msg); - let next_ptr = next as *const u8; - if next_ptr >= msg_begin_min && next_ptr <= msg_begin_max { - Ok(next) - } else { - Err(Error::illegal_state(format!( - "Inconsistent data on sharedmap, or Bug (next_ptr was {:x}, sharedmap page was {:x})", - next_ptr as usize, page as usize - ))) + unsafe { + let page = map.page_mut(); + let map_size = map.shmem.len(); + let msg_begin_min = (page as *const u8).add(size_of::()); + // We still need space for this msg (alloc_size). + let msg_begin_max = (page as *const u8).add(map_size - alloc_size); + let next = llmp_next_msg_ptr(last_msg); + let next_ptr = next as *const u8; + if next_ptr >= msg_begin_min && next_ptr <= msg_begin_max { + Ok(next) + } else { + Err(Error::illegal_state(format!( + "Inconsistent data on sharedmap, or Bug (next_ptr was {:x}, sharedmap page was {:x})", + next_ptr as usize, page as usize + ))) + } } } @@ -593,10 +599,12 @@ unsafe fn llmp_next_msg_ptr_checked( #[inline] #[expect(clippy::cast_ptr_alignment)] unsafe fn llmp_next_msg_ptr(last_msg: *const LlmpMsg) -> *mut LlmpMsg { - /* DBG("llmp_next_msg_ptr %p %lu + %lu\n", last_msg, last_msg->buf_len_padded, sizeof(llmp_message)); */ - (last_msg as *mut u8) - .add(size_of::()) - .add((*last_msg).buf_len_padded as usize) as *mut LlmpMsg + unsafe { + /* DBG("llmp_next_msg_ptr %p %lu + %lu\n", last_msg, last_msg->buf_len_padded, sizeof(llmp_message)); */ + (last_msg as *mut u8) + .add(size_of::()) + .add((*last_msg).buf_len_padded as usize) as *mut LlmpMsg + } } /// Description of a shared map. @@ -650,7 +658,7 @@ impl LlmpMsg { /// This is unsafe if somebody has access to shared mem pages on the system. #[must_use] pub unsafe fn as_slice_unsafe(&self) -> &[u8] { - slice::from_raw_parts(self.buf.as_ptr(), self.buf_len as usize) + unsafe { slice::from_raw_parts(self.buf.as_ptr(), self.buf_len as usize) } } /// Gets the buffer from this message as a mutable slice, with the correct length. @@ -659,7 +667,7 @@ impl LlmpMsg { /// This is unsafe if somebody has access to shared mem pages on the system. #[must_use] pub unsafe fn as_slice_mut_unsafe(&mut self) -> &mut [u8] { - slice::from_raw_parts_mut(self.buf.as_mut_ptr(), self.buf_len as usize) + unsafe { slice::from_raw_parts_mut(self.buf.as_mut_ptr(), self.buf_len as usize) } } /// Gets the buffer from this message as slice, with the correct length. @@ -671,7 +679,9 @@ impl LlmpMsg { if self.in_shmem(map) { Ok(self.as_slice_unsafe()) } else { - Err(Error::illegal_state("Current message not in page. The sharedmap get tampered with or we have a BUG.")) + Err(Error::illegal_state( + "Current message not in page. The sharedmap get tampered with or we have a BUG.", + )) } } } @@ -686,7 +696,9 @@ impl LlmpMsg { if self.in_shmem(map) { Ok(self.as_slice_mut_unsafe()) } else { - Err(Error::illegal_state("Current message not in page. The sharedmap get tampered with or we have a BUG.")) + Err(Error::illegal_state( + "Current message not in page. The sharedmap get tampered with or we have a BUG.", + )) } } } @@ -1006,41 +1018,45 @@ where /// eventually. This function sees if we can deallocate older pages. /// The broker would have informed us by setting the safe_to_unmap-flag. unsafe fn prune_old_pages(&mut self) { - // Exclude the current page by splitting of the last element for this iter - let mut unmap_until_excl = 0; - for map in self.out_shmems.split_last_mut().unwrap().1 { - if (*map.page()).receivers_joined_count.load(Ordering::Acquire) == 0 { - // The broker didn't read this page yet, no more pages to unmap. - break; + unsafe { + // Exclude the current page by splitting of the last element for this iter + let mut unmap_until_excl = 0; + for map in self.out_shmems.split_last_mut().unwrap().1 { + if (*map.page()).receivers_joined_count.load(Ordering::Acquire) == 0 { + // The broker didn't read this page yet, no more pages to unmap. + break; + } + unmap_until_excl += 1; } - unmap_until_excl += 1; - } - if unmap_until_excl == 0 && self.out_shmems.len() > LLMP_CFG_MAX_PENDING_UNREAD_PAGES { - // Looks like nobody is listening to our pages anymore! :/ - // The n old pages have not been touched yet. - // We send one last information to the broker before quitting. - self.send_buf(LLMP_SLOW_RECEIVER_PANIC, &[]).unwrap(); - panic!("The receiver/broker could not process our sent llmp messages in time. Either we're sending too many messages too fast, the broker got stuck, or it crashed. Giving up."); - } + if unmap_until_excl == 0 && self.out_shmems.len() > LLMP_CFG_MAX_PENDING_UNREAD_PAGES { + // Looks like nobody is listening to our pages anymore! :/ + // The n old pages have not been touched yet. + // We send one last information to the broker before quitting. + self.send_buf(LLMP_SLOW_RECEIVER_PANIC, &[]).unwrap(); + panic!( + "The receiver/broker could not process our sent llmp messages in time. Either we're sending too many messages too fast, the broker got stuck, or it crashed. Giving up." + ); + } - // Remove all maps that the broker already mapped, move them to our unused pages cache - self.out_shmems.reserve(unmap_until_excl); - for _ in 0..unmap_until_excl { - let mut map = self.out_shmems.remove(0); + // Remove all maps that the broker already mapped, move them to our unused pages cache + self.out_shmems.reserve(unmap_until_excl); + for _ in 0..unmap_until_excl { + let mut map = self.out_shmems.remove(0); - let page = shmem2page_mut(&mut map.shmem); - assert!( - (*page).magic == PAGE_INITIALIZED_MAGIC, - "LLMP: Tried to free uninitialized shared map at addr {:#}!", - page as usize - ); - (*page).magic = PAGE_DEINITIALIZED_MAGIC; + let page = shmem2page_mut(&mut map.shmem); + assert!( + (*page).magic == PAGE_INITIALIZED_MAGIC, + "LLMP: Tried to free uninitialized shared map at addr {:#}!", + page as usize + ); + (*page).magic = PAGE_DEINITIALIZED_MAGIC; - #[cfg(feature = "llmp_debug")] - log::debug!("Moving unused map to cache: {map:?} {:x?}", map.page()); - self.unused_shmem_cache - .insert(self.unused_shmem_cache.len(), map); + #[cfg(feature = "llmp_debug")] + log::debug!("Moving unused map to cache: {map:?} {:x?}", map.page()); + self.unused_shmem_cache + .insert(self.unused_shmem_cache.len(), map); + } } } @@ -1051,123 +1067,129 @@ where sender_id: ClientId, next_min_shmem_size: usize, ) -> Result, Error> { - // Find a shared map that has been released to reuse, from which all receivers left / finished reading. - let cached_shmem = self - .unused_shmem_cache - .iter() - .position(|cached_shmem| { - let page = &(*shmem2page(&cached_shmem.shmem)); - let receivers_joined_count = page.receivers_joined_count.load(Ordering::Relaxed); - debug_assert_ne!(receivers_joined_count, 0); - let receivers_left_count = page.receivers_left_count.load(Ordering::Relaxed); - debug_assert!(receivers_joined_count >= receivers_left_count); + unsafe { + // Find a shared map that has been released to reuse, from which all receivers left / finished reading. + let cached_shmem = self + .unused_shmem_cache + .iter() + .position(|cached_shmem| { + let page = &(*shmem2page(&cached_shmem.shmem)); + let receivers_joined_count = + page.receivers_joined_count.load(Ordering::Relaxed); + debug_assert_ne!(receivers_joined_count, 0); + let receivers_left_count = page.receivers_left_count.load(Ordering::Relaxed); + debug_assert!(receivers_joined_count >= receivers_left_count); - let ret = receivers_joined_count == receivers_left_count; + let ret = receivers_joined_count == receivers_left_count; - // For proper refcounts, double check that nobody joined in the meantime. - debug_assert_eq!( - receivers_joined_count, - page.receivers_joined_count.load(Ordering::Relaxed), - "Oops, some receiver joined while re-using the page!" - ); + // For proper refcounts, double check that nobody joined in the meantime. + debug_assert_eq!( + receivers_joined_count, + page.receivers_joined_count.load(Ordering::Relaxed), + "Oops, some receiver joined while re-using the page!" + ); - ret - }) - .map(|e| self.unused_shmem_cache.remove(e)); + ret + }) + .map(|e| self.unused_shmem_cache.remove(e)); - if let Some(mut cached_shmem) = cached_shmem { - // We got cached shmems laying around, hand it out, if they are large enough. - if cached_shmem.shmem.len() < next_min_shmem_size { - // This map is too small, we will never need it again (llmp allocation sizes always increase). Drop it, then call this function again.. - #[cfg(feature = "llmp_debug")] - log::info!("Dropping too small shmem {cached_shmem:?}"); - drop(cached_shmem); - self.new_or_unused_shmem(sender_id, next_min_shmem_size) - } else { - #[cfg(feature = "llmp_debug")] - log::info!("Returning cached shmem {cached_shmem:?}"); - unsafe { - llmp_page_init(&mut cached_shmem.shmem, sender_id, false); + match cached_shmem { + Some(mut cached_shmem) => { + // We got cached shmems laying around, hand it out, if they are large enough. + if cached_shmem.shmem.len() < next_min_shmem_size { + // This map is too small, we will never need it again (llmp allocation sizes always increase). Drop it, then call this function again.. + #[cfg(feature = "llmp_debug")] + log::info!("Dropping too small shmem {cached_shmem:?}"); + drop(cached_shmem); + self.new_or_unused_shmem(sender_id, next_min_shmem_size) + } else { + #[cfg(feature = "llmp_debug")] + log::info!("Returning cached shmem {cached_shmem:?}"); + llmp_page_init(&mut cached_shmem.shmem, sender_id, false); + Ok(cached_shmem) + } + } + _ => { + // No cached maps that fit our need, let's allocate a new one. + Ok(LlmpSharedMap::new( + sender_id, + self.shmem_provider.new_shmem(next_min_shmem_size)?, + )) } - Ok(cached_shmem) } - } else { - // No cached maps that fit our need, let's allocate a new one. - Ok(LlmpSharedMap::new( - sender_id, - self.shmem_provider.new_shmem(next_min_shmem_size)?, - )) } } /// listener about it using a EOP message. unsafe fn handle_out_eop(&mut self) -> Result<(), Error> { - #[cfg(all(feature = "llmp_debug", feature = "std"))] - { - #[cfg(debug_assertions)] - let bt = Backtrace::new(); - #[cfg(not(debug_assertions))] - let bt = ""; - let shm = self.out_shmems.last().unwrap(); - log::info!( - "LLMP_DEBUG: End of page reached for map {} with len {}, sending EOP, bt: {:?}", - shm.shmem.id(), - shm.shmem.len(), - bt - ); - } + unsafe { + #[cfg(all(feature = "llmp_debug", feature = "std"))] + { + #[cfg(debug_assertions)] + let bt = Backtrace::new(); + #[cfg(not(debug_assertions))] + let bt = ""; + let shm = self.out_shmems.last().unwrap(); + log::info!( + "LLMP_DEBUG: End of page reached for map {} with len {}, sending EOP, bt: {:?}", + shm.shmem.id(), + shm.shmem.len(), + bt + ); + } + + // If we want to get red if old pages, (client to broker), do that now + if !self.keep_pages_forever { + #[cfg(feature = "llmp_debug")] + log::debug!("LLMP DEBUG: pruning old pages"); + self.prune_old_pages(); + } + + let old_map = self.out_shmems.last_mut().unwrap().page_mut(); + + let next_min_shmem_size = next_shmem_size((*old_map).max_alloc_size); - // If we want to get red if old pages, (client to broker), do that now - if !self.keep_pages_forever { #[cfg(feature = "llmp_debug")] - log::debug!("LLMP DEBUG: pruning old pages"); - self.prune_old_pages(); + log::info!("Next min ShMem Size {next_min_shmem_size}",); + + // Get a new shared page, or reuse an old one, if available. + let mut new_map_shmem = + self.new_or_unused_shmem((*old_map).sender_id, next_min_shmem_size)?; + + let new_map = new_map_shmem.page_mut(); + + #[cfg(feature = "llmp_debug")] + log::info!("got new map at: {new_map:?}"); + + // New maps always start with 0 as message id -> No messages yet. + (*new_map).current_msg_id.store(0, Ordering::Release); + + #[cfg(feature = "llmp_debug")] + log::info!("Setting max alloc size: {:?}", (*old_map).max_alloc_size); + + // Allocations may never shrink: + // keep track of the max message size we allocated across maps. + (*new_map).max_alloc_size = (*old_map).max_alloc_size; + + /* On the old map, place a last message linking to the new map for the clients + * to consume */ + let out = self.alloc_eop()?; + + #[expect(clippy::cast_ptr_alignment)] + let end_of_page_msg = (*out).buf.as_mut_ptr() as *mut LlmpPayloadSharedMapInfo; + (*end_of_page_msg).map_size = new_map_shmem.shmem.len(); + (*end_of_page_msg).shm_str = *new_map_shmem.shmem.id().as_array(); + + /* Send the last msg (the EOP message) on the old buf */ + self.send(out, true)?; + + // Set the new page as current page. + self.out_shmems.push(new_map_shmem); + // We never sent a msg on the new buf */ + self.last_msg_sent = ptr::null_mut(); + + Ok(()) } - - let old_map = self.out_shmems.last_mut().unwrap().page_mut(); - - let next_min_shmem_size = next_shmem_size((*old_map).max_alloc_size); - - #[cfg(feature = "llmp_debug")] - log::info!("Next min ShMem Size {next_min_shmem_size}",); - - // Get a new shared page, or reuse an old one, if available. - let mut new_map_shmem = - self.new_or_unused_shmem((*old_map).sender_id, next_min_shmem_size)?; - - let new_map = new_map_shmem.page_mut(); - - #[cfg(feature = "llmp_debug")] - log::info!("got new map at: {new_map:?}"); - - // New maps always start with 0 as message id -> No messages yet. - (*new_map).current_msg_id.store(0, Ordering::Release); - - #[cfg(feature = "llmp_debug")] - log::info!("Setting max alloc size: {:?}", (*old_map).max_alloc_size); - - // Allocations may never shrink: - // keep track of the max message size we allocated across maps. - (*new_map).max_alloc_size = (*old_map).max_alloc_size; - - /* On the old map, place a last message linking to the new map for the clients - * to consume */ - let out = self.alloc_eop()?; - - #[expect(clippy::cast_ptr_alignment)] - let end_of_page_msg = (*out).buf.as_mut_ptr() as *mut LlmpPayloadSharedMapInfo; - (*end_of_page_msg).map_size = new_map_shmem.shmem.len(); - (*end_of_page_msg).shm_str = *new_map_shmem.shmem.id().as_array(); - - /* Send the last msg (the EOP message) on the old buf */ - self.send(out, true)?; - - // Set the new page as current page. - self.out_shmems.push(new_map_shmem); - // We never sent a msg on the new buf */ - self.last_msg_sent = ptr::null_mut(); - - Ok(()) } /// Allocates the next space on this sender page @@ -1196,11 +1218,13 @@ where /// # Safety /// They msg pointer may no longer be used after `cancel_send` pub unsafe fn cancel_send(&mut self, msg: *mut LlmpMsg) { - /* DBG("Client %d cancels send of msg at %p with tag 0x%X and size %ld", client->id, msg, msg->tag, - * msg->buf_len_padded); */ - let page = self.out_shmems.last_mut().unwrap().page_mut(); - (*msg).tag = LLMP_TAG_UNSET; - (*page).size_used -= (*msg).buf_len_padded as usize + size_of::(); + unsafe { + /* DBG("Client %d cancels send of msg at %p with tag 0x%X and size %ld", client->id, msg, msg->tag, + * msg->buf_len_padded); */ + let page = self.out_shmems.last_mut().unwrap().page_mut(); + (*msg).tag = LLMP_TAG_UNSET; + (*page).size_used -= (*msg).buf_len_padded as usize + size_of::(); + } } /// Shrinks the allocated [`LlmpMsg`] to a given size. @@ -1212,38 +1236,43 @@ where msg: *mut LlmpMsg, shrinked_len: usize, ) -> Result<(), Error> { - if msg.is_null() { - return Err(Error::illegal_argument("Null msg passed to shrink_alloced")); - } else if !self.has_unsent_message { - return Err(Error::illegal_state( - "Called shrink_alloced, but the msg was not unsent", - )); + unsafe { + if msg.is_null() { + return Err(Error::illegal_argument("Null msg passed to shrink_alloced")); + } else if !self.has_unsent_message { + return Err(Error::illegal_state( + "Called shrink_alloced, but the msg was not unsent", + )); + } + + let old_len_padded = (*msg).buf_len_padded; + + let msg_start = msg as usize; + // Make sure the end of our msg is aligned. + let buf_len_padded = llmp_align(msg_start + shrinked_len + size_of::()) + - msg_start + - size_of::(); + + if buf_len_padded > old_len_padded.try_into().unwrap() { + return Err(Error::illegal_argument(format!( + "Cannot shrink msg of size {} (paded: {old_len_padded}) to requested larger size of {shrinked_len} (padded: {buf_len_padded})!", + (*msg).buf_len + ))); + } + + (*msg).buf_len = shrinked_len as u64; + (*msg).buf_len_padded = buf_len_padded as u64; + + let page = self.out_shmems.last_mut().unwrap().page_mut(); + + // Doing this step by step will catch underflows in debug builds :) + (*page).size_used -= old_len_padded as usize; + (*page).size_used += buf_len_padded; + + (*llmp_next_msg_ptr(msg)).tag = LLMP_TAG_UNSET; + + Ok(()) } - - let old_len_padded = (*msg).buf_len_padded; - - let msg_start = msg as usize; - // Make sure the end of our msg is aligned. - let buf_len_padded = llmp_align(msg_start + shrinked_len + size_of::()) - - msg_start - - size_of::(); - - if buf_len_padded > old_len_padded.try_into().unwrap() { - return Err(Error::illegal_argument(format!("Cannot shrink msg of size {} (paded: {old_len_padded}) to requested larger size of {shrinked_len} (padded: {buf_len_padded})!", (*msg).buf_len))); - } - - (*msg).buf_len = shrinked_len as u64; - (*msg).buf_len_padded = buf_len_padded as u64; - - let page = self.out_shmems.last_mut().unwrap().page_mut(); - - // Doing this step by step will catch underflows in debug builds :) - (*page).size_used -= old_len_padded as usize; - (*page).size_used += buf_len_padded; - - (*llmp_next_msg_ptr(msg)).tag = LLMP_TAG_UNSET; - - Ok(()) } /// Allocates a message of the given size, tags it, and sends it off. @@ -1331,12 +1360,14 @@ where /// Only safe if you really really restart the page on everything connected /// No receiver should read from this page at a different location. pub unsafe fn reset(&mut self) { - llmp_page_init( - &mut self.out_shmems.last_mut().unwrap().shmem, - self.id, - true, - ); - self.last_msg_sent = ptr::null_mut(); + unsafe { + llmp_page_init( + &mut self.out_shmems.last_mut().unwrap().shmem, + self.id, + true, + ); + self.last_msg_sent = ptr::null_mut(); + } } /// Reads the stored sender / client id for the given `env_name` (by appending `_CLIENT_ID`). @@ -1355,17 +1386,23 @@ where /// Writes the `id` to an env var #[cfg(feature = "std")] fn client_id_to_env(env_name: &str, id: ClientId) { - env::set_var(format!("{env_name}_CLIENT_ID"), format!("{}", id.0)); + // TODO: Audit that the environment access only happens in single-threaded code. + unsafe { env::set_var(format!("{env_name}_CLIENT_ID"), format!("{}", id.0)) }; } /// Store the info to this sender to env. /// A new client can reattach to it using [`LlmpSender::on_existing_from_env()`]. + /// + /// # Safety + /// Writes to env variables and may only be done single-threaded. #[cfg(feature = "std")] - pub fn to_env(&self, env_name: &str) -> Result<(), Error> { - let current_out_shmem = self.out_shmems.last().unwrap(); - current_out_shmem.shmem.write_to_env(env_name)?; - Self::client_id_to_env(env_name, self.id); - unsafe { current_out_shmem.msg_to_env(self.last_msg_sent, env_name) } + pub unsafe fn to_env(&self, env_name: &str) -> Result<(), Error> { + unsafe { + let current_out_shmem = self.out_shmems.last().unwrap(); + current_out_shmem.shmem.write_to_env(env_name)?; + Self::client_id_to_env(env_name, self.id); + current_out_shmem.msg_to_env(self.last_msg_sent, env_name) + } } /// Waits for this sender to be save to unmap. @@ -1405,7 +1442,9 @@ where /// # Safety /// If this method is called, the page may be unmapped before it is read by any receiver. pub unsafe fn mark_safe_to_unmap(&mut self) { - (*self.out_shmems.last_mut().unwrap().page_mut()).receiver_joined(); + unsafe { + (*self.out_shmems.last_mut().unwrap().page_mut()).receiver_joined(); + } } /// Intern: Special allocation function for `EOP` messages (and nothing else!) @@ -1413,116 +1452,127 @@ where /// So if [`alloc_next`] fails, create new page if necessary, use this function, /// place `EOP`, commit `EOP`, reset, alloc again on the new space. unsafe fn alloc_eop(&mut self) -> Result<*mut LlmpMsg, Error> { - let map = self.out_shmems.last_mut().unwrap(); - let page = map.page_mut(); - let last_msg = self.last_msg_sent; - assert!((*page).size_used + EOP_MSG_SIZE <= (*page).size_total, + unsafe { + let map = self.out_shmems.last_mut().unwrap(); + let page = map.page_mut(); + let last_msg = self.last_msg_sent; + assert!( + (*page).size_used + EOP_MSG_SIZE <= (*page).size_total, "PROGRAM ABORT : BUG: EOP does not fit in page! page {page:?}, size_current {:?}, size_total {:?}", - &raw const (*page).size_used, &raw const (*page).size_total); + &raw const (*page).size_used, + &raw const (*page).size_total + ); - let ret: *mut LlmpMsg = if last_msg.is_null() { - (*page).messages.as_mut_ptr() - } else { - llmp_next_msg_ptr_checked(map, last_msg, EOP_MSG_SIZE)? - }; - assert!( - (*ret).tag != LLMP_TAG_UNINITIALIZED, - "Did not call send() on last message!" - ); + let ret: *mut LlmpMsg = if last_msg.is_null() { + (*page).messages.as_mut_ptr() + } else { + llmp_next_msg_ptr_checked(map, last_msg, EOP_MSG_SIZE)? + }; + assert!( + (*ret).tag != LLMP_TAG_UNINITIALIZED, + "Did not call send() on last message!" + ); - (*ret).buf_len = size_of::() as u64; + (*ret).buf_len = size_of::() as u64; - // We don't need to pad the EOP message: it'll always be the last in this page. - (*ret).buf_len_padded = (*ret).buf_len; - (*ret).message_id = if last_msg.is_null() { - MessageId(1) - } else { - MessageId((*last_msg).message_id.0 + 1) - }; - (*ret).tag = LLMP_TAG_END_OF_PAGE; - (*page).size_used += EOP_MSG_SIZE; - Ok(ret) + // We don't need to pad the EOP message: it'll always be the last in this page. + (*ret).buf_len_padded = (*ret).buf_len; + (*ret).message_id = if last_msg.is_null() { + MessageId(1) + } else { + MessageId((*last_msg).message_id.0 + 1) + }; + (*ret).tag = LLMP_TAG_END_OF_PAGE; + (*page).size_used += EOP_MSG_SIZE; + Ok(ret) + } } /// Intern: Will return a ptr to the next msg buf, or None if map is full. /// Never call [`alloc_next`] without either sending or cancelling the last allocated message for this page! /// There can only ever be up to one message allocated per page at each given time. unsafe fn alloc_next_if_space(&mut self, buf_len: usize) -> Option<*mut LlmpMsg> { - let map = self.out_shmems.last_mut().unwrap(); - let page = map.page_mut(); - let last_msg = self.last_msg_sent; + unsafe { + let map = self.out_shmems.last_mut().unwrap(); + let page = map.page_mut(); + let last_msg = self.last_msg_sent; - assert!( - !self.has_unsent_message, - "Called alloc without calling send inbetween" - ); + assert!( + !self.has_unsent_message, + "Called alloc without calling send inbetween" + ); - #[cfg(feature = "llmp_debug")] - log::info!( - "Allocating {} bytes on page {:?} / map {:?} (last msg: {:?})", - buf_len, - page, - &map.shmem.id().as_str(), - last_msg - ); - - let msg_start = (*page).messages.as_mut_ptr() as usize + (*page).size_used; - - // Make sure the end of our msg is aligned. - let buf_len_padded = llmp_align(msg_start + buf_len + size_of::()) - - msg_start - - size_of::(); - - #[cfg(feature = "llmp_debug")] - log::trace!( - "{page:?} {:?} size_used={:x} buf_len_padded={:x} EOP_MSG_SIZE={:x} size_total={}", - &(*page), - (*page).size_used, - buf_len_padded, - EOP_MSG_SIZE, - (*page).size_total - ); - - // For future allocs, keep track of the maximum (aligned) alloc size we used - (*page).max_alloc_size = max( - (*page).max_alloc_size, - size_of::() + buf_len_padded, - ); - - // We need enough space for the current page size_used + payload + padding - if (*page).size_used + size_of::() + buf_len_padded + EOP_MSG_SIZE - > (*page).size_total - { #[cfg(feature = "llmp_debug")] - log::info!("LLMP: Page full."); + log::info!( + "Allocating {} bytes on page {:?} / map {:?} (last msg: {:?})", + buf_len, + page, + &map.shmem.id().as_str(), + last_msg + ); - /* We're full. */ - return None; + let msg_start = (*page).messages.as_mut_ptr() as usize + (*page).size_used; + + // Make sure the end of our msg is aligned. + let buf_len_padded = llmp_align(msg_start + buf_len + size_of::()) + - msg_start + - size_of::(); + + #[cfg(feature = "llmp_debug")] + log::trace!( + "{page:?} {:?} size_used={:x} buf_len_padded={:x} EOP_MSG_SIZE={:x} size_total={}", + &(*page), + (*page).size_used, + buf_len_padded, + EOP_MSG_SIZE, + (*page).size_total + ); + + // For future allocs, keep track of the maximum (aligned) alloc size we used + (*page).max_alloc_size = max( + (*page).max_alloc_size, + size_of::() + buf_len_padded, + ); + + // We need enough space for the current page size_used + payload + padding + if (*page).size_used + size_of::() + buf_len_padded + EOP_MSG_SIZE + > (*page).size_total + { + #[cfg(feature = "llmp_debug")] + log::info!("LLMP: Page full."); + + /* We're full. */ + return None; + } + + let ret = msg_start as *mut LlmpMsg; + + /* We need to start with 1 for ids, as current message id is initialized + * with 0... */ + (*ret).message_id = if last_msg.is_null() { + MessageId(1) + } else if (*page).current_msg_id.load(Ordering::Relaxed) == (*last_msg).message_id.0 { + MessageId((*last_msg).message_id.0 + 1) + } else { + /* Oops, wrong usage! */ + panic!( + "BUG: The current message never got committed using send! (page->current_msg_id {:?}, last_msg->message_id: {:?})", + &raw const (*page).current_msg_id, + (*last_msg).message_id + ); + }; + + (*ret).buf_len = buf_len as u64; + (*ret).buf_len_padded = buf_len_padded as u64; + (*page).size_used += size_of::() + buf_len_padded; + + (*llmp_next_msg_ptr(ret)).tag = LLMP_TAG_UNSET; + (*ret).tag = LLMP_TAG_UNINITIALIZED; + + self.has_unsent_message = true; + + Some(ret) } - - let ret = msg_start as *mut LlmpMsg; - - /* We need to start with 1 for ids, as current message id is initialized - * with 0... */ - (*ret).message_id = if last_msg.is_null() { - MessageId(1) - } else if (*page).current_msg_id.load(Ordering::Relaxed) == (*last_msg).message_id.0 { - MessageId((*last_msg).message_id.0 + 1) - } else { - /* Oops, wrong usage! */ - panic!("BUG: The current message never got committed using send! (page->current_msg_id {:?}, last_msg->message_id: {:?})", &raw const (*page).current_msg_id, (*last_msg).message_id); - }; - - (*ret).buf_len = buf_len as u64; - (*ret).buf_len_padded = buf_len_padded as u64; - (*page).size_used += size_of::() + buf_len_padded; - - (*llmp_next_msg_ptr(ret)).tag = LLMP_TAG_UNSET; - (*ret).tag = LLMP_TAG_UNINITIALIZED; - - self.has_unsent_message = true; - - Some(ret) } /// Commit the message last allocated by [`alloc_next`] to the queue. @@ -1531,44 +1581,46 @@ where /// If `overwrite_client_id` is `false`, the message's `sender` won't be touched (for broker forwarding) #[inline(never)] // Not inlined to make cpu-level reodering (hopefully?) improbable unsafe fn send(&mut self, msg: *mut LlmpMsg, overwrite_client_id: bool) -> Result<(), Error> { - // log::info!("Sending msg {:?}", msg); + unsafe { + // log::info!("Sending msg {:?}", msg); - assert!(self.last_msg_sent != msg, "Message sent twice!"); - assert!( - (*msg).tag != LLMP_TAG_UNSET, - "No tag set on message with id {:?}", - (*msg).message_id - ); - // A client gets the sender id assigned to by the broker during the initial handshake. - if overwrite_client_id { - (*msg).sender = self.id; + assert!(self.last_msg_sent != msg, "Message sent twice!"); + assert!( + (*msg).tag != LLMP_TAG_UNSET, + "No tag set on message with id {:?}", + (*msg).message_id + ); + // A client gets the sender id assigned to by the broker during the initial handshake. + if overwrite_client_id { + (*msg).sender = self.id; + } + let page = self.out_shmems.last_mut().unwrap().page_mut(); + if msg.is_null() || !llmp_msg_in_page(page, msg) { + return Err(Error::unknown(format!( + "Llmp Message {msg:?} is null or not in current page" + ))); + } + + let mid = (*page).current_msg_id.load(Ordering::Relaxed) + 1; + (*msg).message_id.0 = mid; + + // Make sure all things have been written to the page, and commit the message to the page + (*page) + .current_msg_id + .store((*msg).message_id.0, Ordering::Release); + + self.last_msg_sent = msg; + self.has_unsent_message = false; + + log::debug!( + "[{} - {:#x}] Send message with id {}", + self.id.0, + ptr::from_ref::(self) as u64, + mid + ); + + Ok(()) } - let page = self.out_shmems.last_mut().unwrap().page_mut(); - if msg.is_null() || !llmp_msg_in_page(page, msg) { - return Err(Error::unknown(format!( - "Llmp Message {msg:?} is null or not in current page" - ))); - } - - let mid = (*page).current_msg_id.load(Ordering::Relaxed) + 1; - (*msg).message_id.0 = mid; - - // Make sure all things have been written to the page, and commit the message to the page - (*page) - .current_msg_id - .store((*msg).message_id.0, Ordering::Release); - - self.last_msg_sent = msg; - self.has_unsent_message = false; - - log::debug!( - "[{} - {:#x}] Send message with id {}", - self.id.0, - ptr::from_ref::(self) as u64, - mid - ); - - Ok(()) } /// Describe this [`LlmpClient`] in a way that it can be restored later, using [`Self::on_existing_from_description`]. @@ -1653,122 +1705,126 @@ where /// Will *not* update `self.last_msg_time`. #[inline(never)] unsafe fn recv(&mut self) -> Result, Error> { - /* DBG("recv %p %p\n", page, last_msg); */ - let page = self.current_recv_shmem.page_mut(); - let last_msg = self.last_msg_recvd; + unsafe { + /* DBG("recv %p %p\n", page, last_msg); */ + let page = self.current_recv_shmem.page_mut(); + let last_msg = self.last_msg_recvd; - let (current_msg_id, loaded) = - if !last_msg.is_null() && self.highest_msg_id > (*last_msg).message_id { - // read the msg_id from cache - (self.highest_msg_id, false) + let (current_msg_id, loaded) = + if !last_msg.is_null() && self.highest_msg_id > (*last_msg).message_id { + // read the msg_id from cache + (self.highest_msg_id, false) + } else { + // read the msg_id from shared map + let current_msg_id = (*page).current_msg_id.load(Ordering::Relaxed); + self.highest_msg_id = MessageId(current_msg_id); + (MessageId(current_msg_id), true) + }; + + // Read the message from the page + let ret = if current_msg_id.0 == 0 { + /* No messages yet */ + None + } else if last_msg.is_null() { + /* We never read a message from this queue. Return first. */ + fence(Ordering::Acquire); + Some((*page).messages.as_mut_ptr()) + } else if (*last_msg).message_id == current_msg_id { + /* Oops! No new message! */ + None } else { - // read the msg_id from shared map - let current_msg_id = (*page).current_msg_id.load(Ordering::Relaxed); - self.highest_msg_id = MessageId(current_msg_id); - (MessageId(current_msg_id), true) + if loaded { + // we read a higher id from this page, fetch. + fence(Ordering::Acquire); + } + // We don't know how big the msg wants to be, assert at least the header has space. + Some(llmp_next_msg_ptr_checked( + &mut self.current_recv_shmem, + last_msg, + size_of::(), + )?) }; - // Read the message from the page - let ret = if current_msg_id.0 == 0 { - /* No messages yet */ - None - } else if last_msg.is_null() { - /* We never read a message from this queue. Return first. */ - fence(Ordering::Acquire); - Some((*page).messages.as_mut_ptr()) - } else if (*last_msg).message_id == current_msg_id { - /* Oops! No new message! */ - None - } else { - if loaded { - // we read a higher id from this page, fetch. - fence(Ordering::Acquire); - } - // We don't know how big the msg wants to be, assert at least the header has space. - Some(llmp_next_msg_ptr_checked( - &mut self.current_recv_shmem, - last_msg, - size_of::(), - )?) - }; - - // Let's see what we got. - if let Some(msg) = ret { - if !(*msg).in_shmem(&mut self.current_recv_shmem) { - return Err(Error::illegal_state("Unexpected message in map (out of map bounds) - buggy client or tampered shared map detected!")); - } - - log::debug!( - "[{} - {:#x}] Received message with ID {}...", - self.id.0, - ptr::from_ref::(self) as u64, - (*msg).message_id.0 - ); - - // Handle special, LLMP internal, messages. - match (*msg).tag { - LLMP_TAG_UNSET => panic!( - "BUG: Read unallocated msg (tag was {:?} - msg header: {:?}", - LLMP_TAG_UNSET, - &(*msg) - ), - LLMP_TAG_EXITING => { - // The other side is done. - assert_eq!((*msg).buf_len, 0); - return Err(Error::shutting_down()); + // Let's see what we got. + if let Some(msg) = ret { + if !(*msg).in_shmem(&mut self.current_recv_shmem) { + return Err(Error::illegal_state( + "Unexpected message in map (out of map bounds) - buggy client or tampered shared map detected!", + )); } - LLMP_TAG_END_OF_PAGE => { - log::debug!("Received end of page, allocating next"); - // Handle end of page - assert!( - (*msg).buf_len >= size_of::() as u64, - "Illegal message length for EOP (is {}/{}, expected {})", - (*msg).buf_len, - (*msg).buf_len_padded, - size_of::() - ); - #[expect(clippy::cast_ptr_alignment)] - let pageinfo = (*msg).buf.as_mut_ptr() as *mut LlmpPayloadSharedMapInfo; + log::debug!( + "[{} - {:#x}] Received message with ID {}...", + self.id.0, + ptr::from_ref::(self) as u64, + (*msg).message_id.0 + ); - /* The pageinfo points to the map we're about to unmap. - Copy the contents first to be safe (probably fine in rust either way). */ - let pageinfo_cpy = *pageinfo; + // Handle special, LLMP internal, messages. + match (*msg).tag { + LLMP_TAG_UNSET => panic!( + "BUG: Read unallocated msg (tag was {:?} - msg header: {:?}", + LLMP_TAG_UNSET, + &(*msg) + ), + LLMP_TAG_EXITING => { + // The other side is done. + assert_eq!((*msg).buf_len, 0); + return Err(Error::shutting_down()); + } + LLMP_TAG_END_OF_PAGE => { + log::debug!("Received end of page, allocating next"); + // Handle end of page + assert!( + (*msg).buf_len >= size_of::() as u64, + "Illegal message length for EOP (is {}/{}, expected {})", + (*msg).buf_len, + (*msg).buf_len_padded, + size_of::() + ); - // Set last msg we received to null (as the map may no longer exist) - self.last_msg_recvd = ptr::null(); - self.highest_msg_id = MessageId(0); + #[expect(clippy::cast_ptr_alignment)] + let pageinfo = (*msg).buf.as_mut_ptr() as *mut LlmpPayloadSharedMapInfo; - // Mark the old page save to remap. - (*page).receiver_left(); + /* The pageinfo points to the map we're about to unmap. + Copy the contents first to be safe (probably fine in rust either way). */ + let pageinfo_cpy = *pageinfo; - // Map the new page. The old one should be unmapped by Drop - self.current_recv_shmem = - LlmpSharedMap::existing(self.shmem_provider.shmem_from_id_and_size( - ShMemId::from_array(&pageinfo_cpy.shm_str), - pageinfo_cpy.map_size, - )?); - let new_page = self.current_recv_shmem.page_mut(); + // Set last msg we received to null (as the map may no longer exist) + self.last_msg_recvd = ptr::null(); + self.highest_msg_id = MessageId(0); - // Mark the old page as save to remap (it's mapped by us, the receiver, now) - (*new_page).receiver_joined(); + // Mark the old page save to remap. + (*page).receiver_left(); - #[cfg(feature = "llmp_debug")] - log::info!( - "LLMP_DEBUG: Got a new recv map {} with len {:?}", - self.current_recv_shmem.shmem.id(), - self.current_recv_shmem.shmem.len() - ); - // After we mapped the new page, return the next message, if available - return self.recv(); + // Map the new page. The old one should be unmapped by Drop + self.current_recv_shmem = + LlmpSharedMap::existing(self.shmem_provider.shmem_from_id_and_size( + ShMemId::from_array(&pageinfo_cpy.shm_str), + pageinfo_cpy.map_size, + )?); + let new_page = self.current_recv_shmem.page_mut(); + + // Mark the old page as save to remap (it's mapped by us, the receiver, now) + (*new_page).receiver_joined(); + + #[cfg(feature = "llmp_debug")] + log::info!( + "LLMP_DEBUG: Got a new recv map {} with len {:?}", + self.current_recv_shmem.shmem.id(), + self.current_recv_shmem.shmem.len() + ); + // After we mapped the new page, return the next message, if available + return self.recv(); + } + _ => (), } - _ => (), - } - // Store the last msg for next time - self.last_msg_recvd = msg; + // Store the last msg for next time + self.last_msg_recvd = msg; + } + Ok(ret) } - Ok(ret) } /// Blocks/spins until the next message gets posted to the page, @@ -1776,25 +1832,27 @@ where /// # Safety /// Returns a raw ptr, on the recv map. Should be safe in general pub unsafe fn recv_blocking(&mut self) -> Result<*mut LlmpMsg, Error> { - let mut current_msg_id = MessageId(0); - let page = self.current_recv_shmem.page_mut(); - let last_msg = self.last_msg_recvd; - if !last_msg.is_null() { - assert!( - (*last_msg).tag != LLMP_TAG_END_OF_PAGE || llmp_msg_in_page(page, last_msg), - "BUG: full page passed to await_message_blocking or reset failed" - ); + unsafe { + let mut current_msg_id = MessageId(0); + let page = self.current_recv_shmem.page_mut(); + let last_msg = self.last_msg_recvd; + if !last_msg.is_null() { + assert!( + (*last_msg).tag != LLMP_TAG_END_OF_PAGE || llmp_msg_in_page(page, last_msg), + "BUG: full page passed to await_message_blocking or reset failed" + ); - current_msg_id = (*last_msg).message_id; - } - loop { - if (*page).current_msg_id.load(Ordering::Relaxed) != current_msg_id.0 { - return match self.recv()? { - Some(msg) => Ok(msg), - None => panic!("BUG: blocking llmp message should never be NULL"), - }; + current_msg_id = (*last_msg).message_id; + } + loop { + if (*page).current_msg_id.load(Ordering::Relaxed) != current_msg_id.0 { + return match self.recv()? { + Some(msg) => Ok(msg), + None => panic!("BUG: blocking llmp message should never be NULL"), + }; + } + hint::spin_loop(); } - hint::spin_loop(); } } @@ -1879,10 +1937,15 @@ where { /// Store the info to this receiver to env. /// A new client can reattach to it using [`LlmpReceiver::on_existing_from_env()`] + /// + /// # Safety + /// Alters the env. Should only be called from a single thread. #[cfg(feature = "std")] - pub fn to_env(&self, env_name: &str) -> Result<(), Error> { + pub unsafe fn to_env(&self, env_name: &str) -> Result<(), Error> { let current_out_shmem = &self.current_recv_shmem; - current_out_shmem.shmem.write_to_env(env_name)?; + unsafe { + current_out_shmem.shmem.write_to_env(env_name)?; + } unsafe { current_out_shmem.msg_to_env(self.last_msg_recvd, env_name) } } @@ -1976,14 +2039,14 @@ where /// # Safety /// The unsafe page pointer is obviously unsafe. pub unsafe fn page_mut(&mut self) -> *mut LlmpPage { - shmem2page_mut(&mut self.shmem) + unsafe { shmem2page_mut(&mut self.shmem) } } /// Get the unsafe ptr to this page, situated on the shared map /// # Safety /// The unsafe page pointer is obviously unsafe. pub unsafe fn page(&self) -> *const LlmpPage { - shmem2page(&self.shmem) + unsafe { shmem2page(&self.shmem) } } /// Gets the offset of a message on this here page. @@ -1993,15 +2056,17 @@ where /// This dereferences msg, make sure to pass a proper pointer to it. #[expect(clippy::cast_sign_loss)] pub unsafe fn msg_to_offset(&self, msg: *const LlmpMsg) -> Result { - let page = self.page(); - if llmp_msg_in_page(page, msg) { - // Cast both sides to u8 arrays, get the offset, then cast the return isize to u64 - Ok((msg as *const u8).offset_from((*page).messages.as_ptr() as *const u8) as u64) - } else { - Err(Error::illegal_argument(format!( - "Message (0x{:X}) not in page (0x{:X})", - page as u64, msg as u64 - ))) + unsafe { + let page = self.page(); + if llmp_msg_in_page(page, msg) { + // Cast both sides to u8 arrays, get the offset, then cast the return isize to u64 + Ok((msg as *const u8).offset_from((*page).messages.as_ptr() as *const u8) as u64) + } else { + Err(Error::illegal_argument(format!( + "Message (0x{:X}) not in page (0x{:X})", + page as u64, msg as u64 + ))) + } } } @@ -2023,12 +2088,16 @@ where #[cfg(feature = "std")] pub unsafe fn msg_to_env(&self, msg: *const LlmpMsg, map_env_name: &str) -> Result<(), Error> { if msg.is_null() { - env::set_var(format!("{map_env_name}_OFFSET"), _NULL_ENV_STR); + // TODO: Audit that the environment access only happens in single-threaded code. + unsafe { env::set_var(format!("{map_env_name}_OFFSET"), _NULL_ENV_STR) }; } else { - env::set_var( - format!("{map_env_name}_OFFSET"), - format!("{}", self.msg_to_offset(msg)?), - ); + // TODO: Audit that the environment access only happens in single-threaded code. + unsafe { + env::set_var( + format!("{map_env_name}_OFFSET"), + format!("{}", self.msg_to_offset(msg)?), + ); + }; } Ok(()) } @@ -2640,115 +2709,13 @@ where #[expect(clippy::cast_ptr_alignment)] #[expect(clippy::too_many_lines)] unsafe fn handle_new_msgs(&mut self, client_id: ClientId) -> Result { - let mut new_messages = false; + unsafe { + let mut new_messages = false; - // TODO: We could memcpy a range of pending messages, instead of one by one. - loop { - // log::trace!("{:#?}", self.llmp_clients); - let msg = { - let pos = if (client_id.0 as usize) < self.inner.llmp_clients.len() - && self.inner.llmp_clients[client_id.0 as usize].id == client_id - { - // Fast path when no client before this one was removed - client_id.0 as usize - } else { - self.inner - .llmp_clients - .binary_search_by_key(&client_id, |x| x.id) - .unwrap_or_else(|_| { - panic!( - "Fatal error, client ID {client_id:?} not found in llmp_clients." - ) - }) - }; - let client = &mut self.inner.llmp_clients[pos]; - match client.recv()? { - None => { - // We're done handling this client - #[cfg(feature = "std")] - if new_messages { - // set the recv time - // We don't do that in recv() to keep calls to `current_time` to a minimum. - self.inner.llmp_clients[pos].last_msg_time = current_time(); - } - return Ok(new_messages); - } - Some(msg) => msg, - } - }; - // We got a new message - new_messages = true; - - match (*msg).tag { - // first, handle the special, llmp-internal messages - LLMP_SLOW_RECEIVER_PANIC => { - return Err(Error::unknown(format!("The broker was too slow to handle messages of client {client_id:?} in time, so it quit. Either the client sent messages too fast, or we (the broker) got stuck!"))); - } - LLMP_TAG_CLIENT_EXIT => { - let msg_buf_len_padded = (*msg).buf_len_padded; - if (*msg).buf_len < size_of::() as u64 { - log::info!("Ignoring broken CLIENT_EXIT msg due to incorrect size. Expected {} but got {}", - msg_buf_len_padded, - size_of::() - ); - #[cfg(not(feature = "std"))] - return Err(Error::unknown(format!("Broken CLIENT_EXIT msg with incorrect size received. Expected {} but got {}", - msg_buf_len_padded, - size_of::() - ))); - } - let exitinfo = (*msg).buf.as_mut_ptr() as *mut LlmpClientExitInfo; - let client_id = ClientId((*exitinfo).client_id); - log::info!("Client exit message received!, we are removing clients whose client_group_id is {:#?}", client_id); - - self.inner.clients_to_remove.push(client_id); - } - LLMP_TAG_NEW_SHM_CLIENT => { - /* This client informs us about yet another new client - add it to the list! Also, no need to forward this msg. */ - let msg_buf_len_padded = (*msg).buf_len_padded; - if (*msg).buf_len < size_of::() as u64 { - log::info!("Ignoring broken CLIENT_ADDED msg due to incorrect size. Expected {} but got {}", - msg_buf_len_padded, - size_of::() - ); - #[cfg(not(feature = "std"))] - return Err(Error::unknown(format!("Broken CLIENT_ADDED msg with incorrect size received. Expected {} but got {}", - msg_buf_len_padded, - size_of::() - ))); - } - let pageinfo = (*msg).buf.as_mut_ptr() as *mut LlmpPayloadSharedMapInfo; - match self.inner.shmem_provider.shmem_from_id_and_size( - ShMemId::from_array(&(*pageinfo).shm_str), - (*pageinfo).map_size, - ) { - Ok(new_shmem) => { - let mut new_page = LlmpSharedMap::existing(new_shmem); - new_page.mark_safe_to_unmap(); - - let _new_client = self.inner.add_client(LlmpReceiver { - id: ClientId(0), // will be auto-filled - current_recv_shmem: new_page, - last_msg_recvd: ptr::null_mut(), - shmem_provider: self.inner.shmem_provider.clone(), - highest_msg_id: MessageId(0), - // We don't know the last received time, just assume the current time. - #[cfg(feature = "std")] - last_msg_time: current_time(), - }); - } - Err(e) => { - log::info!("Error adding client! Ignoring: {e:?}"); - #[cfg(not(feature = "std"))] - return Err(Error::unknown(format!( - "Error adding client! PANIC! {e:?}" - ))); - } - } - } - // handle all other messages - _ => { + // TODO: We could memcpy a range of pending messages, instead of one by one. + loop { + // log::trace!("{:#?}", self.llmp_clients); + let msg = { let pos = if (client_id.0 as usize) < self.inner.llmp_clients.len() && self.inner.llmp_clients[client_id.0 as usize].id == client_id { @@ -2758,32 +2725,145 @@ where self.inner .llmp_clients .binary_search_by_key(&client_id, |x| x.id) - .unwrap_or_else(|_| panic!("Fatal error, client ID {client_id:?} not found in llmp_clients.")) + .unwrap_or_else(|_| { + panic!( + "Fatal error, client ID {client_id:?} not found in llmp_clients." + ) + }) }; - - let map = &mut self.inner.llmp_clients[pos].current_recv_shmem; - let msg_buf = (*msg).try_as_slice_mut(map)?; - - // The message is not specifically for use. Let the user handle it, then forward it to the clients, if necessary. - let mut new_msgs: Vec<(Tag, Flags, Vec)> = Vec::new(); - if let LlmpMsgHookResult::ForwardToClients = self.hooks.on_new_message_all( - &mut self.inner, - client_id, - &mut (*msg).tag, - &mut (*msg).flags, - msg_buf, - &mut new_msgs, - )? { - self.inner.forward_msg(msg)?; + let client = &mut self.inner.llmp_clients[pos]; + match client.recv()? { + None => { + // We're done handling this client + #[cfg(feature = "std")] + if new_messages { + // set the recv time + // We don't do that in recv() to keep calls to `current_time` to a minimum. + self.inner.llmp_clients[pos].last_msg_time = current_time(); + } + return Ok(new_messages); + } + Some(msg) => msg, } + }; + // We got a new message + new_messages = true; - log::debug!("New msg vector: {}", new_msgs.len()); - for (new_msg_tag, new_msg_flag, new_msg) in new_msgs { - self.inner.llmp_out.send_buf_with_flags( - new_msg_tag, - new_msg_flag, - new_msg.as_ref(), - )?; + match (*msg).tag { + // first, handle the special, llmp-internal messages + LLMP_SLOW_RECEIVER_PANIC => { + return Err(Error::unknown(format!( + "The broker was too slow to handle messages of client {client_id:?} in time, so it quit. Either the client sent messages too fast, or we (the broker) got stuck!" + ))); + } + LLMP_TAG_CLIENT_EXIT => { + let msg_buf_len_padded = (*msg).buf_len_padded; + if (*msg).buf_len < size_of::() as u64 { + log::info!( + "Ignoring broken CLIENT_EXIT msg due to incorrect size. Expected {} but got {}", + msg_buf_len_padded, + size_of::() + ); + #[cfg(not(feature = "std"))] + return Err(Error::unknown(format!( + "Broken CLIENT_EXIT msg with incorrect size received. Expected {} but got {}", + msg_buf_len_padded, + size_of::() + ))); + } + let exitinfo = (*msg).buf.as_mut_ptr() as *mut LlmpClientExitInfo; + let client_id = ClientId((*exitinfo).client_id); + log::info!( + "Client exit message received!, we are removing clients whose client_group_id is {:#?}", + client_id + ); + + self.inner.clients_to_remove.push(client_id); + } + LLMP_TAG_NEW_SHM_CLIENT => { + /* This client informs us about yet another new client + add it to the list! Also, no need to forward this msg. */ + let msg_buf_len_padded = (*msg).buf_len_padded; + if (*msg).buf_len < size_of::() as u64 { + log::info!( + "Ignoring broken CLIENT_ADDED msg due to incorrect size. Expected {} but got {}", + msg_buf_len_padded, + size_of::() + ); + #[cfg(not(feature = "std"))] + return Err(Error::unknown(format!( + "Broken CLIENT_ADDED msg with incorrect size received. Expected {} but got {}", + msg_buf_len_padded, + size_of::() + ))); + } + let pageinfo = (*msg).buf.as_mut_ptr() as *mut LlmpPayloadSharedMapInfo; + match self.inner.shmem_provider.shmem_from_id_and_size( + ShMemId::from_array(&(*pageinfo).shm_str), + (*pageinfo).map_size, + ) { + Ok(new_shmem) => { + let mut new_page = LlmpSharedMap::existing(new_shmem); + new_page.mark_safe_to_unmap(); + + let _new_client = self.inner.add_client(LlmpReceiver { + id: ClientId(0), // will be auto-filled + current_recv_shmem: new_page, + last_msg_recvd: ptr::null_mut(), + shmem_provider: self.inner.shmem_provider.clone(), + highest_msg_id: MessageId(0), + // We don't know the last received time, just assume the current time. + #[cfg(feature = "std")] + last_msg_time: current_time(), + }); + } + Err(e) => { + log::info!("Error adding client! Ignoring: {e:?}"); + #[cfg(not(feature = "std"))] + return Err(Error::unknown(format!( + "Error adding client! PANIC! {e:?}" + ))); + } + } + } + // handle all other messages + _ => { + let pos = if (client_id.0 as usize) < self.inner.llmp_clients.len() + && self.inner.llmp_clients[client_id.0 as usize].id == client_id + { + // Fast path when no client before this one was removed + client_id.0 as usize + } else { + self.inner + .llmp_clients + .binary_search_by_key(&client_id, |x| x.id) + .unwrap_or_else(|_| panic!("Fatal error, client ID {client_id:?} not found in llmp_clients.")) + }; + + let map = &mut self.inner.llmp_clients[pos].current_recv_shmem; + let msg_buf = (*msg).try_as_slice_mut(map)?; + + // The message is not specifically for use. Let the user handle it, then forward it to the clients, if necessary. + let mut new_msgs: Vec<(Tag, Flags, Vec)> = Vec::new(); + if let LlmpMsgHookResult::ForwardToClients = self.hooks.on_new_message_all( + &mut self.inner, + client_id, + &mut (*msg).tag, + &mut (*msg).flags, + msg_buf, + &mut new_msgs, + )? { + self.inner.forward_msg(msg)?; + } + + log::debug!("New msg vector: {}", new_msgs.len()); + for (new_msg_tag, new_msg_flag, new_msg) in new_msgs { + self.inner.llmp_out.send_buf_with_flags( + new_msg_tag, + new_msg_flag, + new_msg.as_ref(), + )?; + } } } } @@ -2955,7 +3035,7 @@ where _ => { return Err(Error::illegal_state( "Unexpected response from B2B server received.".to_string(), - )) + )); } } @@ -3008,21 +3088,23 @@ where /// For internal use: Forward the current message to the out map. unsafe fn forward_msg(&mut self, msg: *mut LlmpMsg) -> Result<(), Error> { - let out: *mut LlmpMsg = self.alloc_next((*msg).buf_len_padded as usize)?; + unsafe { + let out: *mut LlmpMsg = self.alloc_next((*msg).buf_len_padded as usize)?; - /* Copy over the whole message. - If we should need zero copy, we could instead post a link to the - original msg with the map_id and offset. */ - let actual_size = (*out).buf_len_padded; - let complete_size = actual_size as usize + size_of::(); - (msg as *const u8).copy_to_nonoverlapping(out as *mut u8, complete_size); - (*out).buf_len_padded = actual_size; - /* We need to replace the message ID with our own */ - if let Err(e) = self.llmp_out.send(out, false) { - panic!("Error sending msg: {e:?}"); + /* Copy over the whole message. + If we should need zero copy, we could instead post a link to the + original msg with the map_id and offset. */ + let actual_size = (*out).buf_len_padded; + let complete_size = actual_size as usize + size_of::(); + (msg as *const u8).copy_to_nonoverlapping(out as *mut u8, complete_size); + (*out).buf_len_padded = actual_size; + /* We need to replace the message ID with our own */ + if let Err(e) = self.llmp_out.send(out, false) { + panic!("Error sending msg: {e:?}"); + } + self.llmp_out.last_msg_sent = out; + Ok(()) } - self.llmp_out.last_msg_sent = out; - Ok(()) } /// Internal function, returns true when shuttdown is requested by a `SIGINT` signal @@ -3194,7 +3276,9 @@ where payload: payload.to_vec(), }, ) { - log::info!("Got error {e} while trying to forward a message to broker {peer_address}, exiting thread"); + log::info!( + "Got error {e} while trying to forward a message to broker {peer_address}, exiting thread" + ); return; } } @@ -3569,7 +3653,7 @@ where /// Should be save, unless the internal state is corrupt. Returns raw ptr. #[inline] pub unsafe fn recv(&mut self) -> Result, Error> { - self.receiver.recv() + unsafe { self.receiver.recv() } } /// A client blocks/spins until the next message gets posted to the page, @@ -3578,7 +3662,7 @@ where /// Should be save, unless the internal state is corrupt. Returns raw ptr. #[inline] pub unsafe fn recv_blocking(&mut self) -> Result<*mut LlmpMsg, Error> { - self.receiver.recv_blocking() + unsafe { self.receiver.recv_blocking() } } /// The current page could have changed in recv (EOP). @@ -3716,22 +3800,29 @@ where /// Calling this in other contexts may lead to a premature page unmap and result in a crash in another process, /// or an unexpected read from an empty page in a receiving process. pub unsafe fn mark_safe_to_unmap(&mut self) { - self.sender.mark_safe_to_unmap(); + unsafe { + self.sender.mark_safe_to_unmap(); + } } /// Commits a msg to the client's out map /// # Safety /// Needs to be called with a proper msg pointer pub unsafe fn send(&mut self, msg: *mut LlmpMsg) -> Result<(), Error> { - self.sender.send(msg, true) + unsafe { self.sender.send(msg, true) } } /// Write the current state to env. /// A new client can attach to exactly the same state by calling [`LlmpClient::on_existing_shmem()`]. + /// + /// # Safety + /// Writes to env variables and may only be done single-threaded. #[cfg(feature = "std")] - pub fn to_env(&self, env_name: &str) -> Result<(), Error> { - self.sender.to_env(&format!("{env_name}_SENDER"))?; - self.receiver.to_env(&format!("{env_name}_RECEIVER")) + pub unsafe fn to_env(&self, env_name: &str) -> Result<(), Error> { + unsafe { + self.sender.to_env(&format!("{env_name}_SENDER"))?; + self.receiver.to_env(&format!("{env_name}_RECEIVER")) + } } /// Describe this client in a way that it can be recreated, for example after crash @@ -3809,7 +3900,11 @@ mod tests { // Send stuff client.send_buf(tag, &arr).unwrap(); - client.to_env("_ENV_TEST").unwrap(); + // # Safety + // Test only. Should run one instance. + unsafe { + client.to_env("_ENV_TEST").unwrap(); + } #[cfg(all(feature = "llmp_debug", feature = "std"))] log::info!("{:?}", std::env::vars()); diff --git a/libafl_bolts/src/minibsod.rs b/libafl_bolts/src/minibsod.rs index eb28fa63ba..ee7a8d44cc 100644 --- a/libafl_bolts/src/minibsod.rs +++ b/libafl_bolts/src/minibsod.rs @@ -24,7 +24,7 @@ use mach::{ use windows::Win32::System::Diagnostics::Debug::{CONTEXT, EXCEPTION_POINTERS}; #[cfg(unix)] -use crate::os::unix_signals::{ucontext_t, Signal}; +use crate::os::unix_signals::{Signal, ucontext_t}; /// Necessary info to print a mini-BSOD. #[derive(Debug)] @@ -48,7 +48,7 @@ pub fn dump_registers( ucontext: &ucontext_t, ) -> Result<(), std::io::Error> { use libc::{ - REG_EFL, REG_R10, REG_R11, REG_R12, REG_R13, REG_R14, REG_R15, REG_R8, REG_R9, REG_RAX, + REG_EFL, REG_R8, REG_R9, REG_R10, REG_R11, REG_R12, REG_R13, REG_R14, REG_R15, REG_RAX, REG_RBP, REG_RBX, REG_RCX, REG_RDI, REG_RDX, REG_RIP, REG_RSI, REG_RSP, }; @@ -272,7 +272,7 @@ pub fn dump_registers( ucontext: &ucontext_t, ) -> Result<(), std::io::Error> { use libc::{ - _REG_CS, _REG_R10, _REG_R11, _REG_R12, _REG_R13, _REG_R14, _REG_R15, _REG_R8, _REG_R9, + _REG_CS, _REG_R8, _REG_R9, _REG_R10, _REG_R11, _REG_R12, _REG_R13, _REG_R14, _REG_R15, _REG_RAX, _REG_RBP, _REG_RBX, _REG_RCX, _REG_RDI, _REG_RDX, _REG_RFLAGS, _REG_RIP, _REG_RSI, _REG_RSP, }; @@ -430,7 +430,7 @@ pub fn dump_registers( ucontext: &ucontext_t, ) -> Result<(), std::io::Error> { use libc::{ - REG_R10, REG_R11, REG_R12, REG_R13, REG_R14, REG_R15, REG_R8, REG_R9, REG_RAX, REG_RBP, + REG_R8, REG_R9, REG_R10, REG_R11, REG_R12, REG_R13, REG_R14, REG_R15, REG_RAX, REG_RBP, REG_RBX, REG_RCX, REG_RDI, REG_RDX, REG_RFL, REG_RIP, REG_RSI, REG_RSP, }; @@ -1165,7 +1165,7 @@ pub fn generate_minibsod( #[cfg(test)] mod tests { - use std::io::{stdout, BufWriter}; + use std::io::{BufWriter, stdout}; use crate::{minibsod::dump_registers, os::unix_signals::ucontext}; @@ -1183,16 +1183,16 @@ mod tests { mod tests { use std::{ - io::{stdout, BufWriter}, + io::{BufWriter, stdout}, os::raw::c_void, sync::mpsc, }; use windows::Win32::{ - Foundation::{CloseHandle, DuplicateHandle, DUPLICATE_SAME_ACCESS, HANDLE}, + Foundation::{CloseHandle, DUPLICATE_SAME_ACCESS, DuplicateHandle, HANDLE}, System::{ Diagnostics::Debug::{ - GetThreadContext, CONTEXT, CONTEXT_FULL_AMD64, CONTEXT_FULL_ARM64, CONTEXT_FULL_X86, + CONTEXT, CONTEXT_FULL_AMD64, CONTEXT_FULL_ARM64, CONTEXT_FULL_X86, GetThreadContext, }, Threading::{GetCurrentProcess, GetCurrentThread, ResumeThread, SuspendThread}, }, diff --git a/libafl_bolts/src/os/mod.rs b/libafl_bolts/src/os/mod.rs index a90c6fc4d7..004b8bfb14 100644 --- a/libafl_bolts/src/os/mod.rs +++ b/libafl_bolts/src/os/mod.rs @@ -75,19 +75,21 @@ pub enum ForkResult { /// A Normal fork. Runs on in two processes. Should be memory safe in general. #[cfg(unix)] pub unsafe fn fork() -> Result { - match libc::fork() { - pid if pid > 0 => Ok(ForkResult::Parent(ChildHandle { pid })), - pid if pid < 0 => { - // Getting errno from rust is hard, we'll just let the libc print to stderr for now. - // In any case, this should usually not happen. - #[cfg(feature = "std")] - { - let err_str = CString::new("Fork failed").unwrap(); - libc::perror(err_str.as_ptr()); + unsafe { + match libc::fork() { + pid if pid > 0 => Ok(ForkResult::Parent(ChildHandle { pid })), + pid if pid < 0 => { + // Getting errno from rust is hard, we'll just let the libc print to stderr for now. + // In any case, this should usually not happen. + #[cfg(feature = "std")] + { + let err_str = CString::new("Fork failed").unwrap(); + libc::perror(err_str.as_ptr()); + } + Err(Error::unknown(format!("Fork failed ({pid})"))) } - Err(Error::unknown(format!("Fork failed ({pid})"))) + _ => Ok(ForkResult::Child), } - _ => Ok(ForkResult::Child), } } @@ -123,7 +125,7 @@ pub fn peak_rss_mb_child_processes() -> Result { use core::mem; use std::io; - use libc::{rusage, RUSAGE_CHILDREN}; + use libc::{RUSAGE_CHILDREN, rusage}; let rss = unsafe { let mut rusage = mem::MaybeUninit::::uninit(); diff --git a/libafl_bolts/src/os/unix_shmem_server.rs b/libafl_bolts/src/os/unix_shmem_server.rs index 29254ac4e2..4ed95c701d 100644 --- a/libafl_bolts/src/os/unix_shmem_server.rs +++ b/libafl_bolts/src/os/unix_shmem_server.rs @@ -39,14 +39,14 @@ use std::{ use hashbrown::HashMap; use nix::poll::PollTimeout; #[cfg(all(feature = "std", unix))] -use nix::poll::{poll, PollFd, PollFlags}; +use nix::poll::{PollFd, PollFlags, poll}; use serde::{Deserialize, Serialize}; #[cfg(all(unix, feature = "std"))] use uds::{UnixListenerExt, UnixSocketAddr, UnixStreamExt}; use crate::{ - shmem::{ShMem, ShMemDescription, ShMemId, ShMemProvider}, Error, + shmem::{ShMem, ShMemDescription, ShMemId, ShMemProvider}, }; /// The default server name for our abstract shmem server @@ -130,7 +130,9 @@ impl ServedShMemProvider { let (slice_size, fd_count) = self.stream.recv_fds(&mut shm_slice, &mut fd_buf)?; //.expect("Did not receive a response"); if slice_size == 0 && fd_count == 0 { - return Err(Error::illegal_state(format!("Tried to receive 20 bytes and one fd via unix shmem socket, but got {slice_size} bytes and {fd_count} fds."))); + return Err(Error::illegal_state(format!( + "Tried to receive 20 bytes and one fd via unix shmem socket, but got {slice_size} bytes and {fd_count} fds." + ))); } let server_id = ShMemId::from_array(&shm_slice); @@ -368,7 +370,8 @@ impl Drop for ShMemServiceThread { #[cfg(target_vendor = "apple")] fs::remove_file(UNIX_SERVER_NAME).unwrap(); - env::remove_var(AFL_SHMEM_SERVICE_STARTED); + // TODO: Audit that the environment access only happens in single-threaded code. + unsafe { env::remove_var(AFL_SHMEM_SERVICE_STARTED) }; } } } @@ -404,11 +407,12 @@ where return Err(e); } }; - if let Err(e) = worker.listen(UNIX_SERVER_NAME, &childsyncpair) { - log::error!("Error spawning ShMemService: {e:?}"); - Err(e) - } else { - Ok(()) + match worker.listen(UNIX_SERVER_NAME, &childsyncpair) { + Err(e) => { + log::error!("Error spawning ShMemService: {e:?}"); + Err(e) + } + _ => Ok(()), } }); @@ -420,7 +424,8 @@ where // Optimization: Following calls or even child processe don't need to try to start a service anymore. // It's either running at this point, or we won't be able to spawn it anyway. - env::set_var(AFL_SHMEM_SERVICE_STARTED, "true"); + // TODO: Audit that the environment access only happens in single-threaded code. + unsafe { env::set_var(AFL_SHMEM_SERVICE_STARTED, "true") }; let status = *success; match status { @@ -532,21 +537,25 @@ where let client = self.clients.get_mut(&client_id).unwrap(); if description.id.is_empty() { - return Err(Error::illegal_state("Received empty ShMemId from unix shmem client. Are the shmem limits set correctly? Did a client crash?")); + return Err(Error::illegal_state( + "Received empty ShMemId from unix shmem client. Are the shmem limits set correctly? Did a client crash?", + )); } let description_id: i32 = description.id.into(); if !self.all_shmems.contains_key(&description_id) { // We should never get here, but it may happen if the OS ran out of shmem pages at some point//reached limits. - return Err(Error::illegal_state(format!("Client wanted to read from existing map with id {description_id}/{description:?}, but it was not allocated by this shmem server. Are the shmem limits set correctly? Did a client crash?"))); + return Err(Error::illegal_state(format!( + "Client wanted to read from existing map with id {description_id}/{description:?}, but it was not allocated by this shmem server. Are the shmem limits set correctly? Did a client crash?" + ))); } if client.maps.contains_key(&description_id) { // Using let else here as self needs to be accessed in the else branch. #[expect(clippy::option_if_let_else)] Ok(ServedShMemResponse::Mapping( - if let Some(map) = client + match client .maps .get_mut(&description_id) .as_mut() @@ -554,9 +563,8 @@ where .first() .as_mut() { - map.clone() - } else { - self.upgrade_shmem_with_id(description_id) + Some(map) => map.clone(), + _ => self.upgrade_shmem_with_id(description_id), }, )) } else { @@ -645,7 +653,8 @@ where cvar.notify_one(); return Err(Error::unknown(format!( - "The ShMem server appears to already be running. We are probably a client. Error: {err:?}"))); + "The ShMem server appears to already be running. We are probably a client. Error: {err:?}" + ))); } }; diff --git a/libafl_bolts/src/os/unix_signals.rs b/libafl_bolts/src/os/unix_signals.rs index 8ff6a11775..3ebed948f7 100644 --- a/libafl_bolts/src/os/unix_signals.rs +++ b/libafl_bolts/src/os/unix_signals.rs @@ -7,7 +7,7 @@ use core::mem::size_of; use core::{ cell::UnsafeCell, ptr::{self, write_volatile}, - sync::atomic::{compiler_fence, Ordering}, + sync::atomic::{Ordering, compiler_fence}, }; use core::{ fmt::{self, Display, Formatter}, @@ -161,7 +161,6 @@ pub struct arm_thread_state64 { #[derive(Debug)] #[repr(C, align(16))] #[allow(non_camel_case_types)] // expect breaks for some reason - //#[repr(align(16))] pub struct arm_neon_state64 { /// opaque pub opaque: [u8; (32 * 16) + (2 * size_of::())], @@ -254,21 +253,21 @@ use libc::ssize_t; all(target_vendor = "apple", target_arch = "aarch64") )))] pub use libc::ucontext_t; -use libc::{ - c_int, SIGABRT, SIGALRM, SIGBUS, SIGFPE, SIGHUP, SIGILL, SIGINT, SIGKILL, SIGPIPE, SIGQUIT, - SIGSEGV, SIGTERM, SIGTRAP, SIGUSR2, -}; -pub use libc::{c_void, siginfo_t}; #[cfg(feature = "alloc")] use libc::{ - malloc, sigaction, sigaddset, sigaltstack, sigemptyset, stack_t, SA_NODEFER, SA_ONSTACK, - SA_SIGINFO, + SA_NODEFER, SA_ONSTACK, SA_SIGINFO, malloc, sigaction, sigaddset, sigaltstack, sigemptyset, + stack_t, }; +use libc::{ + SIGABRT, SIGALRM, SIGBUS, SIGFPE, SIGHUP, SIGILL, SIGINT, SIGKILL, SIGPIPE, SIGQUIT, SIGSEGV, + SIGTERM, SIGTRAP, SIGUSR2, c_int, +}; +pub use libc::{c_void, siginfo_t}; use num_enum::{IntoPrimitive, TryFromPrimitive}; use crate::Error; -extern "C" { +unsafe extern "C" { /// The `libc` `getcontext` /// For some reason, it's not available on `MacOS`. fn getcontext(ucp: *mut ucontext_t) -> c_int; @@ -436,18 +435,20 @@ static mut SIGNAL_HANDLERS: [Option; 32] = [ /// unless the signal handlers registered using [`setup_signal_handler()`] are broken. #[cfg(feature = "alloc")] unsafe fn handle_signal(sig: c_int, info: *mut siginfo_t, void: *mut c_void) { - let signal = &Signal::try_from(sig).unwrap(); - let handler = { - match &SIGNAL_HANDLERS[*signal as usize] { - Some(handler_holder) => &mut **handler_holder.handler.get(), - None => return, - } - }; - handler.handle( - *signal, - &mut ptr::read_unaligned(info), - (void as *mut ucontext_t).as_mut(), - ); + unsafe { + let signal = &Signal::try_from(sig).unwrap(); + let handler = { + match &SIGNAL_HANDLERS[*signal as usize] { + Some(handler_holder) => &mut **handler_holder.handler.get(), + None => return, + } + }; + handler.handle( + *signal, + &mut ptr::read_unaligned(info), + (void as *mut ucontext_t).as_mut(), + ); + } } /// Setup signal handlers in a somewhat rusty way. @@ -465,47 +466,49 @@ unsafe fn handle_signal(sig: c_int, info: *mut siginfo_t, void: *mut c_void) { pub unsafe fn setup_signal_handler( handler: *mut T, ) -> Result<(), Error> { - // First, set up our own stack to be used during segfault handling. (and specify `SA_ONSTACK` in `sigaction`) - if SIGNAL_STACK_PTR.is_null() { - SIGNAL_STACK_PTR = malloc(SIGNAL_STACK_SIZE); + unsafe { + // First, set up our own stack to be used during segfault handling. (and specify `SA_ONSTACK` in `sigaction`) + if SIGNAL_STACK_PTR.is_null() { + SIGNAL_STACK_PTR = malloc(SIGNAL_STACK_SIZE); - // Rust always panics on OOM, so we will, too. - assert!( - !SIGNAL_STACK_PTR.is_null(), - "Failed to allocate signal stack with {SIGNAL_STACK_SIZE} bytes!" - ); - } - let mut ss: stack_t = mem::zeroed(); - ss.ss_size = SIGNAL_STACK_SIZE; - ss.ss_sp = SIGNAL_STACK_PTR; - sigaltstack(&raw mut ss, ptr::null_mut() as _); - - let mut sa: sigaction = mem::zeroed(); - sigemptyset(&raw mut sa.sa_mask); - sigaddset(&raw mut sa.sa_mask, SIGALRM); - sa.sa_flags = SA_NODEFER | SA_SIGINFO | SA_ONSTACK; - sa.sa_sigaction = handle_signal as usize; - let signals = unsafe { (*handler).signals() }; - for sig in signals { - write_volatile( - &raw mut SIGNAL_HANDLERS[sig as usize], - Some(HandlerHolder { - handler: UnsafeCell::new(handler as *mut dyn SignalHandler), - }), - ); - - if sigaction(sig as i32, &raw mut sa, ptr::null_mut()) < 0 { - #[cfg(feature = "std")] - { - let err_str = CString::new(format!("Failed to setup {sig} handler")).unwrap(); - libc::perror(err_str.as_ptr()); - } - return Err(Error::unknown(format!("Could not set up {sig} handler"))); + // Rust always panics on OOM, so we will, too. + assert!( + !SIGNAL_STACK_PTR.is_null(), + "Failed to allocate signal stack with {SIGNAL_STACK_SIZE} bytes!" + ); } - } - compiler_fence(Ordering::SeqCst); + let mut ss: stack_t = mem::zeroed(); + ss.ss_size = SIGNAL_STACK_SIZE; + ss.ss_sp = SIGNAL_STACK_PTR; + sigaltstack(&raw mut ss, ptr::null_mut() as _); - Ok(()) + let mut sa: sigaction = mem::zeroed(); + sigemptyset(&raw mut sa.sa_mask); + sigaddset(&raw mut sa.sa_mask, SIGALRM); + sa.sa_flags = SA_NODEFER | SA_SIGINFO | SA_ONSTACK; + sa.sa_sigaction = handle_signal as usize; + let signals = (*handler).signals(); + for sig in signals { + write_volatile( + &raw mut SIGNAL_HANDLERS[sig as usize], + Some(HandlerHolder { + handler: UnsafeCell::new(handler as *mut dyn SignalHandler), + }), + ); + + if sigaction(sig as i32, &raw mut sa, ptr::null_mut()) < 0 { + #[cfg(feature = "std")] + { + let err_str = CString::new(format!("Failed to setup {sig} handler")).unwrap(); + libc::perror(err_str.as_ptr()); + } + return Err(Error::unknown(format!("Could not set up {sig} handler"))); + } + } + compiler_fence(Ordering::SeqCst); + + Ok(()) + } } /// Function to get the current [`ucontext_t`] for this process. diff --git a/libafl_bolts/src/os/windows_exceptions.rs b/libafl_bolts/src/os/windows_exceptions.rs index ca147f03d1..52d7d7f2fd 100644 --- a/libafl_bolts/src/os/windows_exceptions.rs +++ b/libafl_bolts/src/os/windows_exceptions.rs @@ -6,7 +6,7 @@ use core::{ cell::UnsafeCell, fmt::{self, Display, Formatter}, ptr::{self, write_volatile}, - sync::atomic::{compiler_fence, Ordering}, + sync::atomic::{Ordering, compiler_fence}, }; use std::os::raw::{c_long, c_void}; @@ -14,9 +14,9 @@ use num_enum::FromPrimitive; pub use windows::Win32::{ Foundation::{BOOL, NTSTATUS}, System::{ - Console::{SetConsoleCtrlHandler, CTRL_BREAK_EVENT, CTRL_C_EVENT, PHANDLER_ROUTINE}, + Console::{CTRL_BREAK_EVENT, CTRL_C_EVENT, PHANDLER_ROUTINE, SetConsoleCtrlHandler}, Diagnostics::Debug::{ - AddVectoredExceptionHandler, UnhandledExceptionFilter, EXCEPTION_POINTERS, + AddVectoredExceptionHandler, EXCEPTION_POINTERS, UnhandledExceptionFilter, }, Threading::{IsProcessorFeaturePresent, PROCESSOR_FEATURE_ID}, }, @@ -463,14 +463,16 @@ unsafe fn internal_handle_exception( .iter() .position(|x| *x == exception_code) .unwrap(); - if let Some(handler_holder) = &EXCEPTION_HANDLERS[index] { + if let Some(handler_holder) = unsafe { &EXCEPTION_HANDLERS[index] } { log::info!( "{:?}: Handling exception {}", std::process::id(), exception_code ); - let handler = &mut **handler_holder.handler.get(); - handler.handle(exception_code, exception_pointers); + let handler = unsafe { &mut **handler_holder.handler.get() }; + unsafe { + handler.handle(exception_code, exception_pointers); + } EXCEPTION_CONTINUE_EXECUTION } else { log::info!( @@ -479,11 +481,13 @@ unsafe fn internal_handle_exception( exception_code ); // Go to Default one - let handler_holder = &EXCEPTION_HANDLERS[EXCEPTION_HANDLERS_SIZE - 1] + let handler_holder = unsafe { &EXCEPTION_HANDLERS[EXCEPTION_HANDLERS_SIZE - 1] } .as_ref() .unwrap(); - let handler = &mut **handler_holder.handler.get(); - handler.handle(exception_code, exception_pointers); + let handler = unsafe { &mut **handler_holder.handler.get() }; + unsafe { + handler.handle(exception_code, exception_pointers); + } EXCEPTION_CONTINUE_SEARCH } } @@ -494,16 +498,18 @@ unsafe fn internal_handle_exception( pub unsafe extern "system" fn handle_exception( exception_pointers: *mut EXCEPTION_POINTERS, ) -> c_long { - let code = exception_pointers - .as_mut() - .unwrap() - .ExceptionRecord - .as_mut() - .unwrap() - .ExceptionCode; + let code = unsafe { + exception_pointers + .as_mut() + .unwrap() + .ExceptionRecord + .as_mut() + .unwrap() + .ExceptionCode + }; let exception_code = From::from(code.0); log::info!("Received exception; code: {}", exception_code); - internal_handle_exception(exception_code, exception_pointers) + unsafe { internal_handle_exception(exception_code, exception_pointers) } } /// Return `SIGIGN` this is 1 (when represented as u64) @@ -512,17 +518,19 @@ pub unsafe extern "system" fn handle_exception( /// It is just casting into another type, nothing unsafe. #[must_use] pub const unsafe fn sig_ign() -> NativeSignalHandlerType { - core::mem::transmute(1usize) + unsafe { core::mem::transmute(1_usize) } } type NativeSignalHandlerType = unsafe extern "C" fn(i32); -extern "C" { +unsafe extern "C" { pub fn signal(signum: i32, func: NativeSignalHandlerType) -> *const c_void; } unsafe extern "C" fn handle_signal(_signum: i32) { // log::info!("Received signal {}", _signum); - internal_handle_exception(ExceptionCode::AssertionFailure, ptr::null_mut()); + unsafe { + internal_handle_exception(ExceptionCode::AssertionFailure, ptr::null_mut()); + } } /// Setup Win32 exception handlers in a somewhat rusty way. @@ -532,7 +540,7 @@ unsafe extern "C" fn handle_signal(_signum: i32) { pub unsafe fn setup_exception_handler( handler: *mut T, ) -> Result<(), Error> { - let exceptions = (*handler).exceptions(); + let exceptions = unsafe { (*handler).exceptions() }; let mut catch_assertions = false; for exception_code in exceptions { if exception_code == ExceptionCode::AssertionFailure { @@ -542,33 +550,41 @@ pub unsafe fn setup_exception_handler( .iter() .position(|x| *x == exception_code) .unwrap(); + unsafe { + write_volatile( + &raw mut EXCEPTION_HANDLERS[index], + Some(HandlerHolder { + handler: UnsafeCell::new(handler as *mut dyn ExceptionHandler), + }), + ); + } + } + + unsafe { write_volatile( - &raw mut EXCEPTION_HANDLERS[index], + &raw mut (EXCEPTION_HANDLERS[EXCEPTION_HANDLERS_SIZE - 1]), Some(HandlerHolder { handler: UnsafeCell::new(handler as *mut dyn ExceptionHandler), }), ); } - - write_volatile( - &raw mut (EXCEPTION_HANDLERS[EXCEPTION_HANDLERS_SIZE - 1]), - Some(HandlerHolder { - handler: UnsafeCell::new(handler as *mut dyn ExceptionHandler), - }), - ); compiler_fence(Ordering::SeqCst); if catch_assertions { - signal(SIGABRT, handle_signal); + unsafe { + signal(SIGABRT, handle_signal); + } } // SetUnhandledFilter does not work with frida since the stack is changed and exception handler is lost with Stalker enabled. // See https://github.com/AFLplusplus/LibAFL/pull/403 - AddVectoredExceptionHandler( - 0, - Some(core::mem::transmute::< - *const core::ffi::c_void, - unsafe extern "system" fn(*mut EXCEPTION_POINTERS) -> i32, - >(handle_exception as *const c_void)), - ); + unsafe { + AddVectoredExceptionHandler( + 0, + Some(core::mem::transmute::< + *const core::ffi::c_void, + unsafe extern "system" fn(*mut EXCEPTION_POINTERS) -> i32, + >(handle_exception as *const c_void)), + ); + } Ok(()) } @@ -591,16 +607,18 @@ static mut CTRL_HANDLER: Option = None; pub(crate) unsafe fn setup_ctrl_handler( handler: *mut T, ) -> Result<(), Error> { - write_volatile( - &raw mut (CTRL_HANDLER), - Some(CtrlHandlerHolder { - handler: UnsafeCell::new(handler as *mut dyn CtrlHandler), - }), - ); + unsafe { + write_volatile( + &raw mut (CTRL_HANDLER), + Some(CtrlHandlerHolder { + handler: UnsafeCell::new(handler as *mut dyn CtrlHandler), + }), + ); + } compiler_fence(Ordering::SeqCst); // Log the result of SetConsoleCtrlHandler - let result = SetConsoleCtrlHandler(Some(Some(ctrl_handler)), true); + let result = unsafe { SetConsoleCtrlHandler(Some(Some(ctrl_handler)), true) }; match result { Ok(()) => { log::info!("SetConsoleCtrlHandler succeeded"); @@ -614,12 +632,12 @@ pub(crate) unsafe fn setup_ctrl_handler( } unsafe extern "system" fn ctrl_handler(ctrl_type: u32) -> BOOL { - let handler = ptr::read_volatile(&raw const (CTRL_HANDLER)); + let handler = unsafe { ptr::read_volatile(&raw const (CTRL_HANDLER)) }; match handler { Some(handler_holder) => { log::info!("{:?}: Handling ctrl {}", std::process::id(), ctrl_type); - let handler = &mut *handler_holder.handler.get(); - if let Some(ctrl_handler) = handler.as_mut() { + let handler = unsafe { &mut *handler_holder.handler.get() }; + if let Some(ctrl_handler) = unsafe { handler.as_mut() } { (*ctrl_handler).handle(ctrl_type).into() } else { false.into() diff --git a/libafl_bolts/src/ownedref.rs b/libafl_bolts/src/ownedref.rs index 1c7c6bc905..74312ba1ac 100644 --- a/libafl_bolts/src/ownedref.rs +++ b/libafl_bolts/src/ownedref.rs @@ -18,7 +18,7 @@ use core::{ use serde::{Deserialize, Deserializer, Serialize, Serializer}; use crate::{ - shmem::ShMem, AsSizedSlice, AsSizedSliceMut, AsSlice, AsSliceMut, IntoOwned, Truncate, + AsSizedSlice, AsSizedSliceMut, AsSlice, AsSliceMut, IntoOwned, Truncate, shmem::ShMem, }; /// Constant size array visitor for serde deserialization. @@ -28,8 +28,8 @@ mod arrays { use core::{convert::TryInto, marker::PhantomData}; use serde::{ - de::{SeqAccess, Visitor}, Deserialize, Deserializer, + de::{SeqAccess, Visitor}, }; struct ArrayVisitor(PhantomData); @@ -155,11 +155,13 @@ where /// The pointer needs to point to a valid object of type `T`. /// Any use of this [`OwnedRef`] will dereference the pointer accordingly. pub unsafe fn from_ptr(ptr: *const T) -> Self { - assert!( - !ptr.is_null(), - "Null pointer passed to OwnedRef::ref_raw constructor!" - ); - Self::RefRaw(ptr, UnsafeMarker::new()) + unsafe { + assert!( + !ptr.is_null(), + "Null pointer passed to OwnedRef::ref_raw constructor!" + ); + Self::RefRaw(ptr, UnsafeMarker::new()) + } } /// Returns true if the inner ref is a raw pointer, false otherwise. @@ -191,7 +193,7 @@ where /// The shared memory needs to start with a valid object of type `T`. /// Any use of this [`OwnedRef`] will dereference a pointer to the shared memory accordingly. pub unsafe fn from_shmem(shmem: &mut SHM) -> Self { - Self::from_ptr(shmem.as_mut_ptr_of().unwrap()) + unsafe { Self::from_ptr(shmem.as_mut_ptr_of().unwrap()) } } /// Returns a new [`OwnedRef`], owning the given value. @@ -301,11 +303,13 @@ where /// The pointer needs to point to a valid object of type `T`. /// Any use of this [`OwnedRefMut`] will dereference the pointer accordingly. pub unsafe fn from_mut_ptr(ptr: *mut T) -> Self { - assert!( - !ptr.is_null(), - "Null pointer passed to OwnedRefMut::from_mut_ptr constructor!" - ); - Self::RefRaw(ptr, UnsafeMarker::new()) + unsafe { + assert!( + !ptr.is_null(), + "Null pointer passed to OwnedRefMut::from_mut_ptr constructor!" + ); + Self::RefRaw(ptr, UnsafeMarker::new()) + } } } @@ -322,7 +326,7 @@ where /// The shared memory needs to start with a valid object of type `T`. /// Any use of this [`OwnedRefMut`] will dereference a pointer to the shared memory accordingly. pub unsafe fn from_shmem(shmem: &mut SHM) -> Self { - Self::from_mut_ptr(shmem.as_mut_ptr_of().unwrap()) + unsafe { Self::from_mut_ptr(shmem.as_mut_ptr_of().unwrap()) } } /// Returns a new [`OwnedRefMut`], owning the given value. @@ -462,8 +466,10 @@ impl<'a, T> OwnedSlice<'a, T> { /// The contents will be dereferenced in subsequent operations. #[must_use] pub unsafe fn from_raw_parts(ptr: *const T, len: usize) -> Self { - Self { - inner: OwnedSliceInner::RefRaw(ptr, len, UnsafeMarker::new()), + unsafe { + Self { + inner: OwnedSliceInner::RefRaw(ptr, len, UnsafeMarker::new()), + } } } @@ -694,13 +700,15 @@ impl<'a, T: 'a + Sized> OwnedMutSlice<'a, T> { /// The contents will be dereferenced in subsequent operations. #[must_use] pub unsafe fn from_raw_parts_mut(ptr: *mut T, len: usize) -> OwnedMutSlice<'a, T> { - if ptr.is_null() || len == 0 { - Self { - inner: OwnedMutSliceInner::Owned(Vec::new()), - } - } else { - Self { - inner: OwnedMutSliceInner::RefRaw(ptr, len, UnsafeMarker::new()), + unsafe { + if ptr.is_null() || len == 0 { + Self { + inner: OwnedMutSliceInner::Owned(Vec::new()), + } + } else { + Self { + inner: OwnedMutSliceInner::RefRaw(ptr, len, UnsafeMarker::new()), + } } } } @@ -933,8 +941,10 @@ impl<'a, T: 'a + Sized, const N: usize> OwnedMutSizedSlice<'a, T, N> { /// The content will be dereferenced in subsequent operations. #[must_use] pub unsafe fn from_raw_mut(ptr: NonNull<[T; N]>) -> OwnedMutSizedSlice<'a, T, N> { - Self { - inner: OwnedMutSizedSliceInner::RefRaw(ptr.as_ptr(), UnsafeMarker::new()), + unsafe { + Self { + inner: OwnedMutSizedSliceInner::RefRaw(ptr.as_ptr(), UnsafeMarker::new()), + } } } diff --git a/libafl_bolts/src/rands/mod.rs b/libafl_bolts/src/rands/mod.rs index b7d8177cf4..d213588053 100644 --- a/libafl_bolts/src/rands/mod.rs +++ b/libafl_bolts/src/rands/mod.rs @@ -8,7 +8,7 @@ use core::{ num::{NonZero, NonZeroUsize}, }; -use serde::{de::DeserializeOwned, Deserialize, Serialize}; +use serde::{Deserialize, Serialize, de::DeserializeOwned}; #[cfg(feature = "alloc")] pub mod loaded_dice; @@ -674,7 +674,7 @@ pub mod pybind { use pyo3::prelude::*; use serde::{Deserialize, Serialize}; - use super::{random_seed, Rand, StdRand}; + use super::{Rand, StdRand, random_seed}; #[pyclass(unsendable, name = "StdRand")] #[expect(clippy::unsafe_derive_deserialize)] diff --git a/libafl_bolts/src/serdeany.rs b/libafl_bolts/src/serdeany.rs index 6fc23087b4..b4cc50be05 100644 --- a/libafl_bolts/src/serdeany.rs +++ b/libafl_bolts/src/serdeany.rs @@ -3,13 +3,13 @@ #[cfg(feature = "stable_anymap")] use alloc::borrow::Cow; use alloc::boxed::Box; -#[cfg(feature = "stable_anymap")] -use core::any::type_name; #[cfg(not(feature = "stable_anymap"))] use core::any::TypeId; +#[cfg(feature = "stable_anymap")] +use core::any::type_name; use core::{any::Any, fmt::Debug}; -use serde::{de::DeserializeSeed, Deserialize, Deserializer, Serialize, Serializer}; +use serde::{Deserialize, Deserializer, Serialize, Serializer, de::DeserializeSeed}; pub use serdeany_registry::*; #[cfg(not(feature = "stable_anymap"))] @@ -121,17 +121,17 @@ pub mod serdeany_registry { use core::{any::TypeId, fmt, hash::BuildHasherDefault}; use hashbrown::{ - hash_map::{Values, ValuesMut}, HashMap, + hash_map::{Values, ValuesMut}, }; - use serde::{de, Deserialize, Serialize}; + use serde::{Deserialize, Serialize, de}; use crate::{ - serdeany::{ - type_repr, type_repr_owned, DeserializeCallback, DeserializeCallbackSeed, SerdeAny, - TypeRepr, - }, Error, + serdeany::{ + DeserializeCallback, DeserializeCallbackSeed, SerdeAny, TypeRepr, type_repr, + type_repr_owned, + }, }; /// A [`HashMap`] that maps from [`TypeRepr`] to a deserializer and its [`TypeRepr`]. @@ -197,7 +197,12 @@ pub mod serdeany_registry { // We assert that only one element with the given TypeId is in the map. // This is only necessary for stable_anymap where we don't directly use the TypeId, but the type_name instead. #[cfg(feature = "stable_anymap")] - assert_eq!(_entry.1, TypeId::of::(), "Fatal safety error: TypeId of type {} is not equal to the deserializer's TypeId for this type! Two registered types have the same type_name!", type_repr::()); + assert_eq!( + _entry.1, + TypeId::of::(), + "Fatal safety error: TypeId of type {} is not equal to the deserializer's TypeId for this type! Two registered types have the same type_name!", + type_repr::() + ); } pub fn finalize(&mut self) { @@ -349,7 +354,11 @@ pub mod serdeany_registry { match self.map.try_insert(type_repr_owned::(), value) { Ok(_) => (), // then it's fine Err(hashbrown::hash_map::OccupiedError { entry: _, value }) => { - return Err(Error::key_exists(format!("Tried to add a metadata of type {:?}. But this will overwrite the existing metadata value {:?}", core::any::type_name::(), value))); + return Err(Error::key_exists(format!( + "Tried to add a metadata of type {:?}. But this will overwrite the existing metadata value {:?}", + core::any::type_name::(), + value + ))); } } Ok(()) @@ -375,18 +384,18 @@ pub mod serdeany_registry { let registry = &raw const REGISTRY; assert!( - unsafe { - (*registry) - .deserializers - .as_ref() - .expect(super::ERR_EMPTY_TYPES_REGISTER) - .get(type_repr) - .is_some() - }, - "Type {} was inserted without registration! Call RegistryBuilder::register::<{}>() or use serdeany_autoreg.", - core::any::type_name::(), - core::any::type_name::() - ); + unsafe { + (*registry) + .deserializers + .as_ref() + .expect(super::ERR_EMPTY_TYPES_REGISTER) + .get(type_repr) + .is_some() + }, + "Type {} was inserted without registration! Call RegistryBuilder::register::<{}>() or use serdeany_autoreg.", + core::any::type_name::(), + core::any::type_name::() + ); self.map.raw_entry_mut().from_key(type_repr) } @@ -635,7 +644,12 @@ pub mod serdeany_registry { match outer.try_insert(name.into(), Box::new(val)) { Ok(_) => (), // then it's fine Err(hashbrown::hash_map::OccupiedError { entry, value }) => { - return Err(Error::key_exists(format!("Tried to add a metadata of type {:?} named {:?}. But this will overwrite the existing metadata value {:?}", core::any::type_name::(), entry.key(), value))); + return Err(Error::key_exists(format!( + "Tried to add a metadata of type {:?} named {:?}. But this will overwrite the existing metadata value {:?}", + core::any::type_name::(), + entry.key(), + value + ))); } } Ok(()) @@ -655,18 +669,18 @@ pub mod serdeany_registry { let type_repr = &type_repr; let registry = &raw const REGISTRY; assert!( - unsafe { - (*registry) - .deserializers - .as_ref() - .expect(super::ERR_EMPTY_TYPES_REGISTER) - .get(type_repr) - .is_some() - }, - "Type {} was inserted without registration! Call RegistryBuilder::register::<{}>() or use serdeany_autoreg.", - core::any::type_name::(), - core::any::type_name::() - ); + unsafe { + (*registry) + .deserializers + .as_ref() + .expect(super::ERR_EMPTY_TYPES_REGISTER) + .get(type_repr) + .is_some() + }, + "Type {} was inserted without registration! Call RegistryBuilder::register::<{}>() or use serdeany_autoreg.", + core::any::type_name::(), + core::any::type_name::() + ); self.map .raw_entry_mut() .from_key(type_repr) diff --git a/libafl_bolts/src/shmem.rs b/libafl_bolts/src/shmem.rs index 960a64a501..3ae501e91d 100644 --- a/libafl_bolts/src/shmem.rs +++ b/libafl_bolts/src/shmem.rs @@ -29,11 +29,11 @@ pub use unix_shmem::{UnixShMem, UnixShMemProvider}; #[cfg(all(windows, feature = "std"))] pub use win32_shmem::{Win32ShMem, Win32ShMemProvider}; +use crate::Error; #[cfg(all(unix, feature = "std", not(target_os = "haiku")))] use crate::os::pipes::Pipe; #[cfg(all(feature = "std", unix, not(target_os = "haiku")))] pub use crate::os::unix_shmem_server::{ServedShMem, ServedShMemProvider, ShMemService}; -use crate::Error; /// The standard sharedmem provider #[cfg(all(windows, feature = "std"))] @@ -256,12 +256,17 @@ pub trait ShMem: Sized + Debug + Clone + DerefMut { } /// Write this map's config to env + /// + /// # Safety + /// Writes to env variables and may only be done single-threaded. #[cfg(feature = "std")] - fn write_to_env(&self, env_name: &str) -> Result<(), Error> { + unsafe fn write_to_env(&self, env_name: &str) -> Result<(), Error> { let map_size = self.len(); let map_size_env = format!("{env_name}_SIZE"); - env::set_var(env_name, self.id().to_string()); - env::set_var(map_size_env, format!("{map_size}")); + // TODO: Audit that the environment access only happens in single-threaded code. + unsafe { env::set_var(env_name, self.id().to_string()) }; + // TODO: Audit that the environment access only happens in single-threaded code. + unsafe { env::set_var(map_size_env, format!("{map_size}")) }; Ok(()) } } @@ -642,14 +647,14 @@ impl RcShMemProvider> { /// A Unix sharedmem implementation. /// -/// On Android, this is partially reused to wrap [`unix_shmem::ashmem::AshmemShMem`], +/// On Android, this is partially reused to wrap `AshmemShMem`, /// Although for an [`ServedShMemProvider`] using a unix domain socket /// Is needed on top. #[cfg(all(unix, feature = "std", not(target_os = "haiku")))] pub mod unix_shmem { /// Mmap [`ShMem`] for Unix #[cfg(not(target_os = "android"))] - pub use default::{MmapShMem, MmapShMemProvider, MAX_MMAP_FILENAME_LEN}; + pub use default::{MAX_MMAP_FILENAME_LEN, MmapShMem, MmapShMemProvider}; #[cfg(doc)] use crate::shmem::{ShMem, ShMemProvider}; @@ -684,9 +689,9 @@ pub mod unix_shmem { }; use crate::{ + Error, rands::{Rand, StdRand}, shmem::{ShMem, ShMemId, ShMemProvider}, - Error, }; /// The max number of bytes used when generating names for [`MmapShMem`]s. @@ -1051,7 +1056,9 @@ pub mod unix_shmem { ); if os_id < 0_i32 { - return Err(Error::unknown(format!("Failed to allocate a shared mapping of size {map_size} - check OS limits (i.e shmall, shmmax)"))); + return Err(Error::unknown(format!( + "Failed to allocate a shared mapping of size {map_size} - check OS limits (i.e shmall, shmmax)" + ))); } let map = shmat(os_id, ptr::null(), 0) as *mut c_uchar; @@ -1166,13 +1173,13 @@ pub mod unix_shmem { use std::ffi::CString; use libc::{ - c_uint, c_ulong, c_void, close, ioctl, mmap, open, MAP_SHARED, O_RDWR, PROT_READ, - PROT_WRITE, + MAP_SHARED, O_RDWR, PROT_READ, PROT_WRITE, c_uint, c_ulong, c_void, close, ioctl, mmap, + open, }; use crate::{ - shmem::{ShMem, ShMemId, ShMemProvider}, Error, + shmem::{ShMem, ShMemId, ShMemProvider}, }; /// An ashmem based impl for linux/android @@ -1387,13 +1394,13 @@ pub mod unix_shmem { use std::{ffi::CString, os::fd::IntoRawFd}; use libc::{ - c_void, close, fstat, ftruncate, mmap, munmap, MAP_SHARED, PROT_READ, PROT_WRITE, + MAP_SHARED, PROT_READ, PROT_WRITE, c_void, close, fstat, ftruncate, mmap, munmap, }; - use nix::sys::memfd::{memfd_create, MemFdCreateFlag}; + use nix::sys::memfd::{MemFdCreateFlag, memfd_create}; use crate::{ - shmem::{ShMem, ShMemId, ShMemProvider}, Error, + shmem::{ShMem, ShMemId, ShMemProvider}, }; /// An memfd based impl for linux/android @@ -1567,19 +1574,19 @@ pub mod win32_shmem { use uuid::Uuid; use windows::{ - core::PCSTR, Win32::{ Foundation::{CloseHandle, HANDLE}, System::Memory::{ - CreateFileMappingA, MapViewOfFile, OpenFileMappingA, UnmapViewOfFile, - FILE_MAP_ALL_ACCESS, MEMORY_MAPPED_VIEW_ADDRESS, PAGE_READWRITE, + CreateFileMappingA, FILE_MAP_ALL_ACCESS, MEMORY_MAPPED_VIEW_ADDRESS, MapViewOfFile, + OpenFileMappingA, PAGE_READWRITE, UnmapViewOfFile, }, }, + core::PCSTR, }; use crate::{ - shmem::{ShMem, ShMemId, ShMemProvider}, Error, + shmem::{ShMem, ShMemId, ShMemProvider}, }; const INVALID_HANDLE_VALUE: *mut c_void = -1isize as *mut c_void; @@ -1854,8 +1861,8 @@ mod tests { use serial_test::serial; use crate::{ - shmem::{ShMemProvider, StdShMemProvider}, AsSlice, AsSliceMut, Error, + shmem::{ShMemProvider, StdShMemProvider}, }; #[test] diff --git a/libafl_bolts/src/staterestore.rs b/libafl_bolts/src/staterestore.rs index ebce2913f3..f86c3777e7 100644 --- a/libafl_bolts/src/staterestore.rs +++ b/libafl_bolts/src/staterestore.rs @@ -16,11 +16,11 @@ use std::{ }; use ahash::RandomState; -use serde::{de::DeserializeOwned, Serialize}; +use serde::{Serialize, de::DeserializeOwned}; use crate::{ - shmem::{ShMem, ShMemProvider}, AsSlice, Error, + shmem::{ShMem, ShMemProvider}, }; /// If the saved page content equals exactly this buf, the restarted child wants to exit cleanly. @@ -52,7 +52,10 @@ impl StateShMemContent { pub fn buf_len_checked(&self, shmem_size: usize) -> Result { let buf_len = unsafe { read_volatile(&self.buf_len) }; if size_of::() + buf_len > shmem_size { - Err(Error::illegal_state(format!("Stored buf_len is larger than the shared map! Shared data corrupted? Expected {shmem_size} bytes max, but got {} (buf_len {buf_len})", size_of::() + buf_len))) + Err(Error::illegal_state(format!( + "Stored buf_len is larger than the shared map! Shared data corrupted? Expected {shmem_size} bytes max, but got {} (buf_len {buf_len})", + size_of::() + buf_len + ))) } else { Ok(buf_len) } @@ -81,8 +84,11 @@ where } /// Writes this [`StateRestorer`] to env variable, to be restored later - pub fn write_to_env(&self, env_name: &str) -> Result<(), Error> { - self.shmem.write_to_env(env_name) + /// + /// # Safety + /// Alters the env. Should only be called from a single thread. + pub unsafe fn write_to_env(&self, env_name: &str) -> Result<(), Error> { + unsafe { self.shmem.write_to_env(env_name) } } /// Create a [`StateRestorer`] from `env` variable name diff --git a/libafl_bolts/src/subrange.rs b/libafl_bolts/src/subrange.rs index 58a356148e..1228723a3a 100644 --- a/libafl_bolts/src/subrange.rs +++ b/libafl_bolts/src/subrange.rs @@ -7,8 +7,8 @@ use core::{ }; use crate::{ - ownedref::{OwnedMutSlice, OwnedSlice}, HasLen, + ownedref::{OwnedMutSlice, OwnedSlice}, }; /// An immutable contiguous subslice of a byte slice. diff --git a/libafl_bolts/src/tuples.rs b/libafl_bolts/src/tuples.rs index 21f4647342..42ccfb77cd 100644 --- a/libafl_bolts/src/tuples.rs +++ b/libafl_bolts/src/tuples.rs @@ -2,6 +2,7 @@ #[cfg(feature = "alloc")] use alloc::{borrow::Cow, vec::Vec}; +use core::{any::TypeId, mem::transmute}; #[cfg(feature = "alloc")] use core::{ any::type_name, @@ -9,17 +10,16 @@ use core::{ marker::PhantomData, ops::{Deref, DerefMut, Index, IndexMut}, }; -use core::{any::TypeId, mem::transmute}; #[cfg(feature = "alloc")] use serde::{Deserialize, Serialize}; -pub use tuple_list::{tuple_list, tuple_list_type, TupleList}; +pub use tuple_list::{TupleList, tuple_list, tuple_list_type}; -#[cfg(any(feature = "xxh3", feature = "alloc"))] -use crate::hash_std; use crate::HasLen; #[cfg(feature = "alloc")] use crate::Named; +#[cfg(any(feature = "xxh3", feature = "alloc"))] +use crate::hash_std; /// Returns if the type `T` is equal to `U`, ignoring lifetimes. #[must_use] @@ -809,7 +809,7 @@ macro_rules! tuple_for_each_mut { /// ```rust /// use libafl_bolts::{ /// map_tuple_list_type, -/// tuples::{tuple_list, tuple_list_type, Map, MappingFunctor}, +/// tuples::{Map, MappingFunctor, tuple_list, tuple_list_type}, /// }; /// /// struct Wrapper(T); @@ -844,7 +844,7 @@ macro_rules! map_tuple_list_type { /// ```rust /// use libafl_bolts::{ /// merge_tuple_list_type, -/// tuples::{tuple_list, tuple_list_type, Merge}, +/// tuples::{Merge, tuple_list, tuple_list_type}, /// }; /// /// struct A; @@ -919,7 +919,7 @@ mod test { #[cfg(feature = "alloc")] use crate::ownedref::OwnedMutSlice; - use crate::tuples::{type_eq, Map, MappingFunctor, Merge}; + use crate::tuples::{Map, MappingFunctor, Merge, type_eq}; #[test] // for type name tests diff --git a/libafl_cc/Cargo.toml b/libafl_cc/Cargo.toml index 6974aeddcf..3723ee2b67 100644 --- a/libafl_cc/Cargo.toml +++ b/libafl_cc/Cargo.toml @@ -8,8 +8,8 @@ repository = "https://github.com/AFLplusplus/LibAFL/" readme = "README.md" license = "MIT OR Apache-2.0" keywords = ["fuzzing", "testing", "compiler"] -edition = "2021" -rust-version = "1.82" +edition = "2024" +rust-version = "1.85" categories = [ "development-tools::testing", "emulators", diff --git a/libafl_cc/build.rs b/libafl_cc/build.rs index 7cf17f6a0c..ec290d72a5 100644 --- a/libafl_cc/build.rs +++ b/libafl_cc/build.rs @@ -231,22 +231,32 @@ fn build_pass( Ok(s) => { if !s.success() { if required { - panic!("Failed to compile required compiler pass src/{src_file} - Exit status: {s}"); + panic!( + "Failed to compile required compiler pass src/{src_file} - Exit status: {s}" + ); } else { - println!("cargo:warning=Skipping non-required compiler pass src/{src_file} - Reason: Exit status {s}. You can ignore this error unless you want this compiler pass."); + println!( + "cargo:warning=Skipping non-required compiler pass src/{src_file} - Reason: Exit status {s}. You can ignore this error unless you want this compiler pass." + ); } } } Err(err) => { if required { - panic!("Failed to compile required compiler pass src/{src_file} - Exit status: {err}"); + panic!( + "Failed to compile required compiler pass src/{src_file} - Exit status: {err}" + ); } else { - println!("cargo:warning=Skipping non-required compiler pass src/{src_file} - Reason: Exit status {err}. You can ignore this error unless you want this compiler pass."); + println!( + "cargo:warning=Skipping non-required compiler pass src/{src_file} - Reason: Exit status {err}. You can ignore this error unless you want this compiler pass." + ); } } }, None => { - println!("cargo:warning=Skipping compiler pass src/{src_file} - Only supported on Windows or *nix."); + println!( + "cargo:warning=Skipping compiler pass src/{src_file} - Only supported on Windows or *nix." + ); } } } @@ -350,7 +360,11 @@ pub const LIBAFL_CC_LLVM_VERSION: Option = None; found = false; } - assert!(found, "\n\tAt least one of the LLVM dependencies could not be found.\n\tThe following search directory was considered: {}\n", bindir_path.display()); + assert!( + found, + "\n\tAt least one of the LLVM dependencies could not be found.\n\tThe following search directory was considered: {}\n", + bindir_path.display() + ); let cxxflags = if let Ok(flags) = llvm_cxxflags { flags diff --git a/libafl_cc/src/ar.rs b/libafl_cc/src/ar.rs index fefc43afc0..f42abcd8a9 100644 --- a/libafl_cc/src/ar.rs +++ b/libafl_cc/src/ar.rs @@ -3,7 +3,7 @@ use std::{env, path::PathBuf, str::FromStr}; -use crate::{Error, ToolWrapper, LIB_EXT, LIB_PREFIX}; +use crate::{Error, LIB_EXT, LIB_PREFIX, ToolWrapper}; include!(concat!(env!("OUT_DIR"), "/clang_constants.rs")); diff --git a/libafl_cc/src/clang.rs b/libafl_cc/src/clang.rs index 2e5239c250..bf733b54e7 100644 --- a/libafl_cc/src/clang.rs +++ b/libafl_cc/src/clang.rs @@ -6,7 +6,7 @@ use std::{ str::FromStr, }; -use crate::{CompilerWrapper, Error, ToolWrapper, LIB_EXT, LIB_PREFIX}; +use crate::{CompilerWrapper, Error, LIB_EXT, LIB_PREFIX, ToolWrapper}; /// The `OUT_DIR` for `LLVM` compiler passes pub const OUT_DIR: &str = env!("OUT_DIR"); diff --git a/libafl_cc/src/libtool.rs b/libafl_cc/src/libtool.rs index 1d3a07e892..7e944e6fd3 100644 --- a/libafl_cc/src/libtool.rs +++ b/libafl_cc/src/libtool.rs @@ -3,7 +3,7 @@ use std::{env, path::PathBuf, str::FromStr}; -use crate::{Error, ToolWrapper, LIB_EXT, LIB_PREFIX}; +use crate::{Error, LIB_EXT, LIB_PREFIX, ToolWrapper}; /// Wrap Clang #[expect(clippy::struct_excessive_bools)] diff --git a/libafl_concolic/symcc_runtime/src/lib.rs b/libafl_concolic/symcc_runtime/src/lib.rs index 08cbf523b0..b7824b51d7 100644 --- a/libafl_concolic/symcc_runtime/src/lib.rs +++ b/libafl_concolic/symcc_runtime/src/lib.rs @@ -46,7 +46,7 @@ pub mod cpp_runtime { } #[doc(hidden)] -pub use ctor::ctor; +pub use ctor; use libafl::observers::concolic; pub use libafl_bolts::shmem::StdShMem; #[doc(hidden)] @@ -333,12 +333,15 @@ macro_rules! export_runtime { // mean that this is 'safe'. static mut GLOBAL_DATA: Option<$rt> = None; - #[cfg_attr(not(test), $crate::ctor)] - fn init() { - // See comment on GLOBAL_DATA declaration. - unsafe { - GLOBAL_DATA = Some($constructor); - $crate::atexit(fini); + #[cfg(not(test))] + $crate::ctor::declarative::ctor! { + #[ctor] + fn init() { + // See comment on GLOBAL_DATA declaration. + unsafe { + GLOBAL_DATA = Some($constructor); + $crate::atexit(fini); + } } } diff --git a/libafl_concolic/symcc_runtime/src/tracing.rs b/libafl_concolic/symcc_runtime/src/tracing.rs index 3985fc913e..60c9419f73 100644 --- a/libafl_concolic/symcc_runtime/src/tracing.rs +++ b/libafl_concolic/symcc_runtime/src/tracing.rs @@ -44,14 +44,14 @@ where macro_rules! expression_builder { ($method_name:ident ( $($param_name:ident : $param_type:ty ),+ ) => $message:ident) => { // #[expect(clippy::missing_safety_doc)] - #[no_mangle] + #[unsafe(no_mangle)] fn $method_name(&mut self, $( $param_name : $param_type, )+ ) -> Option { self.write_message(SymExpr::$message { $($param_name,)+ }) } }; ($method_name:ident () => $message:ident) => { // #[expect(clippy::missing_safety_doc)] - #[no_mangle] + #[unsafe(no_mangle)] fn $method_name(&mut self) -> Option { self.write_message(SymExpr::$message) } @@ -74,7 +74,7 @@ impl Runtime for TracingRuntime where SHM: ShMem, { - #[no_mangle] + #[unsafe(no_mangle)] fn build_integer_from_buffer( &mut self, _buffer: *mut core::ffi::c_void, diff --git a/libafl_concolic/test/dump_constraints/src/main.rs b/libafl_concolic/test/dump_constraints/src/main.rs index 34d12b6322..196a2f5245 100644 --- a/libafl_concolic/test/dump_constraints/src/main.rs +++ b/libafl_concolic/test/dump_constraints/src/main.rs @@ -64,16 +64,24 @@ fn main() { let concolic_shmem = shmemprovider .new_shmem(1024 * 1024 * 1024) .expect("unable to create shared mapping"); - concolic_shmem - .write_to_env(DEFAULT_ENV_NAME) - .expect("unable to write shared mapping info to environment"); + // # Safety + // Single-threaded env variable access + unsafe { + concolic_shmem + .write_to_env(DEFAULT_ENV_NAME) + .expect("unable to write shared mapping info to environment"); + } let coverage_map = StdShMemProvider::new() .unwrap() .new_shmem(COVERAGE_MAP_SIZE) .unwrap(); - //let the forkserver know the shmid - coverage_map.write_to_env(HITMAP_ENV_NAME).unwrap(); + // let the forkserver know the shmid + // # Safety + // Single-threaded env variable access + unsafe { + coverage_map.write_to_env(HITMAP_ENV_NAME).unwrap(); + } if let Some(symbolize_offsets) = opt.symbolize_offsets { std::env::set_var( diff --git a/libafl_concolic/test/runtime_test/Cargo.toml b/libafl_concolic/test/runtime_test/Cargo.toml index ae700eece3..bfddd19ace 100644 --- a/libafl_concolic/test/runtime_test/Cargo.toml +++ b/libafl_concolic/test/runtime_test/Cargo.toml @@ -1,9 +1,10 @@ [package] name = "runtime_test" version.workspace = true -edition = "2021" +edition = "2024" +rust-version = "1.85" authors = ["Julius Hohnerlein "] -description = "Runtime test of LibAFL fuzzing with symbolicc execution" +description = "Runtime test of LibAFL fuzzing with symbolic execution" documentation = "https://docs.rs/libafl" repository = "https://github.com/AFLplusplus/LibAFL/" readme = "../README.md" diff --git a/libafl_concolic/test/runtime_test/src/lib.rs b/libafl_concolic/test/runtime_test/src/lib.rs index d6ec636d97..e3846b78ee 100644 --- a/libafl_concolic/test/runtime_test/src/lib.rs +++ b/libafl_concolic/test/runtime_test/src/lib.rs @@ -3,14 +3,9 @@ #![forbid(unexpected_cfgs)] //! Just a small runtime to be used in the smoke test. -use symcc_runtime::{ - export_runtime, - filter::NoFloat, - tracing::{self, StdShMemMessageFileWriter}, - Runtime, StdShMem, -}; - -// use libafl_bolts::StdShmem; +#[cfg(not(test))] +use symcc_runtime::tracing::StdShMemMessageFileWriter; +use symcc_runtime::{Runtime, StdShMem, export_runtime, filter::NoFloat, tracing}; export_runtime!( NoFloat => NoFloat; diff --git a/libafl_derive/Cargo.toml b/libafl_derive/Cargo.toml index cd2d76a61b..4079aba2e4 100644 --- a/libafl_derive/Cargo.toml +++ b/libafl_derive/Cargo.toml @@ -8,8 +8,8 @@ repository = "https://github.com/AFLplusplus/LibAFL/" readme = "../README.md" license = "MIT OR Apache-2.0" keywords = ["fuzzing", "testing"] -edition = "2021" -rust-version = "1.82" +edition = "2024" +rust-version = "1.85" categories = [ "development-tools::testing", "emulators", diff --git a/libafl_derive/src/lib.rs b/libafl_derive/src/lib.rs index 354bbc9ca4..fe723de932 100644 --- a/libafl_derive/src/lib.rs +++ b/libafl_derive/src/lib.rs @@ -43,7 +43,7 @@ use proc_macro::TokenStream; use quote::quote; -use syn::{parse_macro_input, Data::Struct, DeriveInput, Field, Fields::Named, Type}; +use syn::{Data::Struct, DeriveInput, Field, Fields::Named, Type, parse_macro_input}; /// Derive macro to implement `SerdeAny`, to use a type in a `SerdeAnyMap` #[proc_macro_derive(SerdeAny)] diff --git a/libafl_frida/Cargo.toml b/libafl_frida/Cargo.toml index b02e2292f5..d2d1344343 100644 --- a/libafl_frida/Cargo.toml +++ b/libafl_frida/Cargo.toml @@ -8,7 +8,7 @@ repository = "https://github.com/AFLplusplus/LibAFL/" readme = "../README.md" license = "MIT OR Apache-2.0" keywords = ["fuzzing", "frida", "instrumentation"] -edition = "2021" +edition = "2024" categories = [ "development-tools::testing", "emulators", diff --git a/libafl_frida/src/alloc.rs b/libafl_frida/src/alloc.rs index b0d945b8ea..7b07bd4427 100644 --- a/libafl_frida/src/alloc.rs +++ b/libafl_frida/src/alloc.rs @@ -222,7 +222,7 @@ impl Allocator { self.map_shadow_for_region( mapping.as_ptr() as usize, - mapping.as_ptr().add(rounded_up_size) as usize, + unsafe { mapping.as_ptr().add(rounded_up_size) as usize }, false, ); let address = mapping.as_ptr() as usize; @@ -243,10 +243,12 @@ impl Allocator { self.largest_allocation = std::cmp::max(self.largest_allocation, metadata.actual_size); // unpoison the shadow memory for the allocation itself - Self::unpoison( - map_to_shadow!(self, metadata.address + self.page_size), - size, - ); + unsafe { + Self::unpoison( + map_to_shadow!(self, metadata.address + self.page_size), + size, + ); + } let address = (metadata.address + self.page_size) as *mut c_void; self.allocations.insert(address as usize, metadata); @@ -285,7 +287,9 @@ impl Allocator { } // poison the shadow memory for the allocation - Self::poison(shadow_mapping_start, metadata.size); + unsafe { + Self::poison(shadow_mapping_start, metadata.size); + } } /// Finds the metadata for the allocation at the given address. @@ -798,7 +802,9 @@ impl Allocator { self.using_pre_allocated_shadow_mapping = true; break; } - log::warn!("shadow_bit {try_shadow_bit:} is not suitable - failed to allocate shadow memory"); + log::warn!( + "shadow_bit {try_shadow_bit:} is not suitable - failed to allocate shadow memory" + ); } } } diff --git a/libafl_frida/src/asan/asan_rt.rs b/libafl_frida/src/asan/asan_rt.rs index cf640e058e..d2a71e597f 100644 --- a/libafl_frida/src/asan/asan_rt.rs +++ b/libafl_frida/src/asan/asan_rt.rs @@ -16,14 +16,14 @@ use std::{ }; use backtrace::Backtrace; -use dynasmrt::{dynasm, DynasmApi, DynasmLabelApi}; +use dynasmrt::{DynasmApi, DynasmLabelApi, dynasm}; #[cfg(target_arch = "x86_64")] use frida_gum::instruction_writer::X86Register; #[cfg(target_arch = "aarch64")] use frida_gum::instruction_writer::{Aarch64Register, IndexMode}; use frida_gum::{ - instruction_writer::InstructionWriter, interceptor::Interceptor, stalker::StalkerOutput, Gum, - Module, ModuleMap, NativePointer, PageProtection, Process, RangeDetails, + Gum, Module, ModuleMap, NativePointer, PageProtection, Process, RangeDetails, + instruction_writer::InstructionWriter, interceptor::Interceptor, stalker::StalkerOutput, }; use frida_gum_sys::Insn; use hashbrown::HashMap; @@ -42,23 +42,23 @@ use yaxpeax_x86::{ #[cfg(target_arch = "x86_64")] use crate::utils::frida_to_cs; +#[cfg(target_arch = "x86_64")] +use crate::utils::{AccessType, operand_details}; #[cfg(target_arch = "aarch64")] use crate::utils::{instruction_width, writer_register}; -#[cfg(target_arch = "x86_64")] -use crate::utils::{operand_details, AccessType}; use crate::{ alloc::Allocator, - asan::errors::{AsanError, AsanErrors, AsanReadWriteError, ASAN_ERRORS}, + asan::errors::{ASAN_ERRORS, AsanError, AsanErrors, AsanReadWriteError}, helper::{FridaRuntime, SkipRange}, utils::disas_count, }; -extern "C" { +unsafe extern "C" { fn __register_frame(begin: *mut c_void); } #[cfg(not(target_vendor = "apple"))] -extern "C" { +unsafe extern "C" { fn tls_ptr() -> *const c_void; } @@ -144,7 +144,7 @@ impl Lock { } #[cfg(any(target_os = "linux", target_vendor = "apple"))] -use errno::{errno, set_errno, Errno}; +use errno::{Errno, errno, set_errno}; #[cfg(target_os = "windows")] use winapi::shared::minwindef::DWORD; /// We need to save and restore the last error in the hooks @@ -315,7 +315,9 @@ impl FridaRuntime for AsanRuntime { } })); - self.register_hooks(gum); + unsafe { + self.register_hooks(gum); + } self.generate_instrumentation_blobs(); self.unpoison_all_existing_memory(); self.register_thread(); @@ -410,7 +412,9 @@ impl AsanRuntime { pub unsafe fn poison(&mut self, address: usize, size: usize) { let start = self.allocator_mut().map_to_shadow(address); if self.allocator_mut().valid_shadow(start, size) { - Allocator::poison(start, size); + unsafe { + Allocator::poison(start, size); + } } } @@ -452,7 +456,7 @@ impl AsanRuntime { let (stack_start, stack_end) = Self::current_stack(); let (tls_start, tls_end) = Self::current_tls(); println!( - "registering thread {:?} with stack {stack_start:x}:{stack_end:x} and tls {tls_start:x}:{tls_end:x}", + "registering thread {:?} with stack {stack_start:x}:{stack_end:x} and tls {tls_start:x}:{tls_end:x}", get_thread_id() ); self.allocator_mut() @@ -593,14 +597,16 @@ impl AsanRuntime { } /// Register the required hooks + /// + /// # Safety + /// Registers a hook for an existing location, the hook can read and write mem freely, so.. #[expect(clippy::too_many_lines)] - pub fn register_hooks(&mut self, gum: &Gum) { + pub unsafe fn register_hooks(&mut self, gum: &Gum) { let mut interceptor = Interceptor::obtain(gum); let process = Process::obtain(gum); macro_rules! hook_func { ($name:ident, ($($param:ident : $param_type:ty),*), $return_type:ty) => { paste::paste! { - let target_function = Module::find_global_export_by_name(stringify!($name)).expect("Failed to find function"); log::warn!("Hooking {} = {:?}", stringify!($name), target_function.0); @@ -610,6 +616,7 @@ impl AsanRuntime { #[allow(non_snake_case)] unsafe extern "C" fn []($($param: $param_type),*) -> $return_type { + unsafe { let _last_error_guard = LastErrorGuard::new(); let mut invocation = Interceptor::current_invocation(); let this = &mut *(invocation.replacement_data().unwrap().0 as *mut AsanRuntime); @@ -633,6 +640,7 @@ impl AsanRuntime { } (original)($($param),*) } + } let self_ptr = core::ptr::from_ref(self) as usize; let _ = interceptor.replace( @@ -658,6 +666,7 @@ impl AsanRuntime { #[allow(non_snake_case)] unsafe extern "C" fn []($($param: $param_type),*) -> $return_type { + unsafe { let _last_error_guard = LastErrorGuard::new(); let mut invocation = Interceptor::current_invocation(); let this = &mut *(invocation.replacement_data().unwrap().0 as *mut AsanRuntime); @@ -674,6 +683,7 @@ impl AsanRuntime { } (original)($($param),*) } + } let self_ptr = core::ptr::from_ref(self) as usize; let _ = interceptor.replace( @@ -702,6 +712,7 @@ impl AsanRuntime { #[allow(non_snake_case)] // depends on the values the macro is invoked with #[allow(clippy::redundant_else)] unsafe extern "C" fn []($($param: $param_type),*) -> $return_type { + unsafe { let _last_error_guard = LastErrorGuard::new(); let mut invocation = Interceptor::current_invocation(); let this = &mut *(invocation.replacement_data().unwrap().0 as *mut AsanRuntime); @@ -737,6 +748,7 @@ impl AsanRuntime { } (original)($($param),*) } + } let self_ptr = core::ptr::from_ref(self) as usize; let _ = interceptor.replace( @@ -762,7 +774,7 @@ impl AsanRuntime { unsafe extern "C" fn []($($param: $param_type),*) -> $return_type { let _last_error_guard = LastErrorGuard::new(); let mut invocation = Interceptor::current_invocation(); - let this = &mut *(invocation.replacement_data().unwrap().0 as *mut AsanRuntime); + let this = unsafe { &mut *(invocation.replacement_data().unwrap().0 as *mut AsanRuntime) }; let original = [<$lib_ident:snake:upper _ $name:snake:upper _PTR>].get().unwrap(); if $always_enabled || this.hooks_enabled { if has_tls() { @@ -1690,9 +1702,9 @@ impl AsanRuntime { )[0]; if insn.opcode == Opcode::MSR && insn.operands[0] == Operand::SystemReg(23056) { //the first operand is nzcv - //What case is this for?? - /*insn = instructions.get(2).unwrap(); - actual_pc = insn.address() as usize;*/ + //What case is this for?? + /*insn = instructions.get(2).unwrap(); + actual_pc = insn.address() as usize;*/ } let operands_len = insn diff --git a/libafl_frida/src/asan/errors.rs b/libafl_frida/src/asan/errors.rs index 26a14d72c4..0c1cd4534b 100644 --- a/libafl_frida/src/asan/errors.rs +++ b/libafl_frida/src/asan/errors.rs @@ -8,21 +8,21 @@ use std::{ }; use backtrace::Backtrace; -use color_backtrace::{default_output_stream, BacktracePrinter, Verbosity}; +use color_backtrace::{BacktracePrinter, Verbosity, default_output_stream}; #[cfg(target_arch = "aarch64")] use frida_gum::interceptor::Interceptor; use frida_gum::{Gum, Process}; use libafl::{ + Error, HasMetadata, corpus::Testcase, executors::ExitKind, feedbacks::{Feedback, StateInitializer}, observers::Observer, - Error, HasMetadata, }; use libafl_bolts::{ + Named, SerdeAny, ownedref::OwnedPtr, tuples::{Handle, Handled, MatchNameRef}, - Named, SerdeAny, }; use mmap_rs::MmapOptions; use serde::{Deserialize, Serialize}; diff --git a/libafl_frida/src/asan/hook_funcs.rs b/libafl_frida/src/asan/hook_funcs.rs index 680da84ae4..e523df8a8a 100644 --- a/libafl_frida/src/asan/hook_funcs.rs +++ b/libafl_frida/src/asan/hook_funcs.rs @@ -13,11 +13,11 @@ use crate::{ }; #[cfg(windows)] -extern "system" { +unsafe extern "system" { fn memcpy(dst: *mut c_void, src: *const c_void, size: usize) -> *mut c_void; } #[cfg(windows)] -extern "system" { +unsafe extern "system" { fn memset(s: *mut c_void, c: i32, n: usize) -> *mut c_void; } @@ -278,7 +278,7 @@ impl AsanRuntime { }; if flags & 8 == 8 { - extern "system" { + unsafe extern "system" { fn memset(s: *mut c_void, c: i32, n: usize) -> *mut c_void; } unsafe { @@ -323,7 +323,7 @@ impl AsanRuntime { }; if flags & 8 == 8 { - extern "system" { + unsafe extern "system" { fn memset(s: *mut c_void, c: i32, n: usize) -> *mut c_void; } unsafe { @@ -619,7 +619,7 @@ impl AsanRuntime { let ret = unsafe { self.allocator_mut().alloc(size, 8) }; if flags & 0x40 == 0x40 { - extern "system" { + unsafe extern "system" { fn memset(s: *mut c_void, c: i32, n: usize) -> *mut c_void; } unsafe { @@ -847,7 +847,7 @@ impl AsanRuntime { log::trace!("hook__Znwm"); let result = unsafe { self.allocator_mut().alloc(size, 8) }; if result.is_null() { - extern "system" { + unsafe extern "system" { fn _ZSt17__throw_bad_allocv(); } @@ -885,7 +885,7 @@ impl AsanRuntime { log::trace!("hook__ZnwmSt11align_val_t"); let result = unsafe { self.allocator_mut().alloc(size, alignment) }; if result.is_null() { - extern "system" { + unsafe extern "system" { fn _ZSt17__throw_bad_allocv(); } @@ -930,7 +930,7 @@ impl AsanRuntime { nmemb: usize, size: usize, ) -> *mut c_void { - extern "system" { + unsafe extern "system" { fn memset(s: *mut c_void, c: i32, n: usize) -> *mut c_void; } log::trace!("hook_calloc"); @@ -954,7 +954,7 @@ impl AsanRuntime { nmemb: usize, size: usize, ) -> *mut c_void { - extern "system" { + unsafe extern "system" { fn memset(s: *mut c_void, c: i32, n: usize) -> *mut c_void; } log::trace!("hook__o_calloc"); @@ -1629,7 +1629,9 @@ impl AsanRuntime { log::trace!("hook_munmap"); let res = original(addr, length); if res != -1 { - Allocator::poison(self.allocator_mut().map_to_shadow(addr as usize), length); + unsafe { + Allocator::poison(self.allocator_mut().map_to_shadow(addr as usize), length); + } } res } @@ -2063,7 +2065,7 @@ impl AsanRuntime { s: *mut c_char, c: i32, ) -> *mut c_char { - extern "system" { + unsafe extern "system" { fn strlen(s: *const c_char) -> usize; } @@ -2091,7 +2093,7 @@ impl AsanRuntime { s: *mut c_char, c: i32, ) -> *mut c_char { - extern "system" { + unsafe extern "system" { fn strlen(s: *const c_char) -> usize; } log::trace!("hook_strrchr"); @@ -2118,7 +2120,7 @@ impl AsanRuntime { s1: *const c_char, s2: *const c_char, ) -> i32 { - extern "system" { + unsafe extern "system" { fn strlen(s: *const c_char) -> usize; } log::trace!("hook_strcasecmp"); @@ -2192,7 +2194,7 @@ impl AsanRuntime { s1: *mut c_char, s2: *const c_char, ) -> *mut c_char { - extern "system" { + unsafe extern "system" { fn strlen(s: *const c_char) -> usize; } log::trace!("hook_strcat"); @@ -2232,7 +2234,7 @@ impl AsanRuntime { s1: *const c_char, s2: *const c_char, ) -> i32 { - extern "system" { + unsafe extern "system" { fn strlen(s: *const c_char) -> usize; } log::trace!("hook_strcmp"); @@ -2273,7 +2275,7 @@ impl AsanRuntime { s2: *const c_char, n: usize, ) -> i32 { - extern "system" { + unsafe extern "system" { fn strnlen(s: *const c_char, n: usize) -> usize; } log::trace!("hook_strncmp"); @@ -2313,7 +2315,7 @@ impl AsanRuntime { dest: *mut c_char, src: *const c_char, ) -> *mut c_char { - extern "system" { + unsafe extern "system" { fn strlen(s: *const c_char) -> usize; } log::trace!("hook_strcpy"); @@ -2354,7 +2356,7 @@ impl AsanRuntime { src: *const c_char, n: usize, ) -> *mut c_char { - extern "system" { + unsafe extern "system" { fn strlen(s: *const c_char) -> usize; } log::trace!("hook_strncpy"); @@ -2391,7 +2393,7 @@ impl AsanRuntime { dest: *mut c_char, src: *const c_char, ) -> *mut c_char { - extern "system" { + unsafe extern "system" { fn strlen(s: *const c_char) -> usize; } log::trace!("hook_stpcpy"); @@ -2440,7 +2442,7 @@ impl AsanRuntime { _original: extern "C" fn(s: *const c_char) -> *mut c_char, s: *const c_char, ) -> *mut c_char { - extern "system" { + unsafe extern "system" { fn strlen(s: *const c_char) -> usize; fn strcpy(dest: *mut c_char, src: *const c_char) -> *mut c_char; } @@ -2517,7 +2519,7 @@ impl AsanRuntime { haystack: *const c_char, needle: *const c_char, ) -> *mut c_char { - extern "system" { + unsafe extern "system" { fn strlen(s: *const c_char) -> usize; } log::trace!("hook_strstr"); @@ -2557,7 +2559,7 @@ impl AsanRuntime { haystack: *const c_char, needle: *const c_char, ) -> *mut c_char { - extern "system" { + unsafe extern "system" { fn strlen(s: *const c_char) -> usize; } log::trace!("hook_strcasestr"); @@ -2596,7 +2598,7 @@ impl AsanRuntime { original: extern "C" fn(s: *const c_char) -> i32, s: *const c_char, ) -> i32 { - extern "system" { + unsafe extern "system" { fn strlen(s: *const c_char) -> usize; } log::trace!("hook_atoi"); @@ -2623,7 +2625,7 @@ impl AsanRuntime { original: extern "C" fn(s: *const c_char) -> i32, s: *const c_char, ) -> i32 { - extern "system" { + unsafe extern "system" { fn strlen(s: *const c_char) -> usize; } log::trace!("hook_atol"); @@ -2650,7 +2652,7 @@ impl AsanRuntime { original: extern "C" fn(s: *const c_char) -> i64, s: *const c_char, ) -> i64 { - extern "system" { + unsafe extern "system" { fn strlen(s: *const c_char) -> usize; } log::trace!("hook_atoll"); @@ -2703,7 +2705,7 @@ impl AsanRuntime { dest: *mut wchar_t, src: *const wchar_t, ) -> *mut wchar_t { - extern "system" { + unsafe extern "system" { fn wcslen(s: *const wchar_t) -> usize; } log::trace!("hook_wcscpy"); @@ -2744,7 +2746,7 @@ impl AsanRuntime { s1: *const wchar_t, s2: *const wchar_t, ) -> i32 { - extern "system" { + unsafe extern "system" { fn wcslen(s: *const wchar_t) -> usize; } log::trace!("hook_wcscmp"); diff --git a/libafl_frida/src/cmplog_rt.rs b/libafl_frida/src/cmplog_rt.rs index 687ab5ce8e..c695296294 100644 --- a/libafl_frida/src/cmplog_rt.rs +++ b/libafl_frida/src/cmplog_rt.rs @@ -30,7 +30,7 @@ use iced_x86::{ OpKind, Register, }; use libafl::Error; -use libafl_targets::{cmps::__libafl_targets_cmplog_instructions, CMPLOG_MAP_W}; +use libafl_targets::{CMPLOG_MAP_W, cmps::__libafl_targets_cmplog_instructions}; use rangemap::RangeMap; use crate::helper::FridaRuntime; diff --git a/libafl_frida/src/coverage_rt.rs b/libafl_frida/src/coverage_rt.rs index f73a78ea17..0c8c991963 100644 --- a/libafl_frida/src/coverage_rt.rs +++ b/libafl_frida/src/coverage_rt.rs @@ -4,8 +4,8 @@ use std::{cell::RefCell, marker::PhantomPinned, pin::Pin, rc::Rc}; #[cfg(target_arch = "aarch64")] use dynasmrt::DynasmLabelApi; -use dynasmrt::{dynasm, DynasmApi}; -use frida_gum::{instruction_writer::InstructionWriter, stalker::StalkerOutput, ModuleMap}; +use dynasmrt::{DynasmApi, dynasm}; +use frida_gum::{ModuleMap, instruction_writer::InstructionWriter, stalker::StalkerOutput}; use libafl_bolts::hash_std; use rangemap::RangeMap; diff --git a/libafl_frida/src/executor.rs b/libafl_frida/src/executor.rs index 83ba6dfeeb..88f280fd78 100644 --- a/libafl_frida/src/executor.rs +++ b/libafl_frida/src/executor.rs @@ -4,19 +4,19 @@ use std::process::abort; use std::{cell::RefCell, ffi::c_void, marker::PhantomData, rc::Rc}; use frida_gum::{ - stalker::{NoneEventSink, Stalker}, Gum, MemoryRange, NativePointer, + stalker::{NoneEventSink, Stalker}, }; #[cfg(windows)] use libafl::executors::{hooks::inprocess::InProcessHooks, inprocess::HasInProcessHooks}; use libafl::{ + Error, executors::{Executor, ExitKind, HasObservers, InProcessExecutor}, inputs::{Input, NopTargetBytesConverter, TargetBytesConverter}, observers::ObserversTuple, state::{HasCurrentTestcase, HasExecutions, HasSolutions}, - Error, }; -use libafl_bolts::{tuples::RefIndexable, AsSlice}; +use libafl_bolts::{AsSlice, tuples::RefIndexable}; #[cfg(not(test))] use crate::asan::errors::AsanErrors; diff --git a/libafl_frida/src/frida_helper_shutdown_observer.rs b/libafl_frida/src/frida_helper_shutdown_observer.rs index 7630cd12c1..23ea18eb6e 100644 --- a/libafl_frida/src/frida_helper_shutdown_observer.rs +++ b/libafl_frida/src/frida_helper_shutdown_observer.rs @@ -3,8 +3,8 @@ use std::{borrow::Cow, cell::RefCell, fmt, rc::Rc}; use libafl::{executors::ExitKind, inputs::HasTargetBytes, observers::Observer}; use libafl_bolts::{Error, Named}; use serde::{ - de::{self, Deserialize, Deserializer, MapAccess, Visitor}, Serialize, + de::{self, Deserialize, Deserializer, MapAccess, Visitor}, }; use crate::helper::{FridaInstrumentationHelper, FridaRuntimeTuple}; diff --git a/libafl_frida/src/helper.rs b/libafl_frida/src/helper.rs index 3e7a9fe0ac..de40a66551 100644 --- a/libafl_frida/src/helper.rs +++ b/libafl_frida/src/helper.rs @@ -9,9 +9,9 @@ use std::{ }; use frida_gum::{ + Backend, Gum, Module, ModuleMap, Script, instruction_writer::InstructionWriter, stalker::{StalkerIterator, StalkerOutput, Transformer}, - Backend, Gum, Module, ModuleMap, Script, }; use frida_gum_sys::gchar; use libafl::Error; @@ -21,7 +21,7 @@ use libafl_bolts::{ }; use libafl_targets::drcov::DrCovBasicBlock; #[cfg(unix)] -use nix::sys::mman::{mmap_anonymous, MapFlags, ProtFlags}; +use nix::sys::mman::{MapFlags, ProtFlags, mmap_anonymous}; use rangemap::RangeMap; #[cfg(target_arch = "aarch64")] use yaxpeax_arch::Arch; @@ -544,9 +544,9 @@ impl Debug for FridaInstrumentationHelper<'_, RT> { /// A callback function to test calling back from FRIDA's JavaScript scripting support /// # Safety /// This function receives a raw pointer to a C string -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn test_function(message: *const gchar) { - if let Ok(msg) = CStr::from_ptr(message).to_str() { + if let Ok(msg) = unsafe { CStr::from_ptr(message).to_str() } { println!("{msg}"); } } diff --git a/libafl_frida/src/lib.rs b/libafl_frida/src/lib.rs index 7be0c8133b..4f5d31c636 100644 --- a/libafl_frida/src/lib.rs +++ b/libafl_frida/src/lib.rs @@ -77,7 +77,7 @@ pub mod frida_helper_shutdown_observer; // for parsing asan and cmplog cores -use libafl_bolts::core_affinity::{get_core_ids, CoreId, Cores}; +use libafl_bolts::core_affinity::{CoreId, Cores, get_core_ids}; /// A representation of the various Frida options #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)] #[expect(clippy::struct_excessive_bools)] @@ -331,20 +331,20 @@ mod tests { use clap::Parser; use frida_gum::Gum; use libafl::{ + Fuzzer, StdFuzzer, corpus::{Corpus, InMemoryCorpus, Testcase}, events::NopEventManager, executors::{ExitKind, InProcessExecutor}, feedback_and_fast, feedback_or_fast, feedbacks::ConstFeedback, inputs::{BytesInput, HasTargetBytes}, - mutators::{mutations::BitFlipMutator, StdScheduledMutator}, + mutators::{StdScheduledMutator, mutations::BitFlipMutator}, schedulers::StdScheduler, stages::StdMutationalStage, state::{HasSolutions, StdState}, - Fuzzer, StdFuzzer, }; use libafl_bolts::{ - cli::FuzzerOptions, rands::StdRand, tuples::tuple_list, AsSlice, SimpleStdoutLogger, + AsSlice, SimpleStdoutLogger, cli::FuzzerOptions, rands::StdRand, tuples::tuple_list, }; use mimalloc::MiMalloc; diff --git a/libafl_frida/src/pthread_hook.rs b/libafl_frida/src/pthread_hook.rs index f986ab71a0..b988f1d50a 100644 --- a/libafl_frida/src/pthread_hook.rs +++ b/libafl_frida/src/pthread_hook.rs @@ -13,7 +13,7 @@ type pthread_introspection_hook_t = extern "C" fn( size: libc::size_t, ); -extern "C" { +unsafe extern "C" { fn pthread_introspection_hook_install( hook: *const pthread_introspection_hook_t, ) -> *const pthread_introspection_hook_t; diff --git a/libafl_frida/src/utils.rs b/libafl_frida/src/utils.rs index 2b59e366d9..68b286c86a 100644 --- a/libafl_frida/src/utils.rs +++ b/libafl_frida/src/utils.rs @@ -1,7 +1,7 @@ #[cfg(target_arch = "aarch64")] use frida_gum::instruction_writer::Aarch64Register; #[cfg(target_arch = "x86_64")] -use frida_gum::{instruction_writer::X86Register, CpuContext}; +use frida_gum::{CpuContext, instruction_writer::X86Register}; #[cfg(target_arch = "x86_64")] use libafl::Error; #[cfg(target_arch = "aarch64")] diff --git a/libafl_frida/src/windows_hooks.rs b/libafl_frida/src/windows_hooks.rs index 772ef469d5..1aab773d5b 100644 --- a/libafl_frida/src/windows_hooks.rs +++ b/libafl_frida/src/windows_hooks.rs @@ -1,23 +1,25 @@ // Based on the example of setting hooks: Https://github.com/frida/frida-rust/blob/main/examples/gum/hook_open/src/lib.rs use std::ffi::c_void; -use frida_gum::{interceptor::Interceptor, Gum, NativePointer, Process}; +use frida_gum::{Gum, NativePointer, Process, interceptor::Interceptor}; use libafl_bolts::os::windows_exceptions::{ - handle_exception, IsProcessorFeaturePresent, UnhandledExceptionFilter, EXCEPTION_POINTERS, - PROCESSOR_FEATURE_ID, + EXCEPTION_POINTERS, IsProcessorFeaturePresent, PROCESSOR_FEATURE_ID, UnhandledExceptionFilter, + handle_exception, }; unsafe extern "C" fn is_processor_feature_present_detour(feature: u32) -> bool { match feature { 0x17 => false, - _ => IsProcessorFeaturePresent(PROCESSOR_FEATURE_ID(feature)).as_bool(), + _ => unsafe { IsProcessorFeaturePresent(PROCESSOR_FEATURE_ID(feature)).as_bool() }, } } unsafe extern "C" fn unhandled_exception_filter_detour( exception_pointers: *mut EXCEPTION_POINTERS, ) -> i32 { - handle_exception(exception_pointers); - UnhandledExceptionFilter(exception_pointers) + unsafe { + handle_exception(exception_pointers); + UnhandledExceptionFilter(exception_pointers) + } } /// Initialize the hooks pub fn initialize(gum: &Gum) { diff --git a/libafl_intelpt/Cargo.toml b/libafl_intelpt/Cargo.toml index 10d29ea704..f8a6ee04d1 100644 --- a/libafl_intelpt/Cargo.toml +++ b/libafl_intelpt/Cargo.toml @@ -4,7 +4,7 @@ version.workspace = true authors = ["Marco Cavenati "] description = "Intel Processor Trace wrapper for libafl" repository = "https://github.com/AFLplusplus/LibAFL/" -edition = "2021" +edition = "2024" license.workspace = true readme = "./README.md" keywords = ["fuzzing", "testing", "security", "intelpt"] diff --git a/libafl_intelpt/src/linux.rs b/libafl_intelpt/src/linux.rs index aaffcbcfa7..786a1c715d 100644 --- a/libafl_intelpt/src/linux.rs +++ b/libafl_intelpt/src/linux.rs @@ -19,7 +19,7 @@ use std::{ use arbitrary_int::u4; use bitbybit::bitfield; use caps::{CapSet, Capability}; -use libafl_bolts::{hash_64_fast, Error}; +use libafl_bolts::{Error, hash_64_fast}; pub use libipt::{ asid::Asid, image::{Image, SectionCache, SectionInfo}, @@ -36,13 +36,13 @@ use libipt::{ use num_enum::TryFromPrimitive; use num_traits::{Euclid, SaturatingAdd}; use perf_event_open_sys::{ - bindings::{perf_event_attr, perf_event_mmap_page, PERF_FLAG_FD_CLOEXEC}, + bindings::{PERF_FLAG_FD_CLOEXEC, perf_event_attr, perf_event_mmap_page}, ioctls::{DISABLE, ENABLE, SET_FILTER}, perf_event_open, }; use raw_cpuid::CpuId; -use super::{availability, PAGE_SIZE}; +use super::{PAGE_SIZE, availability}; const PT_EVENT_PATH: &str = "/sys/bus/event_source/devices/intel_pt"; @@ -424,7 +424,9 @@ impl IntelPT { if trace_entry_iters.0 == offset { trace_entry_iters.1 += 1; if trace_entry_iters.1 > 1000 { - log::warn!("Decoder got stuck at trace offset {offset:x}. Make sure the decoder Image has the right content and offsets."); + log::warn!( + "Decoder got stuck at trace offset {offset:x}. Make sure the decoder Image has the right content and offsets." + ); break 'block; } } else { diff --git a/libafl_intelpt/tests/integration_tests_linux.rs b/libafl_intelpt/tests/integration_tests_linux.rs index f4b06f1061..e385c2b063 100644 --- a/libafl_intelpt/tests/integration_tests_linux.rs +++ b/libafl_intelpt/tests/integration_tests_linux.rs @@ -4,13 +4,13 @@ use std::{arch::asm, process}; -use libafl_intelpt::{availability, Image, IntelPT}; +use libafl_intelpt::{Image, IntelPT, availability}; use nix::{ sys::{ - signal::{kill, raise, Signal}, - wait::{waitpid, WaitPidFlag}, + signal::{Signal, kill, raise}, + wait::{WaitPidFlag, waitpid}, }, - unistd::{fork, ForkResult}, + unistd::{ForkResult, fork}, }; use proc_maps::get_process_maps; diff --git a/libafl_libfuzzer/Cargo.toml b/libafl_libfuzzer/Cargo.toml index a7b43448b4..f79a3f077e 100644 --- a/libafl_libfuzzer/Cargo.toml +++ b/libafl_libfuzzer/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/AFLplusplus/LibAFL/" readme = "../README.md" license = "MIT OR Apache-2.0" keywords = ["fuzzing", "testing", "security"] -edition = "2021" +edition = "2024" categories = ["development-tools::testing"] include = [ diff --git a/libafl_libfuzzer/build.rs b/libafl_libfuzzer/build.rs index 2f668e8542..ce15873c30 100644 --- a/libafl_libfuzzer/build.rs +++ b/libafl_libfuzzer/build.rs @@ -202,9 +202,9 @@ fn main() -> Result<(), Box> { drop(redefinitions_file); assert!( - nm_child.wait().is_ok_and(|s| s.success()), - "Couldn't link runtime crate! Do you have the llvm-tools component installed? (`rustup component add llvm-tools-preview` to install)" - ); + nm_child.wait().is_ok_and(|s| s.success()), + "Couldn't link runtime crate! Do you have the llvm-tools component installed? (`rustup component add llvm-tools-preview` to install)" + ); let mut objcopy_command = Command::new(rust_objcopy); @@ -245,9 +245,9 @@ fn main() -> Result<(), Box> { .args([&archive_path, &redefined_archive_path]); assert!( - objcopy_command.status().is_ok_and(|s| s.success()), - "Couldn't rename allocators in the runtime crate! Do you have the llvm-tools component installed? (`rustup component add llvm-tools-preview` to install)" - ); + objcopy_command.status().is_ok_and(|s| s.success()), + "Couldn't rename allocators in the runtime crate! Do you have the llvm-tools component installed? (`rustup component add llvm-tools-preview` to install)" + ); #[cfg(feature = "embed-runtime")] { diff --git a/libafl_libfuzzer/runtime/Cargo.toml.template b/libafl_libfuzzer/runtime/Cargo.toml.template index 585c6f14b7..ee096e74d4 100644 --- a/libafl_libfuzzer/runtime/Cargo.toml.template +++ b/libafl_libfuzzer/runtime/Cargo.toml.template @@ -1,7 +1,7 @@ [package] name = "libafl_libfuzzer_runtime" version = "0.15.1" -edition = "2021" +edition = "2024" publish = false # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -81,5 +81,5 @@ utf8-chars = "3.0.4" env_logger = "0.11.5" [build-dependencies] -bindgen = "0.70.1" +bindgen = "0.71.1" cc = { version = "1.1.22", features = ["parallel"] } diff --git a/libafl_libfuzzer/runtime/src/corpus.rs b/libafl_libfuzzer/runtime/src/corpus.rs index 448c7e4b0d..f9ba42ebb4 100644 --- a/libafl_libfuzzer/runtime/src/corpus.rs +++ b/libafl_libfuzzer/runtime/src/corpus.rs @@ -6,11 +6,11 @@ use std::{ sync::atomic::{AtomicU64, Ordering}, }; -use hashbrown::{hash_map::Entry, HashMap}; +use hashbrown::{HashMap, hash_map::Entry}; use libafl::{ corpus::{ - inmemory::{TestcaseStorage, TestcaseStorageMap}, Corpus, CorpusId, Testcase, + inmemory::{TestcaseStorage, TestcaseStorageMap}, }, inputs::Input, }; diff --git a/libafl_libfuzzer/runtime/src/feedbacks.rs b/libafl_libfuzzer/runtime/src/feedbacks.rs index c0b018db98..fbbfb3975a 100644 --- a/libafl_libfuzzer/runtime/src/feedbacks.rs +++ b/libafl_libfuzzer/runtime/src/feedbacks.rs @@ -3,15 +3,14 @@ use core::{cell::RefCell, fmt::Debug}; use std::borrow::Cow; use libafl::{ - alloc, + Error, HasMetadata, alloc, corpus::Testcase, executors::ExitKind, feedbacks::{Feedback, MinMapFeedback, StateInitializer}, inputs::{BytesInput, Input}, state::HasCorpus, - Error, HasMetadata, }; -use libafl_bolts::{impl_serdeany, tuples::MatchNameRef, Named}; +use libafl_bolts::{Named, impl_serdeany, tuples::MatchNameRef}; use libafl_targets::OomFeedback; use serde::{Deserialize, Serialize}; diff --git a/libafl_libfuzzer/runtime/src/fuzz.rs b/libafl_libfuzzer/runtime/src/fuzz.rs index 9a352c3e01..8a1d2a43e0 100644 --- a/libafl_libfuzzer/runtime/src/fuzz.rs +++ b/libafl_libfuzzer/runtime/src/fuzz.rs @@ -1,19 +1,19 @@ use core::ffi::c_int; #[cfg(unix)] -use std::io::{stderr, stdout, Write}; +use std::io::{Write, stderr, stdout}; use std::{fmt::Debug, fs::File, net::TcpListener, os::fd::AsRawFd, str::FromStr}; use libafl::{ + Error, Fuzzer, HasMetadata, corpus::Corpus, events::{ - launcher::Launcher, EventConfig, EventReceiver, ProgressReporter, SimpleEventManager, - SimpleRestartingEventManager, + EventConfig, EventReceiver, ProgressReporter, SimpleEventManager, + SimpleRestartingEventManager, launcher::Launcher, }, executors::ExitKind, - monitors::{tui::TuiMonitor, Monitor, MultiMonitor}, + monitors::{Monitor, MultiMonitor, tui::TuiMonitor}, stages::StagesTuple, state::{HasCurrentStageId, HasExecutions, HasLastReportTime, HasSolutions, Stoppable}, - Error, Fuzzer, HasMetadata, }; use libafl_bolts::{ core_affinity::Cores, @@ -141,7 +141,9 @@ where .or_else(|_| { TcpListener::bind("127.0.0.1:0").map(|sock| { let port = sock.local_addr().unwrap().port(); - std::env::set_var(PORT_PROVIDER_VAR, port.to_string()); + unsafe { + std::env::set_var(PORT_PROVIDER_VAR, port.to_string()); + } port }) })?; diff --git a/libafl_libfuzzer/runtime/src/lib.rs b/libafl_libfuzzer/runtime/src/lib.rs index 0f66bf87c2..ce54468dac 100644 --- a/libafl_libfuzzer/runtime/src/lib.rs +++ b/libafl_libfuzzer/runtime/src/lib.rs @@ -66,13 +66,13 @@ #![allow(clippy::borrow_as_ptr)] #![allow(clippy::borrow_deref_ref)] -use core::ffi::{c_char, c_int, CStr}; +use core::ffi::{CStr, c_char, c_int}; use std::{fs::File, io::stderr, os::fd::RawFd}; use env_logger::Target; use libafl::{ - inputs::{BytesInput, HasTargetBytes, Input}, Error, + inputs::{BytesInput, HasTargetBytes, Input}, }; use libafl_bolts::AsSlice; use libc::_exit; @@ -144,6 +144,7 @@ macro_rules! fuzz_with { rands::StdRand, tuples::{Merge, tuple_list}, AsSlice, + nonnull_raw_mut, }; use libafl::{ corpus::Corpus, @@ -159,7 +160,7 @@ macro_rules! fuzz_with { UnicodeCategoryTokenReplaceMutator, UnicodeSubcategoryTokenReplaceMutator, Tokens, tokens_mutations, UnicodeInput, }, - observers::{stacktrace::BacktraceObserver, TimeObserver, CanTrack}, + observers::{stacktrace::BacktraceObserver, TimeObserver, CanTrack, ConstMapObserver}, schedulers::{ IndexesLenTimeMinimizerScheduler, powersched::PowerSchedule, PowerQueueScheduler, }, @@ -205,7 +206,7 @@ macro_rules! fuzz_with { let cmplog_observer = CmpLogObserver::new("cmplog", true); // Create an observer using the cmp map for value profile - let value_profile_observer = unsafe { StdMapObserver::from_mut_ptr("cmps", CMP_MAP.as_mut_ptr(), CMP_MAP.len()) }; + let value_profile_observer = unsafe { ConstMapObserver::from_mut_ptr("cmps", nonnull_raw_mut!(CMP_MAP)) }; // Create a stacktrace observer let backtrace_observer = BacktraceObserver::owned( @@ -537,17 +538,19 @@ macro_rules! fuzz_with { use libafl::observers::{ HitcountsIterableMapObserver, HitcountsMapObserver, MultiMapObserver, StdMapObserver, }; - use libafl_targets::{COUNTERS_MAPS, extra_counters}; + use libafl_targets::{counters_maps_ptr, extra_counters}; + + let counters_len = unsafe { &*counters_maps_ptr() }.len(); // Create an observation channel using the coverage map - if unsafe { COUNTERS_MAPS.len() } == 1 { + if counters_len == 1 { fuzz_with!($options, $harness, $operation, $and_then, || { let edges = unsafe { extra_counters() }; let edges_observer = HitcountsMapObserver::new(StdMapObserver::from_mut_slice("edges", edges.into_iter().next().unwrap())); edges_observer }) - } else if unsafe { COUNTERS_MAPS.len() } > 1 { + } else if counters_len > 1 { fuzz_with!($options, $harness, $operation, $and_then, || { let edges = unsafe { extra_counters() }; let edges_observer = @@ -574,7 +577,7 @@ where fuzz_single(initial_state, mgr, 0) } -extern "C" { +unsafe extern "C" { // redeclaration against libafl_targets because the pointers in our case may be mutable fn libafl_targets_libfuzzer_init(argc: *mut c_int, argv: *mut *mut *const c_char) -> i32; } @@ -591,7 +594,7 @@ pub const STDERR_FD_VAR: &str = "_LIBAFL_LIBFUZZER_STDERR_FD"; /// This will then call the (potentially unsafe) harness. /// The fuzzer itself should catch any side effects and, hence be reasonably safe, if the `harness_fn` parameter is correct. #[expect(clippy::similar_names)] -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn LLVMFuzzerRunDriver( argc: *mut c_int, argv: *mut *mut *const c_char, @@ -613,11 +616,13 @@ pub unsafe extern "C" fn LLVMFuzzerRunDriver( .map_err(Error::from) .and_then(|s| RawFd::from_str(&s).map_err(Error::from)) .unwrap_or_else(|_| { - let stderr = libc::dup(stderr().as_raw_fd()); - std::env::set_var(STDERR_FD_VAR, stderr.to_string()); + let stderr = unsafe { libc::dup(stderr().as_raw_fd()) }; + unsafe { + std::env::set_var(STDERR_FD_VAR, stderr.to_string()); + } stderr }); - let stderr = File::from_raw_fd(stderr_fd); + let stderr = unsafe { File::from_raw_fd(stderr_fd) }; env_logger::builder() .parse_default_env() .target(Target::Pipe(Box::new(stderr))) @@ -626,7 +631,9 @@ pub unsafe extern "C" fn LLVMFuzzerRunDriver( // it appears that no one, not even libfuzzer, uses this return value // https://github.com/llvm/llvm-project/blob/llvmorg-15.0.7/compiler-rt/lib/fuzzer/FuzzerDriver.cpp#L648 - libafl_targets_libfuzzer_init(argc, argv); + unsafe { + libafl_targets_libfuzzer_init(argc, argv); + } let argc = unsafe { *argc } as isize; let argv = unsafe { *argv }; @@ -653,7 +660,9 @@ pub unsafe extern "C" fn LLVMFuzzerRunDriver( "Required folder {} did not exist; failing fast.", folder.to_string_lossy() ); - _exit(1); + unsafe { + _exit(1); + } } } @@ -666,7 +675,11 @@ pub unsafe extern "C" fn LLVMFuzzerRunDriver( let input = BytesInput::from_file(input).unwrap_or_else(|_| { panic!("Couldn't load input {}", input.to_string_lossy().as_ref()) }); - libafl_targets::libfuzzer::libfuzzer_test_one_input(input.target_bytes().as_slice()); + unsafe { + libafl_targets::libfuzzer::libfuzzer_test_one_input( + input.target_bytes().as_slice(), + ); + } } return 0; } diff --git a/libafl_libfuzzer/runtime/src/merge.rs b/libafl_libfuzzer/runtime/src/merge.rs index 427c1a66f9..363e2b57f3 100644 --- a/libafl_libfuzzer/runtime/src/merge.rs +++ b/libafl_libfuzzer/runtime/src/merge.rs @@ -1,12 +1,13 @@ use std::{ env::temp_dir, ffi::c_int, - fs::{rename, File}, + fs::{File, rename}, io::Write, os::fd::{AsRawFd, FromRawFd}, }; use libafl::{ + Error, HasScheduler, StdFuzzer, corpus::Corpus, events::{SendExiting, SimpleRestartingEventManager}, executors::{ExitKind, InProcessExecutor}, @@ -17,15 +18,14 @@ use libafl::{ observers::{MultiMapObserver, TimeObserver}, schedulers::RemovableScheduler, state::{HasCorpus, HasRand, StdState}, - Error, HasScheduler, StdFuzzer, }; use libafl_bolts::{ + AsSlice, rands::{Rand, StdRand}, shmem::{ShMemProvider, StdShMemProvider}, tuples::tuple_list, - AsSlice, }; -use libafl_targets::{OomFeedback, OomObserver, COUNTERS_MAPS}; +use libafl_targets::{OomFeedback, OomObserver, counters_maps_ptr_mut}; use crate::{ corpus::{ArtifactCorpus, LibfuzzerCorpus}, @@ -41,7 +41,9 @@ pub fn merge( harness: &extern "C" fn(*const u8, usize) -> c_int, ) -> Result<(), Error> { if options.dirs().is_empty() { - return Err(Error::illegal_argument("Missing corpora to minimize; you should provide one directory to minimize into and one-to-many from which the inputs are loaded.")); + return Err(Error::illegal_argument( + "Missing corpora to minimize; you should provide one directory to minimize into and one-to-many from which the inputs are loaded.", + )); } let crash_corpus = ArtifactCorpus::new(); @@ -93,7 +95,8 @@ pub fn merge( } } - let edges = unsafe { core::mem::take(&mut COUNTERS_MAPS) }; + #[expect(clippy::deref_addrof)] + let edges = unsafe { core::mem::take(&mut *(counters_maps_ptr_mut())) }; let edges_observer = MultiMapObserver::new("edges", edges); let time = TimeObserver::new("time"); diff --git a/libafl_libfuzzer/runtime/src/misc.rs b/libafl_libfuzzer/runtime/src/misc.rs index 24b4d73169..fee02452e6 100644 --- a/libafl_libfuzzer/runtime/src/misc.rs +++ b/libafl_libfuzzer/runtime/src/misc.rs @@ -6,7 +6,7 @@ use libafl_bolts::impl_serdeany; use serde::{Deserialize, Serialize}; use utf8_chars::BufReadCharsExt; -use crate::{options::LibfuzzerOptions, CustomMutationStatus}; +use crate::{CustomMutationStatus, options::LibfuzzerOptions}; #[derive(Deserialize, Serialize, Debug, Default)] pub(crate) struct ShouldUseGrimoireMetadata { @@ -38,13 +38,17 @@ where .unwrap_or_default(); let grimoire = if let Some(grimoire) = options.grimoire() { if grimoire && !mutator_status.std_mutational { - eprintln!("WARNING: cowardly refusing to use grimoire after detecting the presence of a custom mutator"); + eprintln!( + "WARNING: cowardly refusing to use grimoire after detecting the presence of a custom mutator" + ); } metadata.should = grimoire && mutator_status.std_mutational; metadata } else if mutator_status.std_mutational { if options.dirs().is_empty() { - eprintln!("WARNING: cowardly refusing to use grimoire since we cannot determine if the input is primarily text; set -grimoire=1 or provide a corpus directory."); + eprintln!( + "WARNING: cowardly refusing to use grimoire since we cannot determine if the input is primarily text; set -grimoire=1 or provide a corpus directory." + ); metadata } else { let mut input_queue = VecDeque::new(); @@ -74,7 +78,11 @@ where } metadata.should = metadata.utf8 > metadata.non_utf8; // greater-than so zero testcases doesn't enable if metadata.should { - eprintln!("INFO: inferred grimoire mutator (found {}/{} UTF-8 inputs); if this is undesired, set -grimoire=0", metadata.utf8, metadata.utf8 + metadata.non_utf8); + eprintln!( + "INFO: inferred grimoire mutator (found {}/{} UTF-8 inputs); if this is undesired, set -grimoire=0", + metadata.utf8, + metadata.utf8 + metadata.non_utf8 + ); } metadata } diff --git a/libafl_libfuzzer/runtime/src/observers.rs b/libafl_libfuzzer/runtime/src/observers.rs index 2413b305af..f6b45181b7 100644 --- a/libafl_libfuzzer/runtime/src/observers.rs +++ b/libafl_libfuzzer/runtime/src/observers.rs @@ -6,10 +6,10 @@ use std::{ }; use libafl::{ + Error, executors::ExitKind, observers::{MapObserver, Observer, TimeObserver}, state::HasCorpus, - Error, }; use libafl_bolts::{AsIter, HasLen, Named}; use num_traits::Bounded; diff --git a/libafl_libfuzzer/runtime/src/report.rs b/libafl_libfuzzer/runtime/src/report.rs index aeee85062f..4580c585bb 100644 --- a/libafl_libfuzzer/runtime/src/report.rs +++ b/libafl_libfuzzer/runtime/src/report.rs @@ -1,13 +1,13 @@ use std::ffi::c_int; use libafl::{ + Error, Fuzzer, HasMetadata, HasNamedMetadata, events::{EventReceiver, ProgressReporter, SimpleEventManager}, executors::HasObservers, feedbacks::MapFeedbackMetadata, monitors::SimpleMonitor, stages::StagesTuple, state::{HasCurrentStageId, HasExecutions, HasLastReportTime, Stoppable}, - Error, Fuzzer, HasMetadata, HasNamedMetadata, }; use crate::{fuzz_with, options::LibfuzzerOptions}; diff --git a/libafl_libfuzzer/runtime/src/schedulers.rs b/libafl_libfuzzer/runtime/src/schedulers.rs index 220cd738f6..33d9cfa9ce 100644 --- a/libafl_libfuzzer/runtime/src/schedulers.rs +++ b/libafl_libfuzzer/runtime/src/schedulers.rs @@ -2,12 +2,12 @@ use std::{collections::BTreeSet, marker::PhantomData}; use hashbrown::HashMap; use libafl::{ + Error, HasMetadata, corpus::{Corpus, CorpusId, Testcase}, feedbacks::MapNoveltiesMetadata, inputs::Input, schedulers::{RemovableScheduler, Scheduler}, state::HasCorpus, - Error, HasMetadata, }; #[derive(Clone, Debug)] diff --git a/libafl_libfuzzer/runtime/src/tmin.rs b/libafl_libfuzzer/runtime/src/tmin.rs index faf8a6278b..7afb05d214 100644 --- a/libafl_libfuzzer/runtime/src/tmin.rs +++ b/libafl_libfuzzer/runtime/src/tmin.rs @@ -4,26 +4,26 @@ use std::{ }; use libafl::{ + Error, ExecutesInput, Fuzzer, StdFuzzer, corpus::{Corpus, HasTestcase, InMemoryCorpus, Testcase}, events::SimpleEventManager, - executors::{inprocess_fork::InProcessForkExecutor, ExitKind}, + executors::{ExitKind, inprocess_fork::InProcessForkExecutor}, feedbacks::{CrashFeedback, TimeoutFeedback}, inputs::{BytesInput, HasMutatorBytes, HasTargetBytes}, - mutators::{havoc_mutations_no_crossover, Mutator, StdScheduledMutator}, + mutators::{Mutator, StdScheduledMutator, havoc_mutations_no_crossover}, schedulers::QueueScheduler, stages::StdTMinMutationalStage, state::{HasCorpus, StdState}, - Error, ExecutesInput, Fuzzer, StdFuzzer, }; use libafl_bolts::{ + AsSlice, HasLen, rands::{RomuDuoJrRand, StdRand}, shmem::{ShMemProvider, StdShMemProvider}, tuples::tuple_list, - AsSlice, HasLen, }; use libafl_targets::LLVMCustomMutator; -use crate::{options::LibfuzzerOptions, CustomMutationStatus}; +use crate::{CustomMutationStatus, options::LibfuzzerOptions}; type TMinState = StdState, BytesInput, RomuDuoJrRand, InMemoryCorpus>; diff --git a/libafl_libfuzzer/src/lib.rs b/libafl_libfuzzer/src/lib.rs index 1703d980d5..8b08c82500 100644 --- a/libafl_libfuzzer/src/lib.rs +++ b/libafl_libfuzzer/src/lib.rs @@ -115,7 +115,7 @@ use std::ffi::{c_char, c_int}; pub use libfuzzer_sys::*; -extern "C" { +unsafe extern "C" { /// `LLVMFuzzerRunDriver` allows for harnesses which specify their own main. See: /// /// You can call this function inside of a main function in your harness, or specify `#![no_main]` diff --git a/libafl_nyx/Cargo.toml b/libafl_nyx/Cargo.toml index 2fbfb1ad16..b9b3ec0330 100644 --- a/libafl_nyx/Cargo.toml +++ b/libafl_nyx/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "libafl_nyx" version.workspace = true -edition = "2021" +edition = "2024" authors = ["syheliel "] description = "libafl using nyx, only avaliable on linux" documentation = "https://docs.rs/libafl_nyx" diff --git a/libafl_nyx/src/cmplog.rs b/libafl_nyx/src/cmplog.rs index b81f25b37f..ef4304c132 100644 --- a/libafl_nyx/src/cmplog.rs +++ b/libafl_nyx/src/cmplog.rs @@ -4,17 +4,17 @@ use std::borrow::Cow; use libafl::{ + Error, HasMetadata, executors::ExitKind, observers::{CmpValues, CmpValuesMetadata, Observer}, state::HasExecutions, - Error, HasMetadata, }; use libafl_bolts::Named; pub use libafl_targets::{ + CMPLOG_MAP_H, CMPLOG_MAP_PTR, CMPLOG_MAP_SIZE, CMPLOG_MAP_W, CmpLogMap, CmpLogObserver, cmps::{ __libafl_targets_cmplog_instructions, __libafl_targets_cmplog_routines, CMPLOG_ENABLED, }, - CmpLogMap, CmpLogObserver, CMPLOG_MAP_H, CMPLOG_MAP_PTR, CMPLOG_MAP_SIZE, CMPLOG_MAP_W, }; use serde::{Deserialize, Serialize}; diff --git a/libafl_nyx/src/executor.rs b/libafl_nyx/src/executor.rs index 76b5edb310..ddf8ee0594 100644 --- a/libafl_nyx/src/executor.rs +++ b/libafl_nyx/src/executor.rs @@ -5,13 +5,13 @@ use std::{ }; use libafl::{ + Error, executors::{Executor, ExitKind, HasObservers, HasTimeout}, inputs::HasTargetBytes, observers::{ObserversTuple, StdOutObserver}, state::HasExecutions, - Error, }; -use libafl_bolts::{tuples::RefIndexable, AsSlice}; +use libafl_bolts::{AsSlice, tuples::RefIndexable}; use libnyx::NyxReturnValue; use crate::{cmplog::CMPLOG_ENABLED, helper::NyxHelper}; diff --git a/libafl_qemu/Cargo.toml b/libafl_qemu/Cargo.toml index 1623b23842..09b68877e7 100644 --- a/libafl_qemu/Cargo.toml +++ b/libafl_qemu/Cargo.toml @@ -11,7 +11,7 @@ repository = "https://github.com/AFLplusplus/LibAFL/" readme = "../README.md" license = "MIT OR Apache-2.0" keywords = ["fuzzing", "qemu", "instrumentation"] -edition = "2021" +edition = "2024" categories = [ "development-tools::testing", "emulators", diff --git a/libafl_qemu/build_linux.rs b/libafl_qemu/build_linux.rs index a8a421e280..af4fffec82 100644 --- a/libafl_qemu/build_linux.rs +++ b/libafl_qemu/build_linux.rs @@ -110,7 +110,9 @@ pub fn build() { }; println!("cargo:rerun-if-env-changed=CPU_TARGET"); println!("cargo:rustc-cfg=cpu_target=\"{cpu_target}\""); - println!("cargo::rustc-check-cfg=cfg(cpu_target, values(\"x86_64\", \"arm\", \"aarch64\", \"i386\", \"mips\", \"ppc\", \"hexagon\", \"riscv32\", \"riscv64\"))"); + println!( + "cargo::rustc-check-cfg=cfg(cpu_target, values(\"x86_64\", \"arm\", \"aarch64\", \"i386\", \"mips\", \"ppc\", \"hexagon\", \"riscv32\", \"riscv64\"))" + ); let cross_cc = if cfg!(feature = "usermode") && (qemu_asan || qemu_asan_guest) { // TODO try to autodetect a cross compiler with the arch name (e.g. aarch64-linux-gnu-gcc) @@ -161,10 +163,7 @@ pub fn build() { ) .expect("Could not copy libafl_qemu_impl.h to out directory."); - fs::copy( - nyx_hdr.clone(), - include_dir.join(nyx_hdr_name), - ) + fs::copy(nyx_hdr.clone(), include_dir.join(nyx_hdr_name)) .expect("Could not copy libafl_qemu_impl.h to out directory."); bindgen::Builder::default() @@ -176,6 +175,7 @@ pub fn build() { is_global: true, is_bitfield: true, }) + // .rust_edition(bindgen::RustEdition::Edition2024) .header(libafl_qemu_hdr.display().to_string()) .generate() .expect("Exit bindings generation failed.") @@ -191,6 +191,7 @@ pub fn build() { is_global: true, is_bitfield: true, }) + // .rust_edition(bindgen::RustEdition::Edition2024) .header(nyx_hdr.display().to_string()) .generate() .expect("Exit bindings generation failed.") @@ -220,14 +221,15 @@ pub fn build() { if cfg!(debug_assertions) { make.env("CFLAGS", "-DDEBUG=1"); } - assert!(make - .current_dir(&out_dir) - .env("CC", &cross_cc) - .env("OUT_DIR", &target_dir) - .arg("-C") - .arg(&qasan_dir) - .status() - .expect("make failed") - .success()); + assert!( + make.current_dir(&out_dir) + .env("CC", &cross_cc) + .env("OUT_DIR", &target_dir) + .arg("-C") + .arg(&qasan_dir) + .status() + .expect("make failed") + .success() + ); } } diff --git a/libafl_qemu/libafl_qemu_build/Cargo.toml b/libafl_qemu/libafl_qemu_build/Cargo.toml index 6282e9f6ef..759b8c8f2a 100644 --- a/libafl_qemu/libafl_qemu_build/Cargo.toml +++ b/libafl_qemu/libafl_qemu_build/Cargo.toml @@ -11,7 +11,7 @@ repository = "https://github.com/AFLplusplus/LibAFL/" readme = "./README.md" license = "MIT OR Apache-2.0" keywords = ["fuzzing", "qemu", "instrumentation"] -edition = "2021" +edition = "2024" categories = [ "development-tools::testing", "emulators", diff --git a/libafl_qemu/libafl_qemu_build/src/bindings.rs b/libafl_qemu/libafl_qemu_build/src/bindings.rs index 0fdc10d391..48de22b4f4 100644 --- a/libafl_qemu/libafl_qemu_build/src/bindings.rs +++ b/libafl_qemu/libafl_qemu_build/src/bindings.rs @@ -132,6 +132,7 @@ pub fn generate( }) .header(wrapper_h.display().to_string()) .clang_args(clang_args) + // .rust_edition(RustEdition::Edition2024) .allowlist_var("libafl_dump_core_hook") .allowlist_var("libafl_force_dfl") .allowlist_var("mmap_next_start") diff --git a/libafl_qemu/libafl_qemu_build/src/build.rs b/libafl_qemu/libafl_qemu_build/src/build.rs index 0262d1db5e..7d5cb7adba 100644 --- a/libafl_qemu/libafl_qemu_build/src/build.rs +++ b/libafl_qemu/libafl_qemu_build/src/build.rs @@ -11,7 +11,7 @@ use crate::cargo_add_rpath; pub const QEMU_URL: &str = "https://github.com/AFLplusplus/qemu-libafl-bridge"; pub const QEMU_DIRNAME: &str = "qemu-libafl-bridge"; -pub const QEMU_REVISION: &str = "06c738f64a4a92d5fc8184c9b5a9fe9340f4a63f"; +pub const QEMU_REVISION: &str = "3c60ef9b83107a160021075b485831edecb5a1c3"; pub struct BuildResult { pub qemu_path: PathBuf, @@ -300,7 +300,9 @@ pub fn build( let libafl_qemu_dir = if let Some(qemu_dir) = libafl_qemu_dir.as_ref() { if libafl_qemu_clone_dir.is_some() { - println!("cargo:warning=LIBAFL_QEMU_DIR and LIBAFL_QEMU_CLONE_DIR are both set. LIBAFL_QEMU_DIR will be considered in priority"); + println!( + "cargo:warning=LIBAFL_QEMU_DIR and LIBAFL_QEMU_CLONE_DIR are both set. LIBAFL_QEMU_DIR will be considered in priority" + ); } Path::new(&qemu_dir).to_path_buf() @@ -321,38 +323,46 @@ pub fn build( if !qemu_path.is_dir() { println!("cargo:warning=Qemu not found, cloning with git ({QEMU_REVISION})..."); fs::create_dir_all(&qemu_path).unwrap(); - assert!(Command::new("git") - .current_dir(&qemu_path) - .arg("init") - .status() - .unwrap() - .success()); - assert!(Command::new("git") - .current_dir(&qemu_path) - .arg("remote") - .arg("add") - .arg("origin") - .arg(QEMU_URL) - .status() - .unwrap() - .success()); - assert!(Command::new("git") - .current_dir(&qemu_path) - .arg("fetch") - .arg("--depth") - .arg("1") - .arg("origin") - .arg(QEMU_REVISION) - .status() - .unwrap() - .success()); - assert!(Command::new("git") - .current_dir(&qemu_path) - .arg("checkout") - .arg("FETCH_HEAD") - .status() - .unwrap() - .success()); + assert!( + Command::new("git") + .current_dir(&qemu_path) + .arg("init") + .status() + .unwrap() + .success() + ); + assert!( + Command::new("git") + .current_dir(&qemu_path) + .arg("remote") + .arg("add") + .arg("origin") + .arg(QEMU_URL) + .status() + .unwrap() + .success() + ); + assert!( + Command::new("git") + .current_dir(&qemu_path) + .arg("fetch") + .arg("--depth") + .arg("1") + .arg("origin") + .arg(QEMU_REVISION) + .status() + .unwrap() + .success() + ); + assert!( + Command::new("git") + .current_dir(&qemu_path) + .arg("checkout") + .arg("FETCH_HEAD") + .status() + .unwrap() + .success() + ); fs::write(&qemu_rev, QEMU_REVISION).unwrap(); } diff --git a/libafl_qemu/libafl_qemu_build/src/lib.rs b/libafl_qemu/libafl_qemu_build/src/lib.rs index a86ea5249f..903d80b623 100644 --- a/libafl_qemu/libafl_qemu_build/src/lib.rs +++ b/libafl_qemu/libafl_qemu_build/src/lib.rs @@ -102,7 +102,9 @@ fn find_llvm_config() -> Result { if which("llvm-config").is_ok() { if let Some(ver) = find_llvm_version("llvm-config".to_owned()) { if ver < rustc_llvm_ver { - println!("cargo:warning=Version of llvm-config is {ver} but needs to be at least rustc's version ({rustc_llvm_ver})! We will (try to) continue to build. Continue at your own risk, or rebuild with a set LLVM_CONFIG_PATH env variable, pointing to a newer version."); + println!( + "cargo:warning=Version of llvm-config is {ver} but needs to be at least rustc's version ({rustc_llvm_ver})! We will (try to) continue to build. Continue at your own risk, or rebuild with a set LLVM_CONFIG_PATH env variable, pointing to a newer version." + ); } return Ok("llvm-config".to_owned()); } @@ -163,7 +165,11 @@ fn qemu_bindgen_clang_args( ) -> Vec { if env::var("LLVM_CONFIG_PATH").is_err() { let found = find_llvm_config().expect("Cannot find a suitable llvm-config, it must be a version equal or greater than the rustc LLVM version. Try specifying LLVM_CONFIG_PATH."); - env::set_var("LLVM_CONFIG_PATH", found); + // # Safety + // This edits env variables but in a build script there's not much that can go wrong + unsafe { + env::set_var("LLVM_CONFIG_PATH", found); + } } // load compile commands @@ -419,7 +425,9 @@ pub fn maybe_generate_stub_bindings( false, ); } else if env::var("CARGO_CFG_DOC").is_ok() { - println!("cargo:warning=Bindings regeneration has been skipped. Please rerun with x86_64 with usermode to trigger the bindings regeneration."); + println!( + "cargo:warning=Bindings regeneration has been skipped. Please rerun with x86_64 with usermode to trigger the bindings regeneration." + ); } } diff --git a/libafl_qemu/libafl_qemu_sys/Cargo.toml b/libafl_qemu/libafl_qemu_sys/Cargo.toml index aad3048ff3..77167265e0 100644 --- a/libafl_qemu/libafl_qemu_sys/Cargo.toml +++ b/libafl_qemu/libafl_qemu_sys/Cargo.toml @@ -11,7 +11,7 @@ repository = "https://github.com/AFLplusplus/LibAFL/" readme = "../../README.md" license = "MIT OR Apache-2.0" keywords = ["fuzzing", "qemu", "instrumentation"] -edition = "2021" +edition = "2024" categories = [ "development-tools::testing", "emulators", diff --git a/libafl_qemu/libafl_qemu_sys/src/bindings/mod.rs b/libafl_qemu/libafl_qemu_sys/src/bindings/mod.rs index fb25d7b7ff..8f10efd39f 100644 --- a/libafl_qemu/libafl_qemu_sys/src/bindings/mod.rs +++ b/libafl_qemu/libafl_qemu_sys/src/bindings/mod.rs @@ -1,12 +1,11 @@ -#![allow(non_upper_case_globals)] -#![allow(non_camel_case_types)] -#![allow(non_snake_case)] -#![allow(unused_mut)] -#![allow(unused)] -#![allow(unused_variables)] -#![allow(clippy::all)] -#![allow(clippy::pedantic)] -#![allow(improper_ctypes)] +#![expect(non_upper_case_globals)] +#![expect(non_camel_case_types)] +#![expect(non_snake_case)] +#![expect(clippy::all)] +#![expect(clippy::pedantic)] +#![expect(improper_ctypes)] +#![expect(unsafe_op_in_unsafe_fn)] +#![allow(unused_imports)] #[cfg(all(not(feature = "clippy"), target_os = "linux"))] #[rustfmt::skip] diff --git a/libafl_qemu/libafl_qemu_sys/src/bindings/x86_64_stub_bindings.rs b/libafl_qemu/libafl_qemu_sys/src/bindings/x86_64_stub_bindings.rs index 13389ebd01..b4b6d85294 100644 --- a/libafl_qemu/libafl_qemu_sys/src/bindings/x86_64_stub_bindings.rs +++ b/libafl_qemu/libafl_qemu_sys/src/bindings/x86_64_stub_bindings.rs @@ -1,5 +1,5 @@ -/* 1.86.0-nightly */ -/* qemu git hash: 695657e4f3f408c34b146d5191b102d5eb99b74b */ +/* 1.87.0-nightly */ +/* qemu git hash: 06c738f64a4a92d5fc8184c9b5a9fe9340f4a63f */ /* automatically generated by rust-bindgen 0.71.1 */ use libc::siginfo_t; @@ -51,11 +51,7 @@ where index % 8 }; let mask = 1 << bit_index; - if val { - byte | mask - } else { - byte & !mask - } + if val { byte | mask } else { byte & !mask } } #[inline] pub fn set_bit(&mut self, index: usize, val: bool) { @@ -309,7 +305,6 @@ impl Default for __pthread_mutex_s { pub struct __pthread_cond_s { pub __wseq: __atomic_wide_counter, pub __g1_start: __atomic_wide_counter, - pub __g_refs: [::std::os::raw::c_uint; 2usize], pub __g_size: [::std::os::raw::c_uint; 2usize], pub __g1_orig_size: ::std::os::raw::c_uint, pub __wrefs: ::std::os::raw::c_uint, @@ -317,22 +312,20 @@ pub struct __pthread_cond_s { } #[allow(clippy::unnecessary_operation, clippy::identity_op)] const _: () = { - ["Size of __pthread_cond_s"][::std::mem::size_of::<__pthread_cond_s>() - 48usize]; + ["Size of __pthread_cond_s"][::std::mem::size_of::<__pthread_cond_s>() - 40usize]; ["Alignment of __pthread_cond_s"][::std::mem::align_of::<__pthread_cond_s>() - 8usize]; ["Offset of field: __pthread_cond_s::__wseq"] [::std::mem::offset_of!(__pthread_cond_s, __wseq) - 0usize]; ["Offset of field: __pthread_cond_s::__g1_start"] [::std::mem::offset_of!(__pthread_cond_s, __g1_start) - 8usize]; - ["Offset of field: __pthread_cond_s::__g_refs"] - [::std::mem::offset_of!(__pthread_cond_s, __g_refs) - 16usize]; ["Offset of field: __pthread_cond_s::__g_size"] - [::std::mem::offset_of!(__pthread_cond_s, __g_size) - 24usize]; + [::std::mem::offset_of!(__pthread_cond_s, __g_size) - 16usize]; ["Offset of field: __pthread_cond_s::__g1_orig_size"] - [::std::mem::offset_of!(__pthread_cond_s, __g1_orig_size) - 32usize]; + [::std::mem::offset_of!(__pthread_cond_s, __g1_orig_size) - 24usize]; ["Offset of field: __pthread_cond_s::__wrefs"] - [::std::mem::offset_of!(__pthread_cond_s, __wrefs) - 36usize]; + [::std::mem::offset_of!(__pthread_cond_s, __wrefs) - 28usize]; ["Offset of field: __pthread_cond_s::__g_signals"] - [::std::mem::offset_of!(__pthread_cond_s, __g_signals) - 40usize]; + [::std::mem::offset_of!(__pthread_cond_s, __g_signals) - 32usize]; }; impl Default for __pthread_cond_s { fn default() -> Self { @@ -345,7 +338,16 @@ impl Default for __pthread_cond_s { } impl ::std::fmt::Debug for __pthread_cond_s { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - write ! (f , "__pthread_cond_s {{ __wseq: {:?}, __g1_start: {:?}, __g_refs: {:?}, __g_size: {:?}, __g1_orig_size: {:?}, __wrefs: {:?}, __g_signals: {:?} }}" , self . __wseq , self . __g1_start , self . __g_refs , self . __g_size , self . __g1_orig_size , self . __wrefs , self . __g_signals) + write!( + f, + "__pthread_cond_s {{ __wseq: {:?}, __g1_start: {:?}, __g_size: {:?}, __g1_orig_size: {:?}, __wrefs: {:?}, __g_signals: {:?} }}", + self.__wseq, + self.__g1_start, + self.__g_size, + self.__g1_orig_size, + self.__wrefs, + self.__g_signals + ) } } pub type pthread_t = ::std::os::raw::c_ulong; @@ -448,7 +450,9 @@ pub struct _IO_FILE { pub _markers: *mut _IO_marker, pub _chain: *mut _IO_FILE, pub _fileno: ::std::os::raw::c_int, - pub _flags2: ::std::os::raw::c_int, + pub _bitfield_align_1: [u32; 0], + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 3usize]>, + pub _short_backupbuf: [::std::os::raw::c_char; 1usize], pub _old_offset: __off_t, pub _cur_column: ::std::os::raw::c_ushort, pub _vtable_offset: ::std::os::raw::c_schar, @@ -493,7 +497,8 @@ const _: () = { ["Offset of field: _IO_FILE::_markers"][::std::mem::offset_of!(_IO_FILE, _markers) - 96usize]; ["Offset of field: _IO_FILE::_chain"][::std::mem::offset_of!(_IO_FILE, _chain) - 104usize]; ["Offset of field: _IO_FILE::_fileno"][::std::mem::offset_of!(_IO_FILE, _fileno) - 112usize]; - ["Offset of field: _IO_FILE::_flags2"][::std::mem::offset_of!(_IO_FILE, _flags2) - 116usize]; + ["Offset of field: _IO_FILE::_short_backupbuf"] + [::std::mem::offset_of!(_IO_FILE, _short_backupbuf) - 119usize]; ["Offset of field: _IO_FILE::_old_offset"] [::std::mem::offset_of!(_IO_FILE, _old_offset) - 120usize]; ["Offset of field: _IO_FILE::_cur_column"] @@ -525,6 +530,50 @@ impl Default for _IO_FILE { } } } +impl _IO_FILE { + #[inline] + pub fn _flags2(&self) -> ::std::os::raw::c_int { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 24u8) as u32) } + } + #[inline] + pub fn set__flags2(&mut self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 24u8, val as u64) + } + } + #[inline] + pub unsafe fn _flags2_raw(this: *const Self) -> ::std::os::raw::c_int { + unsafe { + ::std::mem::transmute(<__BindgenBitfieldUnit<[u8; 3usize]>>::raw_get( + ::std::ptr::addr_of!((*this)._bitfield_1), + 0usize, + 24u8, + ) as u32) + } + } + #[inline] + pub unsafe fn set__flags2_raw(this: *mut Self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit<[u8; 3usize]>>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 24u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1(_flags2: ::std::os::raw::c_int) -> __BindgenBitfieldUnit<[u8; 3usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 3usize]> = Default::default(); + __bindgen_bitfield_unit.set(0usize, 24u8, { + let _flags2: u32 = unsafe { ::std::mem::transmute(_flags2) }; + _flags2 as u64 + }); + __bindgen_bitfield_unit + } +} pub type __jmp_buf = [::std::os::raw::c_long; 8usize]; #[repr(C)] #[derive(Debug, Default, Copy, Clone)] @@ -633,7 +682,11 @@ impl Default for siginfo_t__bindgen_ty_1__bindgen_ty_2 { } impl ::std::fmt::Debug for siginfo_t__bindgen_ty_1__bindgen_ty_2 { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - write ! (f , "siginfo_t__bindgen_ty_1__bindgen_ty_2 {{ si_tid: {:?}, si_overrun: {:?}, si_sigval: {:?} }}" , self . si_tid , self . si_overrun , self . si_sigval) + write!( + f, + "siginfo_t__bindgen_ty_1__bindgen_ty_2 {{ si_tid: {:?}, si_overrun: {:?}, si_sigval: {:?} }}", + self.si_tid, self.si_overrun, self.si_sigval + ) } } #[repr(C)] @@ -667,7 +720,11 @@ impl Default for siginfo_t__bindgen_ty_1__bindgen_ty_3 { } impl ::std::fmt::Debug for siginfo_t__bindgen_ty_1__bindgen_ty_3 { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - write ! (f , "siginfo_t__bindgen_ty_1__bindgen_ty_3 {{ si_pid: {:?}, si_uid: {:?}, si_sigval: {:?} }}" , self . si_pid , self . si_uid , self . si_sigval) + write!( + f, + "siginfo_t__bindgen_ty_1__bindgen_ty_3 {{ si_pid: {:?}, si_uid: {:?}, si_sigval: {:?} }}", + self.si_pid, self.si_uid, self.si_sigval + ) } } #[repr(C)] @@ -723,8 +780,16 @@ const _: () = { ["Alignment of siginfo_t__bindgen_ty_1__bindgen_ty_5__bindgen_ty_1__bindgen_ty_1"] [::std::mem::align_of::( ) - 8usize]; - ["Offset of field: siginfo_t__bindgen_ty_1__bindgen_ty_5__bindgen_ty_1__bindgen_ty_1::_lower"] [:: std :: mem :: offset_of ! (siginfo_t__bindgen_ty_1__bindgen_ty_5__bindgen_ty_1__bindgen_ty_1 , _lower) - 0usize] ; - ["Offset of field: siginfo_t__bindgen_ty_1__bindgen_ty_5__bindgen_ty_1__bindgen_ty_1::_upper"] [:: std :: mem :: offset_of ! (siginfo_t__bindgen_ty_1__bindgen_ty_5__bindgen_ty_1__bindgen_ty_1 , _upper) - 8usize] ; + ["Offset of field: siginfo_t__bindgen_ty_1__bindgen_ty_5__bindgen_ty_1__bindgen_ty_1::_lower"] + [::std::mem::offset_of!( + siginfo_t__bindgen_ty_1__bindgen_ty_5__bindgen_ty_1__bindgen_ty_1, + _lower + ) - 0usize]; + ["Offset of field: siginfo_t__bindgen_ty_1__bindgen_ty_5__bindgen_ty_1__bindgen_ty_1::_upper"] + [::std::mem::offset_of!( + siginfo_t__bindgen_ty_1__bindgen_ty_5__bindgen_ty_1__bindgen_ty_1, + _upper + ) - 8usize]; }; impl Default for siginfo_t__bindgen_ty_1__bindgen_ty_5__bindgen_ty_1__bindgen_ty_1 { fn default() -> Self { @@ -791,7 +856,11 @@ impl Default for siginfo_t__bindgen_ty_1__bindgen_ty_5 { } impl ::std::fmt::Debug for siginfo_t__bindgen_ty_1__bindgen_ty_5 { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - write ! (f , "siginfo_t__bindgen_ty_1__bindgen_ty_5 {{ si_addr: {:?}, si_addr_lsb: {:?}, _bounds: {:?} }}" , self . si_addr , self . si_addr_lsb , self . _bounds) + write!( + f, + "siginfo_t__bindgen_ty_1__bindgen_ty_5 {{ si_addr: {:?}, si_addr_lsb: {:?}, _bounds: {:?} }}", + self.si_addr, self.si_addr_lsb, self._bounds + ) } } #[repr(C)] @@ -2175,7 +2244,21 @@ impl Default for BusState { } impl ::std::fmt::Debug for BusState { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - write ! (f , "BusState {{ obj: {:?}, parent: {:?}, name: {:?}, hotplug_handler: {:?}, max_index: {:?}, realized: {:?}, full: {:?}, num_children: {:?}, children: {:?}, sibling: {:?}, reset: {:?} }}" , self . obj , self . parent , self . name , self . hotplug_handler , self . max_index , self . realized , self . full , self . num_children , self . children , self . sibling , self . reset) + write!( + f, + "BusState {{ obj: {:?}, parent: {:?}, name: {:?}, hotplug_handler: {:?}, max_index: {:?}, realized: {:?}, full: {:?}, num_children: {:?}, children: {:?}, sibling: {:?}, reset: {:?} }}", + self.obj, + self.parent, + self.name, + self.hotplug_handler, + self.max_index, + self.realized, + self.full, + self.num_children, + self.children, + self.sibling, + self.reset + ) } } pub type PTR = *mut ::std::os::raw::c_void; @@ -3601,7 +3684,11 @@ impl Default for CPUNegativeOffsetState { } impl ::std::fmt::Debug for CPUNegativeOffsetState { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - write ! (f , "CPUNegativeOffsetState {{ tlb: {:?}, plugin_mem_cbs: {:?}, icount_decr: {:?}, can_do_io: {:?} }}" , self . tlb , self . plugin_mem_cbs , self . icount_decr , self . can_do_io) + write!( + f, + "CPUNegativeOffsetState {{ tlb: {:?}, plugin_mem_cbs: {:?}, icount_decr: {:?}, can_do_io: {:?} }}", + self.tlb, self.plugin_mem_cbs, self.icount_decr, self.can_do_io + ) } } #[repr(C)] @@ -3930,7 +4017,63 @@ impl Default for CPUState { } impl ::std::fmt::Debug for CPUState { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - write ! (f , "CPUState {{ parent_obj: {:?}, cc: {:?}, nr_cores: {:?}, nr_threads: {:?}, thread: {:?}, thread_id: {:?}, running: {:?}, has_waiter: {:?}, halt_cond: {:?}, thread_kicked: {:?}, created: {:?}, stop: {:?}, stopped: {:?}, start_powered_off: {:?}, unplug: {:?}, crash_occurred: {:?}, exit_request: {:?}, exclusive_context_count: {:?}, singlestep_enabled: {:?}, jmp_env: {:?}, work_mutex: {:?}, work_list: {:?}, cpu_ases: {:?}, cpu_ases_count: {:?}, num_ases: {:?}, as: {:?}, memory: {:?}, tb_jmp_cache: {:?}, gdb_regs: {:?}, gdb_num_regs: {:?}, gdb_num_g_regs: {:?}, node: {:?}, breakpoints: {:?}, watchpoints: {:?}, watchpoint_hit: {:?}, opaque: {:?}, kvm_fd: {:?}, kvm_state: {:?}, kvm_run: {:?}, kvm_dirty_gfns: {:?}, kvm_vcpu_stats_fd: {:?}, vcpu_dirty: {:?}, in_ioctl_lock: {:?}, plugin_state: {:?}, cpu_index: {:?}, cluster_index: {:?}, accel: {:?}, throttle_thread_scheduled: {:?}, ignore_memory_transaction_failures: {:?}, prctl_unalign_sigbus: {:?}, iommu_notifiers: {:?}, neg_align: {:?}, neg: {:?} }}" , self . parent_obj , self . cc , self . nr_cores , self . nr_threads , self . thread , self . thread_id , self . running , self . has_waiter , self . halt_cond , self . thread_kicked , self . created , self . stop , self . stopped , self . start_powered_off , self . unplug , self . crash_occurred , self . exit_request , self . exclusive_context_count , self . singlestep_enabled , self . jmp_env , self . work_mutex , self . work_list , self . cpu_ases , self . cpu_ases_count , self . num_ases , self . as_ , self . memory , self . tb_jmp_cache , self . gdb_regs , self . gdb_num_regs , self . gdb_num_g_regs , self . node , self . breakpoints , self . watchpoints , self . watchpoint_hit , self . opaque , self . kvm_fd , self . kvm_state , self . kvm_run , self . kvm_dirty_gfns , self . kvm_vcpu_stats_fd , self . vcpu_dirty , self . in_ioctl_lock , self . plugin_state , self . cpu_index , self . cluster_index , self . accel , self . throttle_thread_scheduled , self . ignore_memory_transaction_failures , self . prctl_unalign_sigbus , self . iommu_notifiers , self . neg_align , self . neg) + write!( + f, + "CPUState {{ parent_obj: {:?}, cc: {:?}, nr_cores: {:?}, nr_threads: {:?}, thread: {:?}, thread_id: {:?}, running: {:?}, has_waiter: {:?}, halt_cond: {:?}, thread_kicked: {:?}, created: {:?}, stop: {:?}, stopped: {:?}, start_powered_off: {:?}, unplug: {:?}, crash_occurred: {:?}, exit_request: {:?}, exclusive_context_count: {:?}, singlestep_enabled: {:?}, jmp_env: {:?}, work_mutex: {:?}, work_list: {:?}, cpu_ases: {:?}, cpu_ases_count: {:?}, num_ases: {:?}, as: {:?}, memory: {:?}, tb_jmp_cache: {:?}, gdb_regs: {:?}, gdb_num_regs: {:?}, gdb_num_g_regs: {:?}, node: {:?}, breakpoints: {:?}, watchpoints: {:?}, watchpoint_hit: {:?}, opaque: {:?}, kvm_fd: {:?}, kvm_state: {:?}, kvm_run: {:?}, kvm_dirty_gfns: {:?}, kvm_vcpu_stats_fd: {:?}, vcpu_dirty: {:?}, in_ioctl_lock: {:?}, plugin_state: {:?}, cpu_index: {:?}, cluster_index: {:?}, accel: {:?}, throttle_thread_scheduled: {:?}, ignore_memory_transaction_failures: {:?}, prctl_unalign_sigbus: {:?}, iommu_notifiers: {:?}, neg_align: {:?}, neg: {:?} }}", + self.parent_obj, + self.cc, + self.nr_cores, + self.nr_threads, + self.thread, + self.thread_id, + self.running, + self.has_waiter, + self.halt_cond, + self.thread_kicked, + self.created, + self.stop, + self.stopped, + self.start_powered_off, + self.unplug, + self.crash_occurred, + self.exit_request, + self.exclusive_context_count, + self.singlestep_enabled, + self.jmp_env, + self.work_mutex, + self.work_list, + self.cpu_ases, + self.cpu_ases_count, + self.num_ases, + self.as_, + self.memory, + self.tb_jmp_cache, + self.gdb_regs, + self.gdb_num_regs, + self.gdb_num_g_regs, + self.node, + self.breakpoints, + self.watchpoints, + self.watchpoint_hit, + self.opaque, + self.kvm_fd, + self.kvm_state, + self.kvm_run, + self.kvm_dirty_gfns, + self.kvm_vcpu_stats_fd, + self.vcpu_dirty, + self.in_ioctl_lock, + self.plugin_state, + self.cpu_index, + self.cluster_index, + self.accel, + self.throttle_thread_scheduled, + self.ignore_memory_transaction_failures, + self.prctl_unalign_sigbus, + self.iommu_notifiers, + self.neg_align, + self.neg + ) } } unsafe extern "C" { @@ -4015,7 +4158,18 @@ impl Default for Property { } impl ::std::fmt::Debug for Property { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - write ! (f , "Property {{ name: {:?}, info: {:?}, set_default: {:?}, defval: {:?}, arrayoffset: {:?}, arrayinfo: {:?}, arrayfieldsize: {:?}, link_type: {:?} }}" , self . name , self . info , self . set_default , self . defval , self . arrayoffset , self . arrayinfo , self . arrayfieldsize , self . link_type) + write!( + f, + "Property {{ name: {:?}, info: {:?}, set_default: {:?}, defval: {:?}, arrayoffset: {:?}, arrayinfo: {:?}, arrayfieldsize: {:?}, link_type: {:?} }}", + self.name, + self.info, + self.set_default, + self.defval, + self.arrayoffset, + self.arrayinfo, + self.arrayfieldsize, + self.link_type + ) } } #[repr(C)] @@ -5302,7 +5456,66 @@ impl Default for CPUArchState { } impl ::std::fmt::Debug for CPUArchState { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - write ! (f , "CPUArchState {{ regs: {:?}, segs: {:?}, ldt: {:?}, tr: {:?}, gdt: {:?}, idt: {:?}, cr: {:?}, pdptrs_valid: {:?}, pdptrs: {:?}, bnd_regs: {:?}, bndcs_regs: {:?}, start_init_save: {:?}, fpstt: {:?}, fptags: {:?}, fpregs: {:?}, fp_status: {:?}, ft0: {:?}, mmx_status: {:?}, sse_status: {:?}, xmm_regs: {:?}, xmm_t0: {:?}, mmx_t0: {:?}, opmask_regs: {:?}, xtilecfg: {:?}, xtiledata: {:?}, msr_ia32_sgxlepubkeyhash: {:?}, msr_fixed_counters: {:?}, msr_gp_counters: {:?}, msr_gp_evtsel: {:?}, end_init_save: {:?}, msr_hv_crash_params: {:?}, msr_hv_synic_sint: {:?}, msr_hv_stimer_config: {:?}, msr_hv_stimer_count: {:?}, msr_rtit_addrs: {:?}, lbr_records: {:?}, error_code: {:?}, exception_is_int: {:?}, dr: {:?}, __bindgen_anon_1: {:?}, old_exception: {:?}, end_reset_fields: {:?}, features: {:?}, user_features: {:?}, cpuid_model: {:?}, cache_info_cpuid2: {:?}, cache_info_cpuid4: {:?}, cache_info_amd: {:?}, mtrr_fixed: {:?}, mtrr_var: {:?}, tsc_valid: {:?}, mce_banks: {:?}, tpr_access_type: {:?}, nr_dies: {:?}, nr_modules: {:?}, avail_cpu_topo: {:?} }}" , self . regs , self . segs , self . ldt , self . tr , self . gdt , self . idt , self . cr , self . pdptrs_valid , self . pdptrs , self . bnd_regs , self . bndcs_regs , self . start_init_save , self . fpstt , self . fptags , self . fpregs , self . fp_status , self . ft0 , self . mmx_status , self . sse_status , self . xmm_regs , self . xmm_t0 , self . mmx_t0 , self . opmask_regs , self . xtilecfg , self . xtiledata , self . msr_ia32_sgxlepubkeyhash , self . msr_fixed_counters , self . msr_gp_counters , self . msr_gp_evtsel , self . end_init_save , self . msr_hv_crash_params , self . msr_hv_synic_sint , self . msr_hv_stimer_config , self . msr_hv_stimer_count , self . msr_rtit_addrs , self . lbr_records , self . error_code , self . exception_is_int , self . dr , self . __bindgen_anon_1 , self . old_exception , self . end_reset_fields , self . features , self . user_features , self . cpuid_model , self . cache_info_cpuid2 , self . cache_info_cpuid4 , self . cache_info_amd , self . mtrr_fixed , self . mtrr_var , self . tsc_valid , self . mce_banks , self . tpr_access_type , self . nr_dies , self . nr_modules , self . avail_cpu_topo) + write!( + f, + "CPUArchState {{ regs: {:?}, segs: {:?}, ldt: {:?}, tr: {:?}, gdt: {:?}, idt: {:?}, cr: {:?}, pdptrs_valid: {:?}, pdptrs: {:?}, bnd_regs: {:?}, bndcs_regs: {:?}, start_init_save: {:?}, fpstt: {:?}, fptags: {:?}, fpregs: {:?}, fp_status: {:?}, ft0: {:?}, mmx_status: {:?}, sse_status: {:?}, xmm_regs: {:?}, xmm_t0: {:?}, mmx_t0: {:?}, opmask_regs: {:?}, xtilecfg: {:?}, xtiledata: {:?}, msr_ia32_sgxlepubkeyhash: {:?}, msr_fixed_counters: {:?}, msr_gp_counters: {:?}, msr_gp_evtsel: {:?}, end_init_save: {:?}, msr_hv_crash_params: {:?}, msr_hv_synic_sint: {:?}, msr_hv_stimer_config: {:?}, msr_hv_stimer_count: {:?}, msr_rtit_addrs: {:?}, lbr_records: {:?}, error_code: {:?}, exception_is_int: {:?}, dr: {:?}, __bindgen_anon_1: {:?}, old_exception: {:?}, end_reset_fields: {:?}, features: {:?}, user_features: {:?}, cpuid_model: {:?}, cache_info_cpuid2: {:?}, cache_info_cpuid4: {:?}, cache_info_amd: {:?}, mtrr_fixed: {:?}, mtrr_var: {:?}, tsc_valid: {:?}, mce_banks: {:?}, tpr_access_type: {:?}, nr_dies: {:?}, nr_modules: {:?}, avail_cpu_topo: {:?} }}", + self.regs, + self.segs, + self.ldt, + self.tr, + self.gdt, + self.idt, + self.cr, + self.pdptrs_valid, + self.pdptrs, + self.bnd_regs, + self.bndcs_regs, + self.start_init_save, + self.fpstt, + self.fptags, + self.fpregs, + self.fp_status, + self.ft0, + self.mmx_status, + self.sse_status, + self.xmm_regs, + self.xmm_t0, + self.mmx_t0, + self.opmask_regs, + self.xtilecfg, + self.xtiledata, + self.msr_ia32_sgxlepubkeyhash, + self.msr_fixed_counters, + self.msr_gp_counters, + self.msr_gp_evtsel, + self.end_init_save, + self.msr_hv_crash_params, + self.msr_hv_synic_sint, + self.msr_hv_stimer_config, + self.msr_hv_stimer_count, + self.msr_rtit_addrs, + self.lbr_records, + self.error_code, + self.exception_is_int, + self.dr, + self.__bindgen_anon_1, + self.old_exception, + self.end_reset_fields, + self.features, + self.user_features, + self.cpuid_model, + self.cache_info_cpuid2, + self.cache_info_cpuid4, + self.cache_info_amd, + self.mtrr_fixed, + self.mtrr_var, + self.tsc_valid, + self.mce_banks, + self.tpr_access_type, + self.nr_dies, + self.nr_modules, + self.avail_cpu_topo + ) } } pub type CPUX86State = CPUArchState; @@ -5539,7 +5752,54 @@ impl Default for ArchCPU { } impl ::std::fmt::Debug for ArchCPU { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - write ! (f , "ArchCPU {{ parent_obj: {:?}, env: {:?}, vmsentry: {:?}, hyperv_vendor: {:?}, hyperv_synic_kvm_only: {:?}, hyperv_passthrough: {:?}, hyperv_no_nonarch_cs: {:?}, hyperv_vendor_id: {:?}, hyperv_interface_id: {:?}, hyperv_limits: {:?}, hyperv_enforce_cpuid: {:?}, check_cpuid: {:?}, enforce_cpuid: {:?}, force_features: {:?}, expose_kvm: {:?}, expose_tcg: {:?}, migratable: {:?}, migrate_smi_count: {:?}, max_features: {:?}, vmware_cpuid_freq: {:?}, cache_info_passthrough: {:?}, mwait: {:?}, filtered_features: {:?}, enable_pmu: {:?}, enable_lmce: {:?}, enable_l3_cache: {:?}, l1_cache_per_core: {:?}, legacy_cache: {:?}, legacy_multi_node: {:?}, enable_cpuid_0xb: {:?}, full_cpuid_auto_level: {:?}, vendor_cpuid_only: {:?}, amd_topoext_features_only: {:?}, intel_pt_auto_level: {:?}, fill_mtrr_mask: {:?}, host_phys_bits: {:?}, kvm_pv_enforce_cpuid: {:?}, apic_state: {:?}, cpu_as_root: {:?}, cpu_as_mem: {:?}, smram: {:?}, machine_done: {:?}, kvm_msr_buf: {:?}, xen_vapic: {:?} }}" , self . parent_obj , self . env , self . vmsentry , self . hyperv_vendor , self . hyperv_synic_kvm_only , self . hyperv_passthrough , self . hyperv_no_nonarch_cs , self . hyperv_vendor_id , self . hyperv_interface_id , self . hyperv_limits , self . hyperv_enforce_cpuid , self . check_cpuid , self . enforce_cpuid , self . force_features , self . expose_kvm , self . expose_tcg , self . migratable , self . migrate_smi_count , self . max_features , self . vmware_cpuid_freq , self . cache_info_passthrough , self . mwait , self . filtered_features , self . enable_pmu , self . enable_lmce , self . enable_l3_cache , self . l1_cache_per_core , self . legacy_cache , self . legacy_multi_node , self . enable_cpuid_0xb , self . full_cpuid_auto_level , self . vendor_cpuid_only , self . amd_topoext_features_only , self . intel_pt_auto_level , self . fill_mtrr_mask , self . host_phys_bits , self . kvm_pv_enforce_cpuid , self . apic_state , self . cpu_as_root , self . cpu_as_mem , self . smram , self . machine_done , self . kvm_msr_buf , self . xen_vapic) + write!( + f, + "ArchCPU {{ parent_obj: {:?}, env: {:?}, vmsentry: {:?}, hyperv_vendor: {:?}, hyperv_synic_kvm_only: {:?}, hyperv_passthrough: {:?}, hyperv_no_nonarch_cs: {:?}, hyperv_vendor_id: {:?}, hyperv_interface_id: {:?}, hyperv_limits: {:?}, hyperv_enforce_cpuid: {:?}, check_cpuid: {:?}, enforce_cpuid: {:?}, force_features: {:?}, expose_kvm: {:?}, expose_tcg: {:?}, migratable: {:?}, migrate_smi_count: {:?}, max_features: {:?}, vmware_cpuid_freq: {:?}, cache_info_passthrough: {:?}, mwait: {:?}, filtered_features: {:?}, enable_pmu: {:?}, enable_lmce: {:?}, enable_l3_cache: {:?}, l1_cache_per_core: {:?}, legacy_cache: {:?}, legacy_multi_node: {:?}, enable_cpuid_0xb: {:?}, full_cpuid_auto_level: {:?}, vendor_cpuid_only: {:?}, amd_topoext_features_only: {:?}, intel_pt_auto_level: {:?}, fill_mtrr_mask: {:?}, host_phys_bits: {:?}, kvm_pv_enforce_cpuid: {:?}, apic_state: {:?}, cpu_as_root: {:?}, cpu_as_mem: {:?}, smram: {:?}, machine_done: {:?}, kvm_msr_buf: {:?}, xen_vapic: {:?} }}", + self.parent_obj, + self.env, + self.vmsentry, + self.hyperv_vendor, + self.hyperv_synic_kvm_only, + self.hyperv_passthrough, + self.hyperv_no_nonarch_cs, + self.hyperv_vendor_id, + self.hyperv_interface_id, + self.hyperv_limits, + self.hyperv_enforce_cpuid, + self.check_cpuid, + self.enforce_cpuid, + self.force_features, + self.expose_kvm, + self.expose_tcg, + self.migratable, + self.migrate_smi_count, + self.max_features, + self.vmware_cpuid_freq, + self.cache_info_passthrough, + self.mwait, + self.filtered_features, + self.enable_pmu, + self.enable_lmce, + self.enable_l3_cache, + self.l1_cache_per_core, + self.legacy_cache, + self.legacy_multi_node, + self.enable_cpuid_0xb, + self.full_cpuid_auto_level, + self.vendor_cpuid_only, + self.amd_topoext_features_only, + self.intel_pt_auto_level, + self.fill_mtrr_mask, + self.host_phys_bits, + self.kvm_pv_enforce_cpuid, + self.apic_state, + self.cpu_as_root, + self.cpu_as_mem, + self.smram, + self.machine_done, + self.kvm_msr_buf, + self.xen_vapic + ) } } unsafe extern "C" { @@ -7784,12 +8044,12 @@ unsafe extern "C" { unsafe extern "C" { pub fn libafl_tcg_gen_asan(addr: *mut TCGTemp, size: usize); } +pub type libafl_backdoor_exec_cb = ::std::option::Option< + unsafe extern "C" fn(data: u64, cpu: *mut CPUArchState, pc: target_ulong), +>; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct libafl_backdoor_hook { - pub gen: ::std::option::Option< - unsafe extern "C" fn(data: u64, cpu: *mut CPUArchState, pc: target_ulong), - >, pub data: u64, pub num: usize, pub helper_info: TCGHelperInfo, @@ -7797,18 +8057,16 @@ pub struct libafl_backdoor_hook { } #[allow(clippy::unnecessary_operation, clippy::identity_op)] const _: () = { - ["Size of libafl_backdoor_hook"][::std::mem::size_of::() - 120usize]; + ["Size of libafl_backdoor_hook"][::std::mem::size_of::() - 112usize]; ["Alignment of libafl_backdoor_hook"][::std::mem::align_of::() - 8usize]; - ["Offset of field: libafl_backdoor_hook::gen"] - [::std::mem::offset_of!(libafl_backdoor_hook, gen) - 0usize]; ["Offset of field: libafl_backdoor_hook::data"] - [::std::mem::offset_of!(libafl_backdoor_hook, data) - 8usize]; + [::std::mem::offset_of!(libafl_backdoor_hook, data) - 0usize]; ["Offset of field: libafl_backdoor_hook::num"] - [::std::mem::offset_of!(libafl_backdoor_hook, num) - 16usize]; + [::std::mem::offset_of!(libafl_backdoor_hook, num) - 8usize]; ["Offset of field: libafl_backdoor_hook::helper_info"] - [::std::mem::offset_of!(libafl_backdoor_hook, helper_info) - 24usize]; + [::std::mem::offset_of!(libafl_backdoor_hook, helper_info) - 16usize]; ["Offset of field: libafl_backdoor_hook::next"] - [::std::mem::offset_of!(libafl_backdoor_hook, next) - 112usize]; + [::std::mem::offset_of!(libafl_backdoor_hook, next) - 104usize]; }; impl Default for libafl_backdoor_hook { fn default() -> Self { @@ -7820,15 +8078,7 @@ impl Default for libafl_backdoor_hook { } } unsafe extern "C" { - pub fn libafl_gen_backdoor(pc: target_ulong); -} -unsafe extern "C" { - pub fn libafl_add_backdoor_hook( - exec: ::std::option::Option< - unsafe extern "C" fn(data: u64, cpu: *mut CPUArchState, pc: target_ulong), - >, - data: u64, - ) -> usize; + pub fn libafl_add_backdoor_hook(exec_cb: libafl_backdoor_exec_cb, data: u64) -> usize; } unsafe extern "C" { pub fn libafl_qemu_remove_backdoor_hook( @@ -7839,14 +8089,20 @@ unsafe extern "C" { unsafe extern "C" { pub fn libafl_qemu_hook_backdoor_run(pc_next: vaddr); } +pub type libafl_block_pre_gen_cb = + ::std::option::Option u64>; +pub type libafl_block_post_gen_cb = ::std::option::Option< + unsafe extern "C" fn(data: u64, pc: target_ulong, block_length: target_ulong), +>; +pub type libafl_block_exec_cb = ::std::option::Option; +pub type libafl_block_jit_cb = + ::std::option::Option usize>; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct libafl_block_hook { - pub gen: ::std::option::Option u64>, - pub post_gen: ::std::option::Option< - unsafe extern "C" fn(data: u64, pc: target_ulong, block_length: target_ulong), - >, - pub jit: ::std::option::Option usize>, + pub pre_gen_cb: libafl_block_pre_gen_cb, + pub post_gen_cb: libafl_block_post_gen_cb, + pub jit_cb: libafl_block_jit_cb, pub data: u64, pub num: usize, pub helper_info: TCGHelperInfo, @@ -7856,12 +8112,12 @@ pub struct libafl_block_hook { const _: () = { ["Size of libafl_block_hook"][::std::mem::size_of::() - 136usize]; ["Alignment of libafl_block_hook"][::std::mem::align_of::() - 8usize]; - ["Offset of field: libafl_block_hook::gen"] - [::std::mem::offset_of!(libafl_block_hook, gen) - 0usize]; - ["Offset of field: libafl_block_hook::post_gen"] - [::std::mem::offset_of!(libafl_block_hook, post_gen) - 8usize]; - ["Offset of field: libafl_block_hook::jit"] - [::std::mem::offset_of!(libafl_block_hook, jit) - 16usize]; + ["Offset of field: libafl_block_hook::pre_gen_cb"] + [::std::mem::offset_of!(libafl_block_hook, pre_gen_cb) - 0usize]; + ["Offset of field: libafl_block_hook::post_gen_cb"] + [::std::mem::offset_of!(libafl_block_hook, post_gen_cb) - 8usize]; + ["Offset of field: libafl_block_hook::jit_cb"] + [::std::mem::offset_of!(libafl_block_hook, jit_cb) - 16usize]; ["Offset of field: libafl_block_hook::data"] [::std::mem::offset_of!(libafl_block_hook, data) - 24usize]; ["Offset of field: libafl_block_hook::num"] @@ -7881,16 +8137,15 @@ impl Default for libafl_block_hook { } } unsafe extern "C" { - pub fn libafl_qemu_hook_block_post_gen(tb: *mut TranslationBlock, pc: vaddr); + pub fn libafl_add_block_hook( + pre_gen_cb: libafl_block_pre_gen_cb, + post_gen_cb: libafl_block_post_gen_cb, + exec_cb: libafl_block_exec_cb, + data: u64, + ) -> usize; } unsafe extern "C" { - pub fn libafl_qemu_hook_block_run(pc: target_ulong); -} -unsafe extern "C" { - pub fn libafl_qemu_block_hook_set_jit( - num: usize, - jit: ::std::option::Option usize>, - ) -> bool; + pub fn libafl_qemu_block_hook_set_jit(num: usize, jit_cb: libafl_block_jit_cb) -> bool; } unsafe extern "C" { pub fn libafl_qemu_remove_block_hook( @@ -7899,21 +8154,25 @@ unsafe extern "C" { ) -> ::std::os::raw::c_int; } unsafe extern "C" { - pub fn libafl_add_block_hook( - gen: ::std::option::Option u64>, - post_gen: ::std::option::Option< - unsafe extern "C" fn(data: u64, pc: target_ulong, block_length: target_ulong), - >, - exec: ::std::option::Option, - data: u64, - ) -> usize; + pub fn libafl_qemu_hook_block_pre_run(pc: target_ulong); } +unsafe extern "C" { + pub fn libafl_qemu_hook_block_post_run(tb: *mut TranslationBlock, pc: vaddr); +} +pub type libafl_cmp_gen_cb = + ::std::option::Option u64>; +pub type libafl_cmp_exec1_cb = + ::std::option::Option; +pub type libafl_cmp_exec2_cb = + ::std::option::Option; +pub type libafl_cmp_exec4_cb = + ::std::option::Option; +pub type libafl_cmp_exec8_cb = + ::std::option::Option; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct libafl_cmp_hook { - pub gen: ::std::option::Option< - unsafe extern "C" fn(data: u64, pc: target_ulong, size: usize) -> u64, - >, + pub gen_cb: libafl_cmp_gen_cb, pub data: u64, pub num: usize, pub helper_info1: TCGHelperInfo, @@ -7926,8 +8185,8 @@ pub struct libafl_cmp_hook { const _: () = { ["Size of libafl_cmp_hook"][::std::mem::size_of::() - 384usize]; ["Alignment of libafl_cmp_hook"][::std::mem::align_of::() - 8usize]; - ["Offset of field: libafl_cmp_hook::gen"] - [::std::mem::offset_of!(libafl_cmp_hook, gen) - 0usize]; + ["Offset of field: libafl_cmp_hook::gen_cb"] + [::std::mem::offset_of!(libafl_cmp_hook, gen_cb) - 0usize]; ["Offset of field: libafl_cmp_hook::data"] [::std::mem::offset_of!(libafl_cmp_hook, data) - 8usize]; ["Offset of field: libafl_cmp_hook::num"] @@ -7957,13 +8216,11 @@ unsafe extern "C" { } unsafe extern "C" { pub fn libafl_add_cmp_hook( - gen: ::std::option::Option< - unsafe extern "C" fn(data: u64, pc: target_ulong, size: usize) -> u64, - >, - exec1: ::std::option::Option, - exec2: ::std::option::Option, - exec4: ::std::option::Option, - exec8: ::std::option::Option, + gen_cb: libafl_cmp_gen_cb, + exec1_cb: libafl_cmp_exec1_cb, + exec2_cb: libafl_cmp_exec2_cb, + exec4_cb: libafl_cmp_exec4_cb, + exec8_cb: libafl_cmp_exec8_cb, data: u64, ) -> usize; } @@ -7973,13 +8230,17 @@ unsafe extern "C" { invalidate: ::std::os::raw::c_int, ) -> ::std::os::raw::c_int; } +pub type libafl_edge_gen_cb = ::std::option::Option< + unsafe extern "C" fn(data: u64, src: target_ulong, dst: target_ulong) -> u64, +>; +pub type libafl_edge_exec_cb = ::std::option::Option; +pub type libafl_edge_jit_cb = + ::std::option::Option usize>; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct libafl_edge_hook { - pub gen: ::std::option::Option< - unsafe extern "C" fn(data: u64, src: target_ulong, dst: target_ulong) -> u64, - >, - pub jit: ::std::option::Option usize>, + pub gen_cb: libafl_edge_gen_cb, + pub jit_cb: libafl_edge_jit_cb, pub data: u64, pub num: usize, pub cur_id: u64, @@ -7990,10 +8251,10 @@ pub struct libafl_edge_hook { const _: () = { ["Size of libafl_edge_hook"][::std::mem::size_of::() - 136usize]; ["Alignment of libafl_edge_hook"][::std::mem::align_of::() - 8usize]; - ["Offset of field: libafl_edge_hook::gen"] - [::std::mem::offset_of!(libafl_edge_hook, gen) - 0usize]; - ["Offset of field: libafl_edge_hook::jit"] - [::std::mem::offset_of!(libafl_edge_hook, jit) - 8usize]; + ["Offset of field: libafl_edge_hook::gen_cb"] + [::std::mem::offset_of!(libafl_edge_hook, gen_cb) - 0usize]; + ["Offset of field: libafl_edge_hook::jit_cb"] + [::std::mem::offset_of!(libafl_edge_hook, jit_cb) - 8usize]; ["Offset of field: libafl_edge_hook::data"] [::std::mem::offset_of!(libafl_edge_hook, data) - 16usize]; ["Offset of field: libafl_edge_hook::num"] @@ -8027,18 +8288,13 @@ unsafe extern "C" { } unsafe extern "C" { pub fn libafl_add_edge_hook( - gen: ::std::option::Option< - unsafe extern "C" fn(data: u64, src: target_ulong, dst: target_ulong) -> u64, - >, - exec: ::std::option::Option, + gen_cb: libafl_edge_gen_cb, + exec_cb: libafl_edge_exec_cb, data: u64, ) -> usize; } unsafe extern "C" { - pub fn libafl_qemu_edge_hook_set_jit( - num: usize, - jit: ::std::option::Option usize>, - ) -> bool; + pub fn libafl_qemu_edge_hook_set_jit(num: usize, jit_cb: libafl_edge_jit_cb) -> bool; } unsafe extern "C" { pub fn libafl_qemu_remove_edge_hook( @@ -8127,7 +8383,7 @@ pub type libafl_rw_execN_cb = ::std::option::Option< #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct libafl_rw_hook { - pub gen: libafl_rw_gen_cb, + pub gen_cb: libafl_rw_gen_cb, pub data: u64, pub num: usize, pub helper_info1: TCGHelperInfo, @@ -8141,7 +8397,8 @@ pub struct libafl_rw_hook { const _: () = { ["Size of libafl_rw_hook"][::std::mem::size_of::() - 472usize]; ["Alignment of libafl_rw_hook"][::std::mem::align_of::() - 8usize]; - ["Offset of field: libafl_rw_hook::gen"][::std::mem::offset_of!(libafl_rw_hook, gen) - 0usize]; + ["Offset of field: libafl_rw_hook::gen_cb"] + [::std::mem::offset_of!(libafl_rw_hook, gen_cb) - 0usize]; ["Offset of field: libafl_rw_hook::data"] [::std::mem::offset_of!(libafl_rw_hook, data) - 8usize]; ["Offset of field: libafl_rw_hook::num"][::std::mem::offset_of!(libafl_rw_hook, num) - 16usize]; @@ -8175,23 +8432,23 @@ unsafe extern "C" { } unsafe extern "C" { pub fn libafl_add_read_hook( - gen: libafl_rw_gen_cb, - exec1: libafl_rw_exec_cb, - exec2: libafl_rw_exec_cb, - exec4: libafl_rw_exec_cb, - exec8: libafl_rw_exec_cb, - execN: libafl_rw_execN_cb, + gen_cb: libafl_rw_gen_cb, + exec1_cb: libafl_rw_exec_cb, + exec2_cb: libafl_rw_exec_cb, + exec4_cb: libafl_rw_exec_cb, + exec8_cb: libafl_rw_exec_cb, + execN_cb: libafl_rw_execN_cb, data: u64, ) -> usize; } unsafe extern "C" { pub fn libafl_add_write_hook( - gen: libafl_rw_gen_cb, - exec1: libafl_rw_exec_cb, - exec2: libafl_rw_exec_cb, - exec4: libafl_rw_exec_cb, - exec8: libafl_rw_exec_cb, - execN: libafl_rw_execN_cb, + gen_cb: libafl_rw_gen_cb, + exec1_cb: libafl_rw_exec_cb, + exec2_cb: libafl_rw_exec_cb, + exec4_cb: libafl_rw_exec_cb, + exec8_cb: libafl_rw_exec_cb, + execN_cb: libafl_rw_execN_cb, data: u64, ) -> usize; } diff --git a/libafl_qemu/libafl_qemu_sys/src/lib.rs b/libafl_qemu/libafl_qemu_sys/src/lib.rs index 4f1bc18138..9ac068ca19 100644 --- a/libafl_qemu/libafl_qemu_sys/src/lib.rs +++ b/libafl_qemu/libafl_qemu_sys/src/lib.rs @@ -44,7 +44,7 @@ macro_rules! extern_c_checked { static [<__ $c_fn:upper __>]: unsafe extern "C" fn($($param_ty),*) $( -> $ret_ty )? = $c_fn; } - extern "C" { + unsafe extern "C" { $visibility fn $c_fn($($param_ident : $param_ty),*) $( -> $ret_ty )?; } @@ -64,7 +64,7 @@ macro_rules! extern_c_checked { static [<__ $c_var:upper __>]: [<__ $c_var:upper _STRUCT__>] = unsafe { [<__ $c_var:upper _STRUCT__>] { member: &raw const $c_var } }; } - extern "C" { + unsafe extern "C" { $visibility static $c_var: $c_var_ty; } @@ -84,7 +84,7 @@ macro_rules! extern_c_checked { static mut [<__ $c_var:upper __>]: [<__ $c_var:upper _STRUCT__>] = unsafe { [<__ $c_var:upper _STRUCT__>] { member: &raw const $c_var } }; } - extern "C" { + unsafe extern "C" { $visibility static mut $c_var: $c_var_ty; } diff --git a/libafl_qemu/libafl_qemu_sys/src/usermode.rs b/libafl_qemu/libafl_qemu_sys/src/usermode.rs index 50b526c5b1..6cbce5f4f1 100644 --- a/libafl_qemu/libafl_qemu_sys/src/usermode.rs +++ b/libafl_qemu/libafl_qemu_sys/src/usermode.rs @@ -7,12 +7,12 @@ use std::convert::Infallible; use libc::{c_char, strlen}; use num_enum::{IntoPrimitive, TryFromPrimitive}; #[cfg(feature = "python")] -use pyo3::{pyclass, pymethods, types::PyInt, Bound, IntoPyObject, Python}; +use pyo3::{Bound, IntoPyObject, Python, pyclass, pymethods, types::PyInt}; use strum_macros::EnumIter; use crate::MmapPerms; #[cfg(target_os = "linux")] -use crate::{libafl_mapinfo, GuestAddr}; +use crate::{GuestAddr, libafl_mapinfo}; #[derive(IntoPrimitive, TryFromPrimitive, Debug, Clone, Copy, EnumIter, PartialEq, Eq)] #[repr(i32)] diff --git a/libafl_qemu/runtime/libafl_qemu_stub_bindings.rs b/libafl_qemu/runtime/libafl_qemu_stub_bindings.rs index 62517cefc2..cb88fef584 100644 --- a/libafl_qemu/runtime/libafl_qemu_stub_bindings.rs +++ b/libafl_qemu/runtime/libafl_qemu_stub_bindings.rs @@ -1,7 +1,150 @@ -/* 1.86.0-nightly */ -/* qemu git hash: 695657e4f3f408c34b146d5191b102d5eb99b74b */ +/* 1.87.0-nightly */ +/* qemu git hash: 06c738f64a4a92d5fc8184c9b5a9fe9340f4a63f */ /* automatically generated by rust-bindgen 0.71.1 */ +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = *(core::ptr::addr_of!((*this).storage) as *const u8).offset(byte_index as isize); + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { + byte | mask + } else { + byte & !mask + } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = + (core::ptr::addr_of_mut!((*this).storage) as *mut u8).offset(byte_index as isize); + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!((bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::()); + let mut val = 0; + for i in 0..(bit_width as usize) { + if Self::raw_get_bit(this, i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!((bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::()); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + Self::raw_set_bit(this, index + bit_offset, val_bit_is_set); + } + } +} +#[derive(PartialEq, Copy, Clone, Hash, Debug, Default)] +#[repr(C)] +pub struct __BindgenComplex { + pub re: T, + pub im: T, +} pub const LIBAFL_SYNC_EXIT_OPCODE: u32 = 1727150607; pub const LIBAFL_BACKDOOR_OPCODE: u32 = 1156725263; pub const LIBAFL_QEMU_TEST_VALUE: u32 = 3405691582; @@ -9,6 +152,7 @@ pub const LIBAFL_QEMU_HDR_VERSION_NUMBER: u32 = 73; pub const _STDIO_H: u32 = 1; pub const _FEATURES_H: u32 = 1; pub const _DEFAULT_SOURCE: u32 = 1; +pub const __GLIBC_USE_ISOC2Y: u32 = 0; pub const __GLIBC_USE_ISOC23: u32 = 0; pub const __USE_ISOC11: u32 = 1; pub const __USE_ISOC99: u32 = 1; @@ -42,7 +186,7 @@ pub const __STDC_IEC_60559_COMPLEX__: u32 = 201404; pub const __STDC_ISO_10646__: u32 = 201706; pub const __GNU_LIBRARY__: u32 = 6; pub const __GLIBC__: u32 = 2; -pub const __GLIBC_MINOR__: u32 = 40; +pub const __GLIBC_MINOR__: u32 = 41; pub const _SYS_CDEFS_H: u32 = 1; pub const __glibc_c99_flexarr_available: u32 = 1; pub const __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI: u32 = 0; @@ -88,8 +232,8 @@ pub const _BITS_STDIO_LIM_H: u32 = 1; pub const FILENAME_MAX: u32 = 4096; pub const L_ctermid: u32 = 9; pub const FOPEN_MAX: u32 = 16; -pub const __HAVE_FLOAT128: u32 = 0; -pub const __HAVE_DISTINCT_FLOAT128: u32 = 0; +pub const __HAVE_FLOAT128: u32 = 1; +pub const __HAVE_DISTINCT_FLOAT128: u32 = 1; pub const __HAVE_FLOAT64X: u32 = 1; pub const __HAVE_FLOAT64X_LONG_DOUBLE: u32 = 1; pub const __HAVE_FLOAT16: u32 = 0; @@ -434,7 +578,9 @@ pub struct _IO_FILE { pub _markers: *mut _IO_marker, pub _chain: *mut _IO_FILE, pub _fileno: ::std::os::raw::c_int, - pub _flags2: ::std::os::raw::c_int, + pub _bitfield_align_1: [u32; 0], + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 3usize]>, + pub _short_backupbuf: [::std::os::raw::c_char; 1usize], pub _old_offset: __off_t, pub _cur_column: ::std::os::raw::c_ushort, pub _vtable_offset: ::std::os::raw::c_schar, @@ -479,7 +625,8 @@ const _: () = { ["Offset of field: _IO_FILE::_markers"][::std::mem::offset_of!(_IO_FILE, _markers) - 96usize]; ["Offset of field: _IO_FILE::_chain"][::std::mem::offset_of!(_IO_FILE, _chain) - 104usize]; ["Offset of field: _IO_FILE::_fileno"][::std::mem::offset_of!(_IO_FILE, _fileno) - 112usize]; - ["Offset of field: _IO_FILE::_flags2"][::std::mem::offset_of!(_IO_FILE, _flags2) - 116usize]; + ["Offset of field: _IO_FILE::_short_backupbuf"] + [::std::mem::offset_of!(_IO_FILE, _short_backupbuf) - 119usize]; ["Offset of field: _IO_FILE::_old_offset"] [::std::mem::offset_of!(_IO_FILE, _old_offset) - 120usize]; ["Offset of field: _IO_FILE::_cur_column"] @@ -511,6 +658,50 @@ impl Default for _IO_FILE { } } } +impl _IO_FILE { + #[inline] + pub fn _flags2(&self) -> ::std::os::raw::c_int { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 24u8) as u32) } + } + #[inline] + pub fn set__flags2(&mut self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 24u8, val as u64) + } + } + #[inline] + pub unsafe fn _flags2_raw(this: *const Self) -> ::std::os::raw::c_int { + unsafe { + ::std::mem::transmute(<__BindgenBitfieldUnit<[u8; 3usize]>>::raw_get( + ::std::ptr::addr_of!((*this)._bitfield_1), + 0usize, + 24u8, + ) as u32) + } + } + #[inline] + pub unsafe fn set__flags2_raw(this: *mut Self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit<[u8; 3usize]>>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 24u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1(_flags2: ::std::os::raw::c_int) -> __BindgenBitfieldUnit<[u8; 3usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 3usize]> = Default::default(); + __bindgen_bitfield_unit.set(0usize, 24u8, { + let _flags2: u32 = unsafe { ::std::mem::transmute(_flags2) }; + _flags2 as u64 + }); + __bindgen_bitfield_unit + } +} pub type cookie_read_function_t = ::std::option::Option< unsafe extern "C" fn( __cookie: *mut ::std::os::raw::c_void, @@ -771,6 +962,8 @@ unsafe extern "C" { ... ) -> ::std::os::raw::c_int; } +pub type __cfloat128 = __BindgenComplex; +pub type _Float128 = u128; pub type _Float32 = f32; pub type _Float64 = f64; pub type _Float32x = f64; diff --git a/libafl_qemu/runtime/nyx_stub_bindings.rs b/libafl_qemu/runtime/nyx_stub_bindings.rs index 6366fcee33..48bbdaa946 100644 --- a/libafl_qemu/runtime/nyx_stub_bindings.rs +++ b/libafl_qemu/runtime/nyx_stub_bindings.rs @@ -1,7 +1,150 @@ -/* 1.86.0-nightly */ -/* qemu git hash: 695657e4f3f408c34b146d5191b102d5eb99b74b */ +/* 1.87.0-nightly */ +/* qemu git hash: 06c738f64a4a92d5fc8184c9b5a9fe9340f4a63f */ /* automatically generated by rust-bindgen 0.71.1 */ +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = *(core::ptr::addr_of!((*this).storage) as *const u8).offset(byte_index as isize); + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { + byte | mask + } else { + byte & !mask + } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = + (core::ptr::addr_of_mut!((*this).storage) as *mut u8).offset(byte_index as isize); + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!((bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::()); + let mut val = 0; + for i in 0..(bit_width as usize) { + if Self::raw_get_bit(this, i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!((bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::()); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + Self::raw_set_bit(this, index + bit_offset, val_bit_is_set); + } + } +} +#[derive(PartialEq, Copy, Clone, Hash, Debug, Default)] +#[repr(C)] +pub struct __BindgenComplex { + pub re: T, + pub im: T, +} #[repr(C)] #[derive(Default)] pub struct __IncompleteArrayField(::std::marker::PhantomData, [T; 0]); @@ -35,6 +178,7 @@ impl ::std::fmt::Debug for __IncompleteArrayField { pub const _STDIO_H: u32 = 1; pub const _FEATURES_H: u32 = 1; pub const _DEFAULT_SOURCE: u32 = 1; +pub const __GLIBC_USE_ISOC2Y: u32 = 0; pub const __GLIBC_USE_ISOC23: u32 = 0; pub const __USE_ISOC11: u32 = 1; pub const __USE_ISOC99: u32 = 1; @@ -68,7 +212,7 @@ pub const __STDC_IEC_60559_COMPLEX__: u32 = 201404; pub const __STDC_ISO_10646__: u32 = 201706; pub const __GNU_LIBRARY__: u32 = 6; pub const __GLIBC__: u32 = 2; -pub const __GLIBC_MINOR__: u32 = 40; +pub const __GLIBC_MINOR__: u32 = 41; pub const _SYS_CDEFS_H: u32 = 1; pub const __glibc_c99_flexarr_available: u32 = 1; pub const __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI: u32 = 0; @@ -114,8 +258,8 @@ pub const _BITS_STDIO_LIM_H: u32 = 1; pub const FILENAME_MAX: u32 = 4096; pub const L_ctermid: u32 = 9; pub const FOPEN_MAX: u32 = 16; -pub const __HAVE_FLOAT128: u32 = 0; -pub const __HAVE_DISTINCT_FLOAT128: u32 = 0; +pub const __HAVE_FLOAT128: u32 = 1; +pub const __HAVE_DISTINCT_FLOAT128: u32 = 1; pub const __HAVE_FLOAT64X: u32 = 1; pub const __HAVE_FLOAT64X_LONG_DOUBLE: u32 = 1; pub const __HAVE_FLOAT16: u32 = 0; @@ -458,7 +602,9 @@ pub struct _IO_FILE { pub _markers: *mut _IO_marker, pub _chain: *mut _IO_FILE, pub _fileno: ::std::os::raw::c_int, - pub _flags2: ::std::os::raw::c_int, + pub _bitfield_align_1: [u32; 0], + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 3usize]>, + pub _short_backupbuf: [::std::os::raw::c_char; 1usize], pub _old_offset: __off_t, pub _cur_column: ::std::os::raw::c_ushort, pub _vtable_offset: ::std::os::raw::c_schar, @@ -503,7 +649,8 @@ const _: () = { ["Offset of field: _IO_FILE::_markers"][::std::mem::offset_of!(_IO_FILE, _markers) - 96usize]; ["Offset of field: _IO_FILE::_chain"][::std::mem::offset_of!(_IO_FILE, _chain) - 104usize]; ["Offset of field: _IO_FILE::_fileno"][::std::mem::offset_of!(_IO_FILE, _fileno) - 112usize]; - ["Offset of field: _IO_FILE::_flags2"][::std::mem::offset_of!(_IO_FILE, _flags2) - 116usize]; + ["Offset of field: _IO_FILE::_short_backupbuf"] + [::std::mem::offset_of!(_IO_FILE, _short_backupbuf) - 119usize]; ["Offset of field: _IO_FILE::_old_offset"] [::std::mem::offset_of!(_IO_FILE, _old_offset) - 120usize]; ["Offset of field: _IO_FILE::_cur_column"] @@ -535,6 +682,50 @@ impl Default for _IO_FILE { } } } +impl _IO_FILE { + #[inline] + pub fn _flags2(&self) -> ::std::os::raw::c_int { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 24u8) as u32) } + } + #[inline] + pub fn set__flags2(&mut self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 24u8, val as u64) + } + } + #[inline] + pub unsafe fn _flags2_raw(this: *const Self) -> ::std::os::raw::c_int { + unsafe { + ::std::mem::transmute(<__BindgenBitfieldUnit<[u8; 3usize]>>::raw_get( + ::std::ptr::addr_of!((*this)._bitfield_1), + 0usize, + 24u8, + ) as u32) + } + } + #[inline] + pub unsafe fn set__flags2_raw(this: *mut Self, val: ::std::os::raw::c_int) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit<[u8; 3usize]>>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 24u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1(_flags2: ::std::os::raw::c_int) -> __BindgenBitfieldUnit<[u8; 3usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 3usize]> = Default::default(); + __bindgen_bitfield_unit.set(0usize, 24u8, { + let _flags2: u32 = unsafe { ::std::mem::transmute(_flags2) }; + _flags2 as u64 + }); + __bindgen_bitfield_unit + } +} pub type cookie_read_function_t = ::std::option::Option< unsafe extern "C" fn( __cookie: *mut ::std::os::raw::c_void, @@ -794,6 +985,8 @@ unsafe extern "C" { ... ) -> ::std::os::raw::c_int; } +pub type __cfloat128 = __BindgenComplex; +pub type _Float128 = u128; pub type _Float32 = f32; pub type _Float64 = f64; pub type _Float32x = f64; diff --git a/libafl_qemu/src/arch/aarch64.rs b/libafl_qemu/src/arch/aarch64.rs index 4017a79c26..e232b8466b 100644 --- a/libafl_qemu/src/arch/aarch64.rs +++ b/libafl_qemu/src/arch/aarch64.rs @@ -1,14 +1,14 @@ use std::sync::OnceLock; use capstone::arch::BuildsCapstone; -use enum_map::{enum_map, EnumMap}; +use enum_map::{EnumMap, enum_map}; use num_enum::{IntoPrimitive, TryFromPrimitive}; #[cfg(feature = "python")] use pyo3::prelude::*; pub use strum_macros::EnumIter; pub use syscall_numbers::aarch64::*; -use crate::{sync_exit::ExitArgs, CallingConvention, GuestAddr, QemuRWError, QemuRWErrorKind}; +use crate::{CallingConvention, GuestAddr, QemuRWError, QemuRWErrorKind, sync_exit::ExitArgs}; #[expect(non_upper_case_globals)] impl CallingConvention { diff --git a/libafl_qemu/src/arch/arm.rs b/libafl_qemu/src/arch/arm.rs index 313235b560..81d5bf076b 100644 --- a/libafl_qemu/src/arch/arm.rs +++ b/libafl_qemu/src/arch/arm.rs @@ -1,14 +1,14 @@ use std::sync::OnceLock; use capstone::arch::BuildsCapstone; -use enum_map::{enum_map, EnumMap}; +use enum_map::{EnumMap, enum_map}; use num_enum::{IntoPrimitive, TryFromPrimitive}; #[cfg(feature = "python")] use pyo3::prelude::*; pub use strum_macros::EnumIter; pub use syscall_numbers::arm::*; -use crate::{sync_exit::ExitArgs, CallingConvention, GuestAddr, QemuRWError, QemuRWErrorKind}; +use crate::{CallingConvention, GuestAddr, QemuRWError, QemuRWErrorKind, sync_exit::ExitArgs}; #[expect(non_upper_case_globals)] impl CallingConvention { diff --git a/libafl_qemu/src/arch/hexagon.rs b/libafl_qemu/src/arch/hexagon.rs index 7ef78be30e..6544033a44 100644 --- a/libafl_qemu/src/arch/hexagon.rs +++ b/libafl_qemu/src/arch/hexagon.rs @@ -1,12 +1,12 @@ use std::sync::OnceLock; -use enum_map::{enum_map, EnumMap}; +use enum_map::{EnumMap, enum_map}; use num_enum::{IntoPrimitive, TryFromPrimitive}; #[cfg(feature = "python")] use pyo3::prelude::*; pub use strum_macros::EnumIter; -use crate::{sync_exit::ExitArgs, CallingConvention, QemuRWError, QemuRWErrorKind}; +use crate::{CallingConvention, QemuRWError, QemuRWErrorKind, sync_exit::ExitArgs}; #[expect(non_upper_case_globals)] impl CallingConvention { diff --git a/libafl_qemu/src/arch/i386.rs b/libafl_qemu/src/arch/i386.rs index bb85184096..00358668ce 100644 --- a/libafl_qemu/src/arch/i386.rs +++ b/libafl_qemu/src/arch/i386.rs @@ -1,14 +1,14 @@ use std::{mem::size_of, sync::OnceLock}; use capstone::arch::BuildsCapstone; -use enum_map::{enum_map, EnumMap}; +use enum_map::{EnumMap, enum_map}; use num_enum::{IntoPrimitive, TryFromPrimitive}; #[cfg(feature = "python")] use pyo3::prelude::*; pub use strum_macros::EnumIter; pub use syscall_numbers::x86::*; -use crate::{sync_exit::ExitArgs, CallingConvention, GuestAddr, QemuRWError, QemuRWErrorKind}; +use crate::{CallingConvention, GuestAddr, QemuRWError, QemuRWErrorKind, sync_exit::ExitArgs}; #[expect(non_upper_case_globals)] impl CallingConvention { diff --git a/libafl_qemu/src/arch/mips.rs b/libafl_qemu/src/arch/mips.rs index bcce7942d0..33722b2736 100644 --- a/libafl_qemu/src/arch/mips.rs +++ b/libafl_qemu/src/arch/mips.rs @@ -1,13 +1,13 @@ use std::sync::OnceLock; -use enum_map::{enum_map, EnumMap}; +use enum_map::{EnumMap, enum_map}; use num_enum::{IntoPrimitive, TryFromPrimitive}; #[cfg(feature = "python")] use pyo3::prelude::*; pub use strum_macros::EnumIter; pub use syscall_numbers::mips::*; -use crate::{sync_exit::ExitArgs, CallingConvention, QemuRWError, QemuRWErrorKind}; +use crate::{CallingConvention, QemuRWError, QemuRWErrorKind, sync_exit::ExitArgs}; #[expect(non_upper_case_globals)] impl CallingConvention { diff --git a/libafl_qemu/src/arch/ppc.rs b/libafl_qemu/src/arch/ppc.rs index a42f022680..aea5297574 100644 --- a/libafl_qemu/src/arch/ppc.rs +++ b/libafl_qemu/src/arch/ppc.rs @@ -1,13 +1,13 @@ use std::sync::OnceLock; -use enum_map::{enum_map, EnumMap}; +use enum_map::{EnumMap, enum_map}; use num_enum::{IntoPrimitive, TryFromPrimitive}; #[cfg(feature = "python")] use pyo3::prelude::*; pub use strum_macros::EnumIter; pub use syscall_numbers::powerpc::*; -use crate::{sync_exit::ExitArgs, CallingConvention, QemuRWError, QemuRWErrorKind}; +use crate::{CallingConvention, QemuRWError, QemuRWErrorKind, sync_exit::ExitArgs}; #[expect(non_upper_case_globals)] impl CallingConvention { diff --git a/libafl_qemu/src/arch/riscv.rs b/libafl_qemu/src/arch/riscv.rs index 79aef7c720..e191b52cfb 100644 --- a/libafl_qemu/src/arch/riscv.rs +++ b/libafl_qemu/src/arch/riscv.rs @@ -2,7 +2,7 @@ use core::ffi::c_long; use std::sync::OnceLock; use capstone::arch::BuildsCapstone; -use enum_map::{enum_map, EnumMap}; +use enum_map::{EnumMap, enum_map}; use num_enum::{IntoPrimitive, TryFromPrimitive}; #[cfg(feature = "python")] use pyo3::prelude::*; @@ -20,7 +20,7 @@ pub const SYS_riscv_flush_icache: c_long = SYS_arch_specific_syscall + 15; #[expect(non_upper_case_globals)] pub const SYS_riscv_hwprobe: c_long = SYS_arch_specific_syscall + 14; -use crate::{sync_exit::ExitArgs, CallingConvention, QemuRWError, QemuRWErrorKind}; +use crate::{CallingConvention, QemuRWError, QemuRWErrorKind, sync_exit::ExitArgs}; #[expect(non_upper_case_globals)] impl CallingConvention { diff --git a/libafl_qemu/src/arch/x86_64.rs b/libafl_qemu/src/arch/x86_64.rs index 19dc5bf952..36a7fff069 100644 --- a/libafl_qemu/src/arch/x86_64.rs +++ b/libafl_qemu/src/arch/x86_64.rs @@ -1,12 +1,12 @@ use std::{mem::size_of, sync::OnceLock}; use capstone::arch::BuildsCapstone; -use enum_map::{enum_map, EnumMap}; +use enum_map::{EnumMap, enum_map}; use num_enum::{IntoPrimitive, TryFromPrimitive}; pub use strum_macros::EnumIter; pub use syscall_numbers::x86_64::*; -use crate::{sync_exit::ExitArgs, CallingConvention, GuestAddr, QemuRWError, QemuRWErrorKind}; +use crate::{CallingConvention, GuestAddr, QemuRWError, QemuRWErrorKind, sync_exit::ExitArgs}; #[expect(non_upper_case_globals)] impl CallingConvention { diff --git a/libafl_qemu/src/breakpoint.rs b/libafl_qemu/src/breakpoint.rs index efdefb005a..0580ea25cb 100644 --- a/libafl_qemu/src/breakpoint.rs +++ b/libafl_qemu/src/breakpoint.rs @@ -3,8 +3,8 @@ use std::{ fmt::{Debug, Display, Formatter}, hash::{Hash, Hasher}, sync::{ - atomic::{AtomicU64, Ordering}, OnceLock, + atomic::{AtomicU64, Ordering}, }, }; diff --git a/libafl_qemu/src/command/mod.rs b/libafl_qemu/src/command/mod.rs index 7bb48268d4..e17ded0c40 100644 --- a/libafl_qemu/src/command/mod.rs +++ b/libafl_qemu/src/command/mod.rs @@ -16,6 +16,8 @@ use num_enum::TryFromPrimitive; use paste::paste; use crate::{ + CPU, Emulator, EmulatorDriverError, EmulatorDriverResult, GuestReg, InputLocation, + IsSnapshotManager, Qemu, QemuMemoryChunk, QemuRWError, Regs, StdEmulatorDriver, command::parser::{ EndCommandParser, InputPhysCommandParser, InputVirtCommandParser, LoadCommandParser, LqprintfCommandParser, NativeCommandParser, SaveCommandParser, StartPhysCommandParser, @@ -23,10 +25,8 @@ use crate::{ VersionCommandParser, }, get_exit_arch_regs, - modules::{utils::filters::HasAddressFilterTuples, EmulatorModuleTuple}, + modules::{EmulatorModuleTuple, utils::filters::HasAddressFilterTuples}, sync_exit::ExitArgs, - Emulator, EmulatorDriverError, EmulatorDriverResult, GuestReg, InputLocation, - IsSnapshotManager, Qemu, QemuMemoryChunk, QemuRWError, Regs, StdEmulatorDriver, CPU, }; #[cfg(all( @@ -37,15 +37,13 @@ pub mod nyx; pub mod parser; mod bindings { - #![allow(non_upper_case_globals)] - #![allow(non_camel_case_types)] - #![allow(non_snake_case)] - #![allow(improper_ctypes)] - #![allow(unused_mut)] - #![allow(unused)] - #![allow(unused_variables)] - #![allow(clippy::all)] - #![allow(clippy::pedantic)] + #![expect(non_upper_case_globals)] + #![expect(non_camel_case_types)] + #![expect(non_snake_case)] + #![expect(unused)] + #![expect(clippy::all)] + #![expect(clippy::pedantic)] + #![allow(unsafe_op_in_unsafe_fn)] include!(concat!(env!("OUT_DIR"), "/libafl_qemu_bindings.rs")); } diff --git a/libafl_qemu/src/command/nyx.rs b/libafl_qemu/src/command/nyx.rs index 8a0601105e..6b0260097f 100644 --- a/libafl_qemu/src/command/nyx.rs +++ b/libafl_qemu/src/command/nyx.rs @@ -22,32 +22,33 @@ use libc::c_uint; use paste::paste; use crate::{ + Emulator, EmulatorDriverError, EmulatorDriverResult, GuestReg, InputLocation, + IsSnapshotManager, NyxEmulatorDriver, Qemu, QemuMemoryChunk, Regs, command::{ + CommandError, CommandManager, IsCommand, NativeCommandParser, parser::nyx::{ AcquireCommandParser, GetHostConfigCommandParser, GetPayloadCommandParser, NextPayloadCommandParser, PanicCommandParser, PrintfCommandParser, RangeSubmitCommandParser, ReleaseCommandParser, SetAgentConfigCommandParser, SubmitCR3CommandParser, SubmitPanicCommandParser, UserAbortCommandParser, }, - CommandError, CommandManager, IsCommand, NativeCommandParser, }, get_exit_arch_regs, - modules::{utils::filters::HasAddressFilterTuples, EmulatorModuleTuple}, + modules::{EmulatorModuleTuple, utils::filters::HasAddressFilterTuples}, sync_exit::ExitArgs, - Emulator, EmulatorDriverError, EmulatorDriverResult, GuestReg, InputLocation, - IsSnapshotManager, NyxEmulatorDriver, Qemu, QemuMemoryChunk, Regs, }; pub(crate) mod bindings { - #![allow(non_upper_case_globals)] - #![allow(non_camel_case_types)] - #![allow(non_snake_case)] + #![expect(non_upper_case_globals)] + #![expect(non_camel_case_types)] + #![expect(non_snake_case)] #![allow(improper_ctypes)] #![allow(unused_mut)] - #![allow(unused)] + #![allow(unsafe_op_in_unsafe_fn)] + #![expect(unused)] #![allow(unused_variables)] - #![allow(clippy::all)] - #![allow(clippy::pedantic)] + #![expect(clippy::all)] + #![expect(clippy::pedantic)] include!(concat!(env!("OUT_DIR"), "/nyx_bindings.rs")); } @@ -428,8 +429,13 @@ where const EMPTY_RANGE: Range = 0..0; if self.allowed_range == EMPTY_RANGE { - log::warn!("The given range is {:#x?}, which is most likely invalid. It is most likely a guest error.", EMPTY_RANGE); - log::warn!("Hint: make sure the range is not getting optimized out (the volatile keyword may help you)."); + log::warn!( + "The given range is {:#x?}, which is most likely invalid. It is most likely a guest error.", + EMPTY_RANGE + ); + log::warn!( + "Hint: make sure the range is not getting optimized out (the volatile keyword may help you)." + ); } emu.modules_mut() diff --git a/libafl_qemu/src/command/parser/mod.rs b/libafl_qemu/src/command/parser/mod.rs index eb51c0cc9b..a7ac95f061 100644 --- a/libafl_qemu/src/command/parser/mod.rs +++ b/libafl_qemu/src/command/parser/mod.rs @@ -1,19 +1,19 @@ use std::{ffi::CStr, sync::OnceLock}; -use enum_map::{enum_map, EnumMap}; +use enum_map::{EnumMap, enum_map}; use libafl::{executors::ExitKind, inputs::HasTargetBytes}; use libafl_qemu_sys::{GuestAddr, GuestPhysAddr, GuestVirtAddr}; use libc::c_uint; use crate::{ - command::{ - bindings, AddressAllowCommand, CommandError, CommandManager, EndCommand, InputCommand, - IsCommand, LoadCommand, LqprintfCommand, NativeExitKind, SaveCommand, StartCommand, - StdCommandManager, TestCommand, VersionCommand, - }, - modules::{utils::filters::HasAddressFilterTuples, EmulatorModuleTuple}, - sync_exit::ExitArgs, GuestReg, IsSnapshotManager, Qemu, QemuMemoryChunk, Regs, StdEmulatorDriver, + command::{ + AddressAllowCommand, CommandError, CommandManager, EndCommand, InputCommand, IsCommand, + LoadCommand, LqprintfCommand, NativeExitKind, SaveCommand, StartCommand, StdCommandManager, + TestCommand, VersionCommand, bindings, + }, + modules::{EmulatorModuleTuple, utils::filters::HasAddressFilterTuples}, + sync_exit::ExitArgs, }; #[cfg(all( diff --git a/libafl_qemu/src/command/parser/nyx.rs b/libafl_qemu/src/command/parser/nyx.rs index b1bb773d73..423f2daec8 100644 --- a/libafl_qemu/src/command/parser/nyx.rs +++ b/libafl_qemu/src/command/parser/nyx.rs @@ -6,18 +6,19 @@ use libafl_qemu_sys::GuestVirtAddr; use libc::c_uint; use crate::{ + IsSnapshotManager, NyxEmulatorDriver, Qemu, QemuMemoryChunk, Regs, command::{ + CommandError, NativeExitKind, nyx::{ - bindings, AcquireCommand, GetHostConfigCommand, GetPayloadCommand, NextPayloadCommand, + AcquireCommand, GetHostConfigCommand, GetPayloadCommand, NextPayloadCommand, NyxCommandManager, PanicCommand, PrintfCommand, RangeSubmitCommand, ReleaseCommand, SetAgentConfigCommand, SubmitCR3Command, SubmitPanicCommand, UserAbortCommand, + bindings, }, parser::NativeCommandParser, - CommandError, NativeExitKind, }, - modules::{utils::filters::HasAddressFilterTuples, EmulatorModuleTuple}, + modules::{EmulatorModuleTuple, utils::filters::HasAddressFilterTuples}, sync_exit::ExitArgs, - IsSnapshotManager, NyxEmulatorDriver, Qemu, QemuMemoryChunk, Regs, }; fn get_guest_string(qemu: Qemu, string_ptr_reg: Regs) -> Result { diff --git a/libafl_qemu/src/elf.rs b/libafl_qemu/src/elf.rs index 40f0726941..fba390a0c6 100644 --- a/libafl_qemu/src/elf.rs +++ b/libafl_qemu/src/elf.rs @@ -2,7 +2,7 @@ use std::{fs::File, io::Read, ops::Range, path::Path, str}; -use goblin::elf::{header::ET_DYN, Elf}; +use goblin::elf::{Elf, header::ET_DYN}; use libafl::Error; use libafl_qemu_sys::GuestAddr; diff --git a/libafl_qemu/src/emu/builder.rs b/libafl_qemu/src/emu/builder.rs index 43541b6904..8e993cd1e6 100644 --- a/libafl_qemu/src/emu/builder.rs +++ b/libafl_qemu/src/emu/builder.rs @@ -1,19 +1,19 @@ use std::marker::PhantomData; use libafl::{inputs::HasTargetBytes, state::HasExecutions}; -use libafl_bolts::tuples::{tuple_list, Append, Prepend}; +use libafl_bolts::tuples::{Append, Prepend, tuple_list}; #[cfg(feature = "systemmode")] use crate::FastSnapshotManager; use crate::{ + Emulator, NopEmulatorDriver, NopSnapshotManager, QemuInitError, QemuParams, StdEmulatorDriver, + StdSnapshotManager, command::{NopCommandManager, StdCommandManager}, config::QemuConfigBuilder, modules::{EmulatorModule, EmulatorModuleTuple}, - Emulator, NopEmulatorDriver, NopSnapshotManager, QemuInitError, QemuParams, StdEmulatorDriver, - StdSnapshotManager, }; #[cfg(doc)] -use crate::{config::QemuConfig, Qemu}; +use crate::{Qemu, config::QemuConfig}; /// An [`Emulator`] Builder. /// diff --git a/libafl_qemu/src/emu/drivers/mod.rs b/libafl_qemu/src/emu/drivers/mod.rs index 0b61094a3b..7f92f6dab2 100644 --- a/libafl_qemu/src/emu/drivers/mod.rs +++ b/libafl_qemu/src/emu/drivers/mod.rs @@ -4,14 +4,14 @@ use std::{cell::OnceCell, fmt::Debug}; use libafl::{executors::ExitKind, inputs::HasTargetBytes, observers::ObserversTuple}; -use libafl_bolts::os::{unix_signals::Signal, CTRL_C_EXIT}; +use libafl_bolts::os::{CTRL_C_EXIT, unix_signals::Signal}; use typed_builder::TypedBuilder; use crate::{ - command::{CommandError, CommandManager, InputCommand, IsCommand}, - modules::EmulatorModuleTuple, Emulator, EmulatorExitError, EmulatorExitResult, InputLocation, IsSnapshotManager, QemuError, QemuShutdownCause, Regs, SnapshotId, SnapshotManagerCheckError, SnapshotManagerError, + command::{CommandError, CommandManager, InputCommand, IsCommand}, + modules::EmulatorModuleTuple, }; #[cfg(all( @@ -257,7 +257,7 @@ where return Err(EmulatorDriverError::UnhandledSignal(*signal)); } QemuShutdownCause::GuestPanic => { - return Ok(Some(EmulatorDriverResult::EndOfRun(ExitKind::Crash))) + return Ok(Some(EmulatorDriverResult::EndOfRun(ExitKind::Crash))); } QemuShutdownCause::GuestShutdown | QemuShutdownCause::HostQmpQuit => { log::warn!("Guest shutdown. Stopping fuzzing..."); @@ -266,7 +266,7 @@ where _ => panic!("Unhandled QEMU shutdown cause: {shutdown_cause:?}."), }, EmulatorExitResult::Timeout => { - return Ok(Some(EmulatorDriverResult::EndOfRun(ExitKind::Timeout))) + return Ok(Some(EmulatorDriverResult::EndOfRun(ExitKind::Timeout))); } EmulatorExitResult::Breakpoint(bp) => (bp.trigger(qemu), None), EmulatorExitResult::CustomInsn(custom_insn) => { diff --git a/libafl_qemu/src/emu/drivers/nyx.rs b/libafl_qemu/src/emu/drivers/nyx.rs index 07e658d82c..89a17ec211 100644 --- a/libafl_qemu/src/emu/drivers/nyx.rs +++ b/libafl_qemu/src/emu/drivers/nyx.rs @@ -5,11 +5,11 @@ use libafl_bolts::os::CTRL_C_EXIT; use typed_builder::TypedBuilder; use crate::{ - command::{nyx::bindings, CommandManager, IsCommand}, - modules::EmulatorModuleTuple, Emulator, EmulatorDriver, EmulatorDriverError, EmulatorDriverResult, EmulatorExitError, EmulatorExitResult, InputLocation, IsSnapshotManager, Qemu, QemuError, QemuShutdownCause, Regs, SnapshotId, + command::{CommandManager, IsCommand, nyx::bindings}, + modules::EmulatorModuleTuple, }; #[derive(Clone, Debug, TypedBuilder)] @@ -180,7 +180,7 @@ where return Err(EmulatorDriverError::UnhandledSignal(*signal)); } QemuShutdownCause::GuestPanic => { - return Ok(Some(EmulatorDriverResult::EndOfRun(ExitKind::Crash))) + return Ok(Some(EmulatorDriverResult::EndOfRun(ExitKind::Crash))); } QemuShutdownCause::GuestShutdown | QemuShutdownCause::HostQmpQuit => { log::warn!("Guest shutdown. Stopping fuzzing..."); @@ -189,7 +189,7 @@ where _ => panic!("Unhandled QEMU shutdown cause: {shutdown_cause:?}."), }, EmulatorExitResult::Timeout => { - return Ok(Some(EmulatorDriverResult::EndOfRun(ExitKind::Timeout))) + return Ok(Some(EmulatorDriverResult::EndOfRun(ExitKind::Timeout))); } EmulatorExitResult::Breakpoint(bp) => (bp.trigger(qemu), None), EmulatorExitResult::CustomInsn(sync_backdoor) => { diff --git a/libafl_qemu/src/emu/hooks.rs b/libafl_qemu/src/emu/hooks.rs index 1c3a0dd2b1..5d2eb85723 100644 --- a/libafl_qemu/src/emu/hooks.rs +++ b/libafl_qemu/src/emu/hooks.rs @@ -5,21 +5,28 @@ use std::{fmt::Debug, marker::PhantomData, mem::transmute, pin::Pin, ptr}; use libafl::{executors::ExitKind, observers::ObserversTuple}; use libafl_qemu_sys::{CPUStatePtr, FatPtr, GuestAddr, GuestUsize, TCGTemp}; -#[cfg(feature = "usermode")] -use crate::qemu::{ - closure_post_syscall_hook_wrapper, closure_pre_syscall_hook_wrapper, - func_post_syscall_hook_wrapper, func_pre_syscall_hook_wrapper, PostSyscallHook, - PostSyscallHookId, PreSyscallHook, PreSyscallHookId, -}; #[cfg(feature = "usermode")] use crate::qemu::{ CrashHookClosure, CrashHookFn, PostSyscallHookClosure, PostSyscallHookFn, PreSyscallHookClosure, PreSyscallHookFn, }; +#[cfg(feature = "usermode")] +use crate::qemu::{ + PostSyscallHook, PostSyscallHookId, PreSyscallHook, PreSyscallHookId, + closure_post_syscall_hook_wrapper, closure_pre_syscall_hook_wrapper, + func_post_syscall_hook_wrapper, func_pre_syscall_hook_wrapper, +}; use crate::{ + CpuPostRunHook, CpuPreRunHook, CpuRunHookId, HookState, MemAccessInfo, NewThreadHookFn, Qemu, cpu_run_post_exec_hook_wrapper, cpu_run_pre_exec_hook_wrapper, modules::{EmulatorModule, EmulatorModuleTuple}, qemu::{ + BackdoorHook, BackdoorHookClosure, BackdoorHookFn, BackdoorHookId, BlockExecHook, + BlockGenHook, BlockHookId, BlockPostGenHook, CmpExecHook, CmpGenHook, CmpHookId, + EdgeExecHook, EdgeGenHook, EdgeHookId, Hook, HookRepr, InstructionHook, + InstructionHookClosure, InstructionHookFn, InstructionHookId, NewThreadHook, + NewThreadHookClosure, NewThreadHookId, QemuHooks, ReadExecHook, ReadExecNHook, ReadGenHook, + ReadHookId, TcgHookState, WriteExecHook, WriteExecNHook, WriteGenHook, WriteHookId, block_0_exec_hook_wrapper, block_gen_hook_wrapper, block_post_gen_hook_wrapper, closure_backdoor_hook_wrapper, closure_instruction_hook_wrapper, closure_new_thread_hook_wrapper, cmp_0_exec_hook_wrapper, cmp_1_exec_hook_wrapper, @@ -29,15 +36,8 @@ use crate::{ read_1_exec_hook_wrapper, read_2_exec_hook_wrapper, read_3_exec_hook_wrapper, read_4_exec_hook_wrapper, read_gen_hook_wrapper, write_0_exec_hook_wrapper, write_1_exec_hook_wrapper, write_2_exec_hook_wrapper, write_3_exec_hook_wrapper, - write_4_exec_hook_wrapper, write_gen_hook_wrapper, BackdoorHook, BackdoorHookClosure, - BackdoorHookFn, BackdoorHookId, BlockExecHook, BlockGenHook, BlockHookId, BlockPostGenHook, - CmpExecHook, CmpGenHook, CmpHookId, EdgeExecHook, EdgeGenHook, EdgeHookId, Hook, HookRepr, - InstructionHook, InstructionHookClosure, InstructionHookFn, InstructionHookId, - NewThreadHook, NewThreadHookClosure, NewThreadHookId, QemuHooks, ReadExecHook, - ReadExecNHook, ReadGenHook, ReadHookId, TcgHookState, WriteExecHook, WriteExecNHook, - WriteGenHook, WriteHookId, + write_4_exec_hook_wrapper, write_gen_hook_wrapper, }, - CpuPostRunHook, CpuPreRunHook, CpuRunHookId, HookState, MemAccessInfo, NewThreadHookFn, Qemu, }; /// Get a C-compatible function pointer from the input hook. @@ -269,7 +269,7 @@ where execution_hook: EdgeExecHook, ) -> EdgeHookId { unsafe { - let gen = get_raw_hook!( + let generator = get_raw_hook!( generation_hook, edge_gen_hook_wrapper::, unsafe extern "C" fn( @@ -303,7 +303,7 @@ where .get_unchecked_mut(), ); - let id = self.qemu_hooks.add_edge_hooks(hook_state, gen, exec); + let id = self.qemu_hooks.add_edge_hooks(hook_state, generator, exec); self.hook_collection .edge_hooks @@ -324,7 +324,7 @@ where execution_hook: BlockExecHook, ) -> BlockHookId { unsafe { - let gen = get_raw_hook!( + let generator = get_raw_hook!( generation_hook, block_gen_hook_wrapper::, unsafe extern "C" fn(&mut TcgHookState<1, BlockHookId>, pc: GuestAddr) -> u64 @@ -366,7 +366,7 @@ where let id = self .qemu_hooks - .add_block_hooks(hook_state, gen, postgen, exec); + .add_block_hooks(hook_state, generator, postgen, exec); self.hook_collection .block_hooks @@ -442,7 +442,7 @@ where execution_hook_n: ReadExecNHook, ) -> ReadHookId { unsafe { - let gen = get_raw_hook!( + let generator = get_raw_hook!( generation_hook, read_gen_hook_wrapper::, unsafe extern "C" fn( @@ -530,7 +530,7 @@ where let id = self .qemu_hooks - .add_read_hooks(hook_state, gen, exec1, exec2, exec4, exec8, execn); + .add_read_hooks(hook_state, generator, exec1, exec2, exec4, exec8, execn); self.hook_collection .read_hooks @@ -555,7 +555,7 @@ where execution_hook_n: WriteExecNHook, ) -> WriteHookId { unsafe { - let gen = get_raw_hook!( + let generator = get_raw_hook!( generation_hook, write_gen_hook_wrapper::, unsafe extern "C" fn( @@ -643,7 +643,7 @@ where let id = self .qemu_hooks - .add_write_hooks(hook_state, gen, exec1, exec2, exec4, exec8, execn); + .add_write_hooks(hook_state, generator, exec1, exec2, exec4, exec8, execn); self.hook_collection .write_hooks @@ -666,7 +666,7 @@ where execution_hook_8: CmpExecHook, ) -> CmpHookId { unsafe { - let gen = get_raw_hook!( + let generator = get_raw_hook!( generation_hook, cmp_gen_hook_wrapper::, unsafe extern "C" fn( @@ -721,7 +721,7 @@ where let id = self .qemu_hooks - .add_cmp_hooks(hook_state, gen, exec1, exec2, exec4, exec8); + .add_cmp_hooks(hook_state, generator, exec1, exec2, exec4, exec8); self.hook_collection .cmp_hooks @@ -780,11 +780,11 @@ where } /// # Safety - /// This can call through to a potentialy unsafe `backtoor_function` + /// This can call through to a potentialy unsafe [`backdoor_function`] pub unsafe fn backdoor(&mut self, hook: BackdoorHook) -> Option { match hook { Hook::Function(f) => Some(self.backdoor_function(f)), - Hook::Closure(c) => Some(self.backdoor_closure(c)), + Hook::Closure(c) => Some(unsafe { self.backdoor_closure(c) }), Hook::Raw(r) => { let z: *const () = ptr::null::<()>(); Some(self.qemu_hooks.add_backdoor_hook(z, r)) @@ -1002,14 +1002,14 @@ impl EmulatorModules { #[must_use] pub unsafe fn emulator_modules_mut_unchecked<'a>() -> &'a mut EmulatorModules { #[cfg(debug_assertions)] - { + unsafe { (EMULATOR_MODULES as *mut EmulatorModules) .as_mut() .unwrap() } #[cfg(not(debug_assertions))] - { + unsafe { &mut *(EMULATOR_MODULES as *mut EmulatorModules) } } @@ -1142,7 +1142,7 @@ where /// # Safety /// This will potentially call an unsafe backdoor hook pub unsafe fn backdoor(&mut self, hook: BackdoorHook) -> Option { - self.hooks.backdoor(hook) + unsafe { self.hooks.backdoor(hook) } } pub fn backdoor_function(&mut self, hook: BackdoorHookFn) -> BackdoorHookId { @@ -1155,7 +1155,7 @@ where &mut self, hook: BackdoorHookClosure, ) -> BackdoorHookId { - self.hooks.backdoor_closure(hook) + unsafe { self.hooks.backdoor_closure(hook) } } pub fn thread_creation(&mut self, hook: NewThreadHook) -> Option { @@ -1204,7 +1204,9 @@ where if EMULATOR_MODULES.is_null() { EMULATOR_MODULES = ptr::from_mut::(modules.as_mut().get_mut()) as *mut (); } else { - panic!("Emulator Modules have already been set and is still active. It is not supported to have multiple instances of `EmulatorModules` at the same time yet.") + panic!( + "Emulator Modules have already been set and is still active. It is not supported to have multiple instances of `EmulatorModules` at the same time yet." + ) } } diff --git a/libafl_qemu/src/emu/mod.rs b/libafl_qemu/src/emu/mod.rs index afe846cd20..b07c5e5759 100644 --- a/libafl_qemu/src/emu/mod.rs +++ b/libafl_qemu/src/emu/mod.rs @@ -14,12 +14,12 @@ use libafl_qemu_sys::{GuestAddr, GuestPhysAddr, GuestUsize, GuestVirtAddr}; #[cfg(doc)] use crate::modules::EmulatorModule; use crate::{ + CPU, Qemu, QemuExitError, QemuExitReason, QemuHooks, QemuInitError, QemuMemoryChunk, + QemuParams, QemuShutdownCause, Regs, breakpoint::{Breakpoint, BreakpointId}, command::{CommandError, CommandManager, NopCommandManager, StdCommandManager}, modules::EmulatorModuleTuple, sync_exit::CustomInsn, - Qemu, QemuExitError, QemuExitReason, QemuHooks, QemuInitError, QemuMemoryChunk, QemuParams, - QemuShutdownCause, Regs, CPU, }; mod hooks; @@ -431,7 +431,7 @@ where // Run QEMU log::debug!("Running QEMU..."); - let mut exit_reason = self.run_qemu(); + let mut exit_reason = unsafe { self.run_qemu() }; log::debug!("QEMU stopped."); // Handle QEMU exit @@ -444,12 +444,13 @@ where } /// This function will run the emulator until the next breakpoint, or until finish. + /// /// # Safety /// /// Should, in general, be safe to call. /// Of course, the emulated target is not contained securely and can corrupt state or interact with the operating system. pub unsafe fn run_qemu(&self) -> Result, EmulatorExitError> { - match self.qemu.run() { + match unsafe { self.qemu.run() } { Ok(qemu_exit_reason) => Ok(match qemu_exit_reason { QemuExitReason::End(qemu_shutdown_cause) => { EmulatorExitResult::QemuExit(qemu_shutdown_cause) diff --git a/libafl_qemu/src/emu/snapshot.rs b/libafl_qemu/src/emu/snapshot.rs index 4ea4fa109a..6c18bc5fef 100644 --- a/libafl_qemu/src/emu/snapshot.rs +++ b/libafl_qemu/src/emu/snapshot.rs @@ -10,7 +10,7 @@ pub trait IsSnapshotManager: Clone + Debug { fn save(&mut self, qemu: Qemu) -> SnapshotId; fn restore(&mut self, qemu: Qemu, snapshot_id: &SnapshotId) - -> Result<(), SnapshotManagerError>; + -> Result<(), SnapshotManagerError>; fn do_check( &self, qemu: Qemu, diff --git a/libafl_qemu/src/emu/systemmode.rs b/libafl_qemu/src/emu/systemmode.rs index f282ef324d..53ba53a4a7 100644 --- a/libafl_qemu/src/emu/systemmode.rs +++ b/libafl_qemu/src/emu/systemmode.rs @@ -4,8 +4,8 @@ use hashbrown::HashMap; use libafl_qemu_sys::GuestPhysAddr; use crate::{ - emu::{IsSnapshotManager, QemuSnapshotCheckResult}, DeviceSnapshotFilter, Emulator, Qemu, SnapshotId, SnapshotManagerError, + emu::{IsSnapshotManager, QemuSnapshotCheckResult}, }; #[derive(Debug, Clone)] @@ -168,13 +168,17 @@ impl Emulator { /// Write a value to a phsical guest address, including ROM areas. #[allow(clippy::missing_safety_doc)] pub unsafe fn write_phys_mem(&self, paddr: GuestPhysAddr, buf: &[u8]) { - self.qemu.write_phys_mem(paddr, buf); + unsafe { + self.qemu.write_phys_mem(paddr, buf); + } } /// Read a value from a physical guest address. #[allow(clippy::missing_safety_doc)] pub unsafe fn read_phys_mem(&self, paddr: GuestPhysAddr, buf: &mut [u8]) { - self.qemu.read_phys_mem(paddr, buf); + unsafe { + self.qemu.read_phys_mem(paddr, buf); + } } pub fn save_snapshot(&self, name: &str, sync: bool) { @@ -201,7 +205,9 @@ impl Emulator { #[allow(clippy::missing_safety_doc)] pub unsafe fn restore_fast_snapshot(&self, snapshot: FastSnapshotPtr) { - self.qemu.restore_fast_snapshot(snapshot); + unsafe { + self.qemu.restore_fast_snapshot(snapshot); + } } pub fn list_devices(&self) -> Vec { diff --git a/libafl_qemu/src/executor.rs b/libafl_qemu/src/executor.rs index a1e86f6049..57b7e82c3b 100644 --- a/libafl_qemu/src/executor.rs +++ b/libafl_qemu/src/executor.rs @@ -12,35 +12,35 @@ use std::{ptr, str}; #[cfg(feature = "usermode")] use libafl::state::HasCorpus; use libafl::{ + Error, ExecutionProcessor, HasScheduler, events::{EventFirer, EventRestarter}, executors::{ - hooks::inprocess::{InProcessExecutorHandlerData, GLOBAL_STATE}, - inprocess::{stateful::StatefulInProcessExecutor, HasInProcessHooks}, - inprocess_fork::stateful::StatefulInProcessForkExecutor, Executor, ExitKind, HasObservers, + hooks::inprocess::{GLOBAL_STATE, InProcessExecutorHandlerData}, + inprocess::{HasInProcessHooks, stateful::StatefulInProcessExecutor}, + inprocess_fork::stateful::StatefulInProcessForkExecutor, }, feedbacks::Feedback, fuzzer::HasObjective, inputs::Input, observers::ObserversTuple, state::{HasCurrentTestcase, HasExecutions, HasSolutions}, - Error, ExecutionProcessor, HasScheduler, }; #[cfg(feature = "usermode")] use libafl_bolts::minibsod; #[cfg(feature = "fork")] use libafl_bolts::shmem::ShMemProvider; use libafl_bolts::{ - os::unix_signals::{ucontext_t, Signal}, + os::unix_signals::{Signal, ucontext_t}, tuples::RefIndexable, }; #[cfg(feature = "systemmode")] use libafl_qemu_sys::libafl_exit_request_timeout; use libc::siginfo_t; -use crate::{command::CommandManager, modules::EmulatorModuleTuple, Emulator, EmulatorDriver}; +use crate::{Emulator, EmulatorDriver, command::CommandManager, modules::EmulatorModuleTuple}; #[cfg(feature = "usermode")] -use crate::{run_target_crash_hooks, EmulatorModules, Qemu, QemuSignalContext}; +use crate::{EmulatorModules, Qemu, QemuSignalContext, run_target_crash_hooks}; type EmulatorInProcessExecutor<'a, C, CM, ED, EM, ET, H, I, OT, S, SM, Z> = StatefulInProcessExecutor<'a, EM, Emulator, H, I, OT, S, Z>; @@ -95,7 +95,9 @@ pub unsafe fn inproc_qemu_crash_handler( // we did not run QEMU's signal handler, run it not log::debug!("It's a simple signal, let QEMU handle it first"); - qemu.run_signal_handler(signal.into(), info, puc); + unsafe { + qemu.run_signal_handler(signal.into(), info, puc); + } // if we are there, we can safely to execution return; @@ -104,8 +106,10 @@ pub unsafe fn inproc_qemu_crash_handler( // we are running in a nested signal handling // and the signal is a host QEMU signal - let si_addr = { info.si_addr() as usize }; - log::error!("QEMU Host crash crashed at addr 0x{si_addr:x}... Bug in QEMU or Emulator modules? Exiting.\n"); + let si_addr = unsafe { info.si_addr() as usize }; + log::error!( + "QEMU Host crash crashed at addr 0x{si_addr:x}... Bug in QEMU or Emulator modules? Exiting.\n" + ); if let Some(cpu) = qemu.current_cpu() { eprint!("QEMU Context:\n{}", cpu.display_context()); @@ -115,12 +119,14 @@ pub unsafe fn inproc_qemu_crash_handler( // we are running in a nested signal handler and the signal is a target signal. // run qemu hooks then report the crash. - log::debug!("QEMU Target signal received that should be handled by host. Most likely a target crash."); + log::debug!( + "QEMU Target signal received that should be handled by host. Most likely a target crash." + ); log::debug!("Running crash hooks."); run_target_crash_hooks::(signal.into()); - assert!(data.maybe_report_crash::(None)); + assert!(unsafe { data.maybe_report_crash::(None) }); if let Some(cpu) = qemu.current_cpu() { eprint!("QEMU Context:\n{}", cpu.display_context()); @@ -129,7 +135,7 @@ pub unsafe fn inproc_qemu_crash_handler( } } else { // qemu is not running, it is a bug in LibAFL - let si_addr = { info.si_addr() as usize }; + let si_addr = unsafe { info.si_addr() as usize }; log::error!("The fuzzer crashed at addr 0x{si_addr:x}... Bug in the fuzzer? Exiting."); let bsod = minibsod::generate_minibsod_to_vec(signal, info, context.as_deref()); @@ -146,7 +152,9 @@ pub unsafe fn inproc_qemu_crash_handler( } } - libc::_exit(128 + (signal as i32)); + unsafe { + libc::_exit(128 + (signal as i32)); + } } #[cfg(feature = "systemmode")] @@ -172,7 +180,7 @@ pub unsafe fn inproc_qemu_timeout_handler( Z: HasObjective, { #[cfg(feature = "systemmode")] - { + unsafe { if BREAK_ON_TMOUT.load(Ordering::Acquire) { libafl_exit_request_timeout(); } else { @@ -188,7 +196,7 @@ pub unsafe fn inproc_qemu_timeout_handler( } #[cfg(feature = "usermode")] - { + unsafe { // run modules' crash callback if let Some(emulator_modules) = EmulatorModules::::emulator_modules_mut() { emulator_modules.modules_mut().on_timeout_all(); @@ -413,7 +421,10 @@ where shmem_provider: SP, timeout: Duration, ) -> Result { - assert!(!ET::HOOKS_DO_SIDE_EFFECTS, "When using QemuForkExecutor, the hooks must not do any side effect as they will happen in the child process and then discarded"); + assert!( + !ET::HOOKS_DO_SIDE_EFFECTS, + "When using QemuForkExecutor, the hooks must not do any side effect as they will happen in the child process and then discarded" + ); Ok(Self { inner: StatefulInProcessForkExecutor::new( diff --git a/libafl_qemu/src/modules/calls.rs b/libafl_qemu/src/modules/calls.rs index 98e2b85dd6..ac288a41d3 100644 --- a/libafl_qemu/src/modules/calls.rs +++ b/libafl_qemu/src/modules/calls.rs @@ -4,7 +4,7 @@ use capstone::prelude::*; use libafl::{ executors::ExitKind, inputs::Input, - observers::{stacktrace::BacktraceObserver, ObserversTuple}, + observers::{ObserversTuple, stacktrace::BacktraceObserver}, }; use libafl_bolts::tuples::{Handle, Handled, MatchFirstType, MatchNameRef}; use libafl_qemu_sys::GuestAddr; @@ -12,15 +12,14 @@ use thread_local::ThreadLocal; use super::utils::filters::HasAddressFilter; #[cfg(feature = "systemmode")] -use crate::modules::utils::filters::{NopPageFilter, NOP_PAGE_FILTER}; +use crate::modules::utils::filters::{NOP_PAGE_FILTER, NopPageFilter}; use crate::{ - capstone, + Qemu, capstone, modules::{ - utils::filters::StdAddressFilter, AddressFilter, EmulatorModule, EmulatorModuleTuple, - EmulatorModules, + AddressFilter, EmulatorModule, EmulatorModuleTuple, EmulatorModules, + utils::filters::StdAddressFilter, }, qemu::{ArchExtras, Hook}, - Qemu, }; pub trait CallTraceCollector: 'static { diff --git a/libafl_qemu/src/modules/cmplog.rs b/libafl_qemu/src/modules/cmplog.rs index 09bd83c626..d73ca697f5 100644 --- a/libafl_qemu/src/modules/cmplog.rs +++ b/libafl_qemu/src/modules/cmplog.rs @@ -1,29 +1,29 @@ #[cfg(feature = "usermode")] -use capstone::{arch::BuildsCapstone, Capstone, InsnDetail}; +use capstone::{Capstone, InsnDetail, arch::BuildsCapstone}; use hashbrown::HashMap; use libafl::HasMetadata; use libafl_bolts::hash_64_fast; use libafl_qemu_sys::GuestAddr; pub use libafl_targets::{ + CMPLOG_MAP_H, CMPLOG_MAP_PTR, CMPLOG_MAP_SIZE, CMPLOG_MAP_W, CmpLogMap, CmpLogObserver, cmps::{ __libafl_targets_cmplog_instructions, __libafl_targets_cmplog_routines, CMPLOG_ENABLED, }, - CmpLogMap, CmpLogObserver, CMPLOG_MAP_H, CMPLOG_MAP_PTR, CMPLOG_MAP_SIZE, CMPLOG_MAP_W, }; use serde::{Deserialize, Serialize}; #[cfg(feature = "usermode")] use crate::capstone; #[cfg(feature = "systemmode")] -use crate::modules::utils::filters::{NopPageFilter, NOP_PAGE_FILTER}; +use crate::modules::utils::filters::{NOP_PAGE_FILTER, NopPageFilter}; use crate::{ + Qemu, emu::EmulatorModules, modules::{ - utils::filters::{HasAddressFilter, StdAddressFilter}, AddressFilter, EmulatorModule, EmulatorModuleTuple, + utils::filters::{HasAddressFilter, StdAddressFilter}, }, qemu::Hook, - Qemu, }; #[cfg_attr( diff --git a/libafl_qemu/src/modules/drcov.rs b/libafl_qemu/src/modules/drcov.rs index 83f488e65f..492846a61a 100644 --- a/libafl_qemu/src/modules/drcov.rs +++ b/libafl_qemu/src/modules/drcov.rs @@ -5,8 +5,8 @@ use std::{ }; use std::{path::PathBuf, sync::Mutex}; -use hashbrown::{hash_map::Entry, HashMap}; -use libafl::{executors::ExitKind, observers::ObserversTuple, HasMetadata}; +use hashbrown::{HashMap, hash_map::Entry}; +use libafl::{HasMetadata, executors::ExitKind, observers::ObserversTuple}; use libafl_qemu_sys::{GuestAddr, GuestUsize}; use libafl_targets::drcov::{DrCovBasicBlock, DrCovWriter}; use rangemap::RangeMap; @@ -14,14 +14,14 @@ use serde::{Deserialize, Serialize}; use super::utils::filters::HasAddressFilter; #[cfg(feature = "systemmode")] -use crate::modules::utils::filters::{NopPageFilter, NOP_PAGE_FILTER}; +use crate::modules::utils::filters::{NOP_PAGE_FILTER, NopPageFilter}; use crate::{ + Qemu, emu::EmulatorModules, modules::{ - utils::filters::NopAddressFilter, AddressFilter, EmulatorModule, EmulatorModuleTuple, + AddressFilter, EmulatorModule, EmulatorModuleTuple, utils::filters::NopAddressFilter, }, qemu::Hook, - Qemu, }; /// Trace of `block_id`s met at runtime diff --git a/libafl_qemu/src/modules/edges/child.rs b/libafl_qemu/src/modules/edges/child.rs index 0f9bcbc5f4..d011840cf2 100644 --- a/libafl_qemu/src/modules/edges/child.rs +++ b/libafl_qemu/src/modules/edges/child.rs @@ -1,16 +1,16 @@ use libafl::HasMetadata; use super::{ - helpers::{gen_hashed_edge_ids, trace_edge_hitcount_ptr, trace_edge_single_ptr}, EdgeCoverageVariant, + helpers::{gen_hashed_edge_ids, trace_edge_hitcount_ptr, trace_edge_single_ptr}, }; use crate::{ + EmulatorModules, Hook, modules::{ - utils::filters::{StdAddressFilter, StdPageFilter}, AddressFilter, EdgeCoverageModule, EdgeCoverageModuleBuilder, EmulatorModuleTuple, PageFilter, + utils::filters::{StdAddressFilter, StdPageFilter}, }, - EmulatorModules, Hook, }; #[derive(Debug)] diff --git a/libafl_qemu/src/modules/edges/classic.rs b/libafl_qemu/src/modules/edges/classic.rs index 7a75c11eff..8217713d50 100644 --- a/libafl_qemu/src/modules/edges/classic.rs +++ b/libafl_qemu/src/modules/edges/classic.rs @@ -1,18 +1,18 @@ use libafl::HasMetadata; use super::{ + EdgeCoverageVariant, helpers::{ gen_hashed_block_ids, trace_block_transition_hitcount, trace_block_transition_single, }, - EdgeCoverageVariant, }; use crate::{ + EmulatorModules, Hook, modules::{ - utils::filters::{StdAddressFilter, StdPageFilter}, AddressFilter, EdgeCoverageModule, EdgeCoverageModuleBuilder, EmulatorModuleTuple, PageFilter, + utils::filters::{StdAddressFilter, StdPageFilter}, }, - EmulatorModules, Hook, }; #[derive(Debug)] diff --git a/libafl_qemu/src/modules/edges/full.rs b/libafl_qemu/src/modules/edges/full.rs index 9dcb368afc..548fe6055e 100644 --- a/libafl_qemu/src/modules/edges/full.rs +++ b/libafl_qemu/src/modules/edges/full.rs @@ -1,16 +1,16 @@ use libafl::HasMetadata; use super::{ - helpers::{gen_unique_edge_ids, trace_edge_hitcount, trace_edge_single}, EdgeCoverageVariant, + helpers::{gen_unique_edge_ids, trace_edge_hitcount, trace_edge_single}, }; use crate::{ + EmulatorModules, Hook, modules::{ - utils::filters::{StdAddressFilter, StdPageFilter}, AddressFilter, EdgeCoverageModule, EdgeCoverageModuleBuilder, EmulatorModuleTuple, PageFilter, + utils::filters::{StdAddressFilter, StdPageFilter}, }, - EmulatorModules, Hook, }; #[derive(Debug)] diff --git a/libafl_qemu/src/modules/edges/helpers.rs b/libafl_qemu/src/modules/edges/helpers.rs index e095d69c7d..f82a70259e 100644 --- a/libafl_qemu/src/modules/edges/helpers.rs +++ b/libafl_qemu/src/modules/edges/helpers.rs @@ -13,16 +13,16 @@ pub use tracers::{ // Constants used for variable-length maps -#[no_mangle] +#[unsafe(no_mangle)] pub(super) static mut LIBAFL_QEMU_EDGES_MAP_PTR: *mut u8 = ptr::null_mut(); -#[no_mangle] +#[unsafe(no_mangle)] pub(super) static mut LIBAFL_QEMU_EDGES_MAP_SIZE_PTR: *mut usize = ptr::null_mut(); -#[no_mangle] +#[unsafe(no_mangle)] pub(super) static mut LIBAFL_QEMU_EDGES_MAP_ALLOCATED_SIZE: usize = 0; -#[no_mangle] +#[unsafe(no_mangle)] pub(super) static mut LIBAFL_QEMU_EDGES_MAP_MASK_MAX: usize = 0; #[cfg_attr( @@ -56,12 +56,12 @@ mod generators { use libafl_qemu_sys::GuestAddr; use super::{ - super::EdgeCoverageVariant, QemuEdgesMapMetadata, LIBAFL_QEMU_EDGES_MAP_MASK_MAX, - LIBAFL_QEMU_EDGES_MAP_SIZE_PTR, + super::EdgeCoverageVariant, LIBAFL_QEMU_EDGES_MAP_MASK_MAX, LIBAFL_QEMU_EDGES_MAP_SIZE_PTR, + QemuEdgesMapMetadata, }; use crate::{ - modules::{AddressFilter, EdgeCoverageModule, EmulatorModuleTuple, PageFilter}, EmulatorModules, Qemu, + modules::{AddressFilter, EdgeCoverageModule, EmulatorModuleTuple, PageFilter}, }; fn get_mask() -> usize { diff --git a/libafl_qemu/src/modules/edges/mod.rs b/libafl_qemu/src/modules/edges/mod.rs index baa8441c7c..dbd28e7361 100644 --- a/libafl_qemu/src/modules/edges/mod.rs +++ b/libafl_qemu/src/modules/edges/mod.rs @@ -1,15 +1,15 @@ use std::fmt::Debug; -use libafl::{observers::VarLenMapObserver, HasMetadata}; +use libafl::{HasMetadata, observers::VarLenMapObserver}; use libafl_bolts::Error; use libafl_qemu_sys::GuestAddr; #[cfg(feature = "systemmode")] use libafl_qemu_sys::GuestPhysAddr; use crate::{ + Qemu, emu::EmulatorModules, modules::{AddressFilter, EmulatorModule, EmulatorModuleTuple, PageFilter}, - Qemu, }; mod helpers; @@ -396,7 +396,7 @@ mod tests { use libafl::observers::{CanTrack, HitcountsMapObserver, VariableMapObserver}; use libafl_bolts::ownedref::OwnedMutSlice; - use libafl_targets::{edges_map_mut_ptr, EDGES_MAP_DEFAULT_SIZE, MAX_EDGES_FOUND}; + use libafl_targets::{EDGES_MAP_DEFAULT_SIZE, MAX_EDGES_FOUND, edges_map_mut_ptr}; use crate::modules::StdEdgeCoverageModule; diff --git a/libafl_qemu/src/modules/logger.rs b/libafl_qemu/src/modules/logger.rs index 195dfd98c2..a10f779a16 100644 --- a/libafl_qemu/src/modules/logger.rs +++ b/libafl_qemu/src/modules/logger.rs @@ -8,12 +8,12 @@ use std::fmt::Debug; use libafl_qemu_sys::TCGTemp; use crate::{ + EmulatorModules, GuestAddr, Hook, MemAccessInfo, modules::{ - utils::filters::{AddressFilter, NopAddressFilter, NopPageFilter}, EmulatorModule, EmulatorModuleTuple, + utils::filters::{AddressFilter, NopAddressFilter, NopPageFilter}, }, qemu::Qemu, - EmulatorModules, GuestAddr, Hook, MemAccessInfo, }; /// A builder for [`LoggerModule`]. @@ -235,7 +235,7 @@ where let kind = if IS_WRITE { "write" } else { "read" }; let size = info.size(); - log::info!("[PC {pc:#x}] gen {kind} of {size} bytes"); + log::info!("[PC {pc:#x}] generator {kind} of {size} bytes"); Some(0) } diff --git a/libafl_qemu/src/modules/mod.rs b/libafl_qemu/src/modules/mod.rs index 667a0223fa..b26d45ffb1 100644 --- a/libafl_qemu/src/modules/mod.rs +++ b/libafl_qemu/src/modules/mod.rs @@ -4,9 +4,9 @@ use libafl::{executors::ExitKind, observers::ObserversTuple}; use libafl_bolts::tuples::{MatchFirstType, SplitBorrowExtractFirstType}; use crate::{ + Qemu, QemuParams, emu::EmulatorModules, modules::utils::filters::{AddressFilter, PageFilter}, - Qemu, QemuParams, }; #[cfg(feature = "usermode")] @@ -362,12 +362,16 @@ where } unsafe fn on_crash_all(&mut self) { - self.0.on_crash(); - self.1.on_crash_all(); + unsafe { + self.0.on_crash(); + self.1.on_crash_all(); + } } unsafe fn on_timeout_all(&mut self) { - self.0.on_timeout(); - self.1.on_timeout_all(); + unsafe { + self.0.on_timeout(); + self.1.on_timeout_all(); + } } } diff --git a/libafl_qemu/src/modules/usermode/asan.rs b/libafl_qemu/src/modules/usermode/asan.rs index 040b9be16d..1998ae78c8 100644 --- a/libafl_qemu/src/modules/usermode/asan.rs +++ b/libafl_qemu/src/modules/usermode/asan.rs @@ -15,22 +15,22 @@ use libafl::{executors::ExitKind, observers::ObserversTuple}; use libafl_bolts::os::unix_signals::Signal; use libafl_qemu_sys::GuestAddr; use libc::{ - c_void, MAP_ANON, MAP_FAILED, MAP_FIXED, MAP_NORESERVE, MAP_PRIVATE, PROT_READ, PROT_WRITE, + MAP_ANON, MAP_FAILED, MAP_FIXED, MAP_NORESERVE, MAP_PRIVATE, PROT_READ, PROT_WRITE, c_void, }; use meminterval::{Interval, IntervalTree}; use num_enum::{IntoPrimitive, TryFromPrimitive}; use crate::{ + Qemu, QemuParams, Regs, emu::EmulatorModules, modules::{ + AddressFilter, EmulatorModule, EmulatorModuleTuple, calls::FullBacktraceCollector, snapshot::SnapshotModule, utils::filters::{HasAddressFilter, StdAddressFilter}, - AddressFilter, EmulatorModule, EmulatorModuleTuple, }, qemu::{Hook, MemAccessInfo, QemuHooks, SyscallHookResult}, sys::TCGTemp, - Qemu, QemuParams, Regs, }; // TODO at some point, merge parts with libafl_frida @@ -171,7 +171,7 @@ impl AsanErrorCallback { /// The `ASan` error report accesses [`FullBacktraceCollector`] #[must_use] pub unsafe fn report() -> Self { - Self::new(Box::new(|rt, qemu, pc, err| { + Self::new(Box::new(|rt, qemu, pc, err| unsafe { asan_report(rt, qemu, pc, &err); })) } @@ -330,7 +330,7 @@ impl AsanModuleBuilder { self.detect_leaks, self.snapshot, self.filter, - Some(AsanErrorCallback::report()), + Some(unsafe { AsanErrorCallback::report() }), self.target_crash, ) } @@ -478,41 +478,43 @@ impl AsanModule { impl AsanGiovese { unsafe fn init(self: &mut Pin>, qemu_hooks: QemuHooks) { - assert_ne!( - libc::mmap( - HIGH_SHADOW_ADDR, - HIGH_SHADOW_SIZE, - PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_FIXED | MAP_NORESERVE | MAP_ANON, - -1, - 0 - ), - MAP_FAILED - ); - assert_ne!( - libc::mmap( - LOW_SHADOW_ADDR, - LOW_SHADOW_SIZE, - PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_FIXED | MAP_NORESERVE | MAP_ANON, - -1, - 0 - ), - MAP_FAILED - ); - assert_ne!( - libc::mmap( - GAP_SHADOW_ADDR, - GAP_SHADOW_SIZE, - PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_FIXED | MAP_NORESERVE | MAP_ANON, - -1, - 0 - ), - MAP_FAILED - ); + unsafe { + assert_ne!( + libc::mmap( + HIGH_SHADOW_ADDR, + HIGH_SHADOW_SIZE, + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_FIXED | MAP_NORESERVE | MAP_ANON, + -1, + 0 + ), + MAP_FAILED + ); + assert_ne!( + libc::mmap( + LOW_SHADOW_ADDR, + LOW_SHADOW_SIZE, + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_FIXED | MAP_NORESERVE | MAP_ANON, + -1, + 0 + ), + MAP_FAILED + ); + assert_ne!( + libc::mmap( + GAP_SHADOW_ADDR, + GAP_SHADOW_SIZE, + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_FIXED | MAP_NORESERVE | MAP_ANON, + -1, + 0 + ), + MAP_FAILED + ); - qemu_hooks.add_pre_syscall_hook(self.as_mut(), Self::fake_syscall); + qemu_hooks.add_pre_syscall_hook(self.as_mut(), Self::fake_syscall); + } } #[must_use] diff --git a/libafl_qemu/src/modules/usermode/asan_guest.rs b/libafl_qemu/src/modules/usermode/asan_guest.rs index 0d3f0589eb..6de295ecb4 100644 --- a/libafl_qemu/src/modules/usermode/asan_guest.rs +++ b/libafl_qemu/src/modules/usermode/asan_guest.rs @@ -12,14 +12,14 @@ use libafl_qemu_sys::{GuestAddr, MapInfo}; #[cfg(not(feature = "clippy"))] use crate::sys::libafl_tcg_gen_asan; use crate::{ + QemuParams, emu::EmulatorModules, modules::{ - utils::filters::{HasAddressFilter, StdAddressFilter}, AddressFilter, EmulatorModule, EmulatorModuleTuple, + utils::filters::{HasAddressFilter, StdAddressFilter}, }, qemu::{Hook, MemAccessInfo, Qemu}, sys::TCGTemp, - QemuParams, }; #[derive(Clone)] diff --git a/libafl_qemu/src/modules/usermode/injections.rs b/libafl_qemu/src/modules/usermode/injections.rs index 783cdc6efa..3827f8289d 100644 --- a/libafl_qemu/src/modules/usermode/injections.rs +++ b/libafl_qemu/src/modules/usermode/injections.rs @@ -21,14 +21,14 @@ use serde::{Deserialize, Serialize}; #[cfg(not(cpu_target = "hexagon"))] use crate::SYS_execve; use crate::{ + CallingConvention, Qemu, elf::EasyElf, emu::EmulatorModules, modules::{ - utils::filters::{HasAddressFilter, NopAddressFilter, NOP_ADDRESS_FILTER}, EmulatorModule, EmulatorModuleTuple, + utils::filters::{HasAddressFilter, NOP_ADDRESS_FILTER, NopAddressFilter}, }, qemu::{ArchExtras, Hook, SyscallHookResult}, - CallingConvention, Qemu, }; #[cfg(cpu_target = "hexagon")] @@ -451,7 +451,7 @@ fn find_subsequence(haystack: &[u8], needle: &[u8]) -> Option { mod tests { use hashbrown::HashMap; - use super::{yaml_entries_to_definition, InjectionDefinition, YamlInjectionEntry}; + use super::{InjectionDefinition, YamlInjectionEntry, yaml_entries_to_definition}; #[test] fn test_yaml_parsing() { diff --git a/libafl_qemu/src/modules/usermode/snapshot.rs b/libafl_qemu/src/modules/usermode/snapshot.rs index 2bf92038a8..2e3c1aca67 100644 --- a/libafl_qemu/src/modules/usermode/snapshot.rs +++ b/libafl_qemu/src/modules/usermode/snapshot.rs @@ -21,14 +21,14 @@ use crate::SYS_mmap2; )))] use crate::SYS_newfstatat; use crate::{ + Qemu, SYS_brk, SYS_mprotect, SYS_mremap, SYS_munmap, SYS_pread64, SYS_read, SYS_readlinkat, emu::EmulatorModules, modules::{ - asan::AsanModule, - utils::filters::{HasAddressFilter, NopAddressFilter, NOP_ADDRESS_FILTER}, EmulatorModule, EmulatorModuleTuple, + asan::AsanModule, + utils::filters::{HasAddressFilter, NOP_ADDRESS_FILTER, NopAddressFilter}, }, qemu::{Hook, SyscallHookResult}, - Qemu, SYS_brk, SYS_mprotect, SYS_mremap, SYS_munmap, SYS_pread64, SYS_read, SYS_readlinkat, }; #[cfg(not(cpu_target = "riscv32"))] use crate::{SYS_fstat, SYS_fstatfs, SYS_futex, SYS_getrandom, SYS_statfs}; @@ -406,7 +406,13 @@ impl SnapshotModule { // The next for loop will restore their content if needed. let aligned_new_brk = (new_brk + ((SNAPSHOT_PAGE_SIZE - 1) as GuestAddr)) & (!(SNAPSHOT_PAGE_SIZE - 1) as GuestAddr); - log::debug!("New brk ({:#x?}) < snapshotted brk ({:#x?})! Mapping back in the target {:#x?} - {:#x?}", new_brk, self.brk, aligned_new_brk, aligned_new_brk + (self.brk - aligned_new_brk)); + log::debug!( + "New brk ({:#x?}) < snapshotted brk ({:#x?})! Mapping back in the target {:#x?} - {:#x?}", + new_brk, + self.brk, + aligned_new_brk, + aligned_new_brk + (self.brk - aligned_new_brk) + ); qemu.map_fixed( aligned_new_brk, (self.brk - aligned_new_brk) as usize, diff --git a/libafl_qemu/src/modules/utils/addr2line.rs b/libafl_qemu/src/modules/utils/addr2line.rs index 36514e606b..3c1c9d24d3 100644 --- a/libafl_qemu/src/modules/utils/addr2line.rs +++ b/libafl_qemu/src/modules/utils/addr2line.rs @@ -2,7 +2,7 @@ use std::{borrow::Cow, fmt::Write, fs}; -use addr2line::{fallible_iterator::FallibleIterator, Loader}; +use addr2line::{Loader, fallible_iterator::FallibleIterator}; use goblin::elf::dynamic::{DF_1_PIE, DT_FLAGS_1}; use hashbrown::HashMap; use libafl_qemu_sys::GuestAddr; diff --git a/libafl_qemu/src/modules/utils/filters.rs b/libafl_qemu/src/modules/utils/filters.rs index 0845a29e8d..9859204667 100644 --- a/libafl_qemu/src/modules/utils/filters.rs +++ b/libafl_qemu/src/modules/utils/filters.rs @@ -319,15 +319,15 @@ pub(crate) static mut NOP_PAGE_FILTER: UnsafeCell = UnsafeCell::n #[cfg(all(feature = "systemmode", test))] mod tests { - use libafl::{inputs::NopInput, state::NopState, HasMetadata}; + use libafl::{HasMetadata, inputs::NopInput, state::NopState}; use libafl_bolts::tuples::tuple_list; use crate::modules::{ + EmulatorModule, EmulatorModuleTuple, utils::filters::{ AddressFilter, NopAddressFilter, NopPageFilter, PageFilter, StdAddressFilter, StdPageFilter, }, - EmulatorModule, EmulatorModuleTuple, }; #[derive(Clone, Debug)] diff --git a/libafl_qemu/src/qemu/hooks.rs b/libafl_qemu/src/qemu/hooks.rs index f2422e15c5..405a65a06d 100644 --- a/libafl_qemu/src/qemu/hooks.rs +++ b/libafl_qemu/src/qemu/hooks.rs @@ -9,13 +9,13 @@ use core::{ffi::c_void, fmt::Debug, mem::transmute, ptr}; use libafl::executors::hooks::inprocess::inprocess_get_state; use libafl_qemu_sys::{CPUArchStatePtr, CPUStatePtr, FatPtr, GuestAddr, GuestUsize}; #[cfg(feature = "python")] -use pyo3::{pyclass, pymethods, FromPyObject}; +use pyo3::{FromPyObject, pyclass, pymethods}; use crate::{ + HookData, HookId, emu::EmulatorModules, qemu::{MemAccessInfo, Qemu}, sys::TCGTemp, - HookData, HookId, }; pub const SKIP_EXEC_HOOK: u64 = u64::MAX; @@ -31,7 +31,7 @@ pub enum HookRepr { #[derive(Debug)] pub struct TcgHookState { id: H, - gen: HookRepr, + generator: HookRepr, post_gen: HookRepr, execs: [HookRepr; N], } @@ -44,10 +44,10 @@ pub struct HookState { } impl TcgHookState { - pub fn new(id: H, gen: HookRepr, post_gen: HookRepr, execs: [HookRepr; N]) -> Self { + pub fn new(id: H, generator: HookRepr, post_gen: HookRepr, execs: [HookRepr; N]) -> Self { Self { id, - gen, + generator, post_gen, execs, } @@ -297,7 +297,7 @@ macro_rules! create_gen_wrapper { let qemu = Qemu::get_unchecked(); let modules = EmulatorModules::::emulator_modules_mut_unchecked(); - match &mut hook.gen { + match &mut hook.generator { HookRepr::Function(ptr) => { let func: fn(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*) -> Option<$ret_type> = transmute(*ptr); @@ -1035,15 +1035,15 @@ impl QemuHooks { pub fn add_edge_hooks>( &self, data: T, - gen: Option u64>, + generator: Option u64>, exec: Option, ) -> EdgeHookId { unsafe { let data: u64 = data.into().0; - let gen: Option u64> = - transmute(gen); + let generator: Option u64> = + transmute(generator); let exec: Option = transmute(exec); - let num = libafl_qemu_sys::libafl_add_edge_hook(gen, exec, data); + let num = libafl_qemu_sys::libafl_add_edge_hook(generator, exec, data); EdgeHookId(num) } } @@ -1061,17 +1061,18 @@ impl QemuHooks { pub fn add_block_hooks>( &self, data: T, - gen: Option u64>, + generator: Option u64>, post_gen: Option, exec: Option, ) -> BlockHookId { unsafe { let data: u64 = data.into().0; - let gen: Option u64> = transmute(gen); + let generator: Option u64> = + transmute(generator); let post_gen: Option = transmute(post_gen); let exec: Option = transmute(exec); - let num = libafl_qemu_sys::libafl_add_block_hook(gen, post_gen, exec, data); + let num = libafl_qemu_sys::libafl_add_block_hook(generator, post_gen, exec, data); BlockHookId(num) } } @@ -1113,7 +1114,7 @@ impl QemuHooks { pub fn add_read_hooks>( &self, data: T, - gen: Option u64>, + generator: Option u64>, exec1: Option, exec2: Option, exec4: Option, @@ -1122,14 +1123,14 @@ impl QemuHooks { ) -> ReadHookId { unsafe { let data: u64 = data.into().0; - let gen: Option< + let generator: Option< unsafe extern "C" fn( u64, GuestAddr, *mut TCGTemp, libafl_qemu_sys::MemOpIdx, ) -> u64, - > = transmute(gen); + > = transmute(generator); let exec1: Option = transmute(exec1); let exec2: Option = @@ -1141,7 +1142,7 @@ impl QemuHooks { let exec_n: Option = transmute(exec_n); let num = libafl_qemu_sys::libafl_add_read_hook( - gen, exec1, exec2, exec4, exec8, exec_n, data, + generator, exec1, exec2, exec4, exec8, exec_n, data, ); ReadHookId(num) } @@ -1165,7 +1166,7 @@ impl QemuHooks { pub fn add_write_hooks>( &self, data: T, - gen: Option u64>, + generator: Option u64>, exec1: Option, exec2: Option, exec4: Option, @@ -1174,14 +1175,14 @@ impl QemuHooks { ) -> WriteHookId { unsafe { let data: u64 = data.into().0; - let gen: Option< + let generator: Option< unsafe extern "C" fn( u64, GuestAddr, *mut TCGTemp, libafl_qemu_sys::MemOpIdx, ) -> u64, - > = transmute(gen); + > = transmute(generator); let exec1: Option = transmute(exec1); let exec2: Option = @@ -1193,7 +1194,7 @@ impl QemuHooks { let exec_n: Option = transmute(exec_n); let num = libafl_qemu_sys::libafl_add_write_hook( - gen, exec1, exec2, exec4, exec8, exec_n, data, + generator, exec1, exec2, exec4, exec8, exec_n, data, ); WriteHookId(num) } @@ -1202,7 +1203,7 @@ impl QemuHooks { pub fn add_cmp_hooks>( &self, data: T, - gen: Option u64>, + generator: Option u64>, exec1: Option, exec2: Option, exec4: Option, @@ -1210,12 +1211,14 @@ impl QemuHooks { ) -> CmpHookId { unsafe { let data: u64 = data.into().0; - let gen: Option u64> = transmute(gen); + let generator: Option u64> = + transmute(generator); let exec1: Option = transmute(exec1); let exec2: Option = transmute(exec2); let exec4: Option = transmute(exec4); let exec8: Option = transmute(exec8); - let num = libafl_qemu_sys::libafl_add_cmp_hook(gen, exec1, exec2, exec4, exec8, data); + let num = + libafl_qemu_sys::libafl_add_cmp_hook(generator, exec1, exec2, exec4, exec8, data); CmpHookId(num) } } diff --git a/libafl_qemu/src/qemu/mod.rs b/libafl_qemu/src/qemu/mod.rs index 0340844218..d412aaf1db 100644 --- a/libafl_qemu/src/qemu/mod.rs +++ b/libafl_qemu/src/qemu/mod.rs @@ -8,25 +8,25 @@ use core::{ fmt, ptr, slice, }; use std::{ - ffi::{c_void, CString}, + ffi::{CString, c_void}, fmt::{Display, Formatter, Write}, - mem::{transmute, MaybeUninit}, + mem::{MaybeUninit, transmute}, ops::{Deref, Range}, pin::Pin, ptr::copy_nonoverlapping, sync::OnceLock, }; -use libafl_bolts::os::unix_signals::Signal; #[cfg(feature = "systemmode")] use libafl_bolts::Error; +use libafl_bolts::os::unix_signals::Signal; use libafl_qemu_sys::{ + CPUArchState, CPUStatePtr, FatPtr, GuestAddr, GuestPhysAddr, GuestUsize, GuestVirtAddr, libafl_flush_jit, libafl_get_exit_reason, libafl_page_from_addr, libafl_qemu_add_gdb_cmd, libafl_qemu_cpu_index, libafl_qemu_current_cpu, libafl_qemu_gdb_reply, libafl_qemu_get_cpu, libafl_qemu_init, libafl_qemu_num_cpus, libafl_qemu_num_regs, libafl_qemu_read_reg, libafl_qemu_remove_breakpoint, libafl_qemu_set_breakpoint, libafl_qemu_trigger_breakpoint, - libafl_qemu_write_reg, CPUArchState, CPUStatePtr, FatPtr, GuestAddr, GuestPhysAddr, GuestUsize, - GuestVirtAddr, + libafl_qemu_write_reg, }; #[cfg(feature = "systemmode")] use libafl_qemu_sys::{libafl_qemu_remove_hw_breakpoint, libafl_qemu_set_hw_breakpoint}; @@ -55,7 +55,7 @@ pub use systemmode::*; mod hooks; pub use hooks::*; -use libafl_bolts::{vec_init, AsSliceMut}; +use libafl_bolts::{AsSliceMut, vec_init}; static mut QEMU_IS_INITIALIZED: bool = false; static mut QEMU_IS_RUNNING: bool = false; @@ -645,9 +645,11 @@ impl Qemu { /// Should, in general, be safe to call. /// Of course, the emulated target is not contained securely and can corrupt state or interact with the operating system. pub unsafe fn run(&self) -> Result { - QEMU_IS_RUNNING = true; - self.run_inner(); - QEMU_IS_RUNNING = false; + unsafe { + QEMU_IS_RUNNING = true; + self.run_inner(); + QEMU_IS_RUNNING = false; + } let exit_reason = unsafe { libafl_get_exit_reason() }; if exit_reason.is_null() { @@ -775,11 +777,13 @@ impl Qemu { /// No checked is performed to check whether the returned object makes sense or not. // TODO: Use sized array when const generics are stabilized. pub unsafe fn read_mem_val(&self, addr: GuestAddr) -> Result { - // let mut val_buf: [u8; size_of::()] = [0; size_of::()]; + unsafe { + // let mut val_buf: [u8; size_of::()] = [0; size_of::()]; - let val_buf: Vec = vec_init(size_of::(), |buf| self.read_mem(addr, buf))?; + let val_buf: Vec = vec_init(size_of::(), |buf| self.read_mem(addr, buf))?; - Ok(ptr::read(val_buf.as_ptr() as *const T)) + Ok(ptr::read(val_buf.as_ptr() as *const T)) + } } /// Write a value to memory at a guest addr, taking into account the potential indirections with the current CPU. @@ -788,10 +792,13 @@ impl Qemu { /// /// val will be used as parameter of [`slice::from_raw_parts`], and thus must enforce the same requirements. pub unsafe fn write_mem_val(&self, addr: GuestAddr, val: &T) -> Result<(), QemuRWError> { - let val_buf: &[u8] = slice::from_raw_parts(ptr::from_ref(val) as *const u8, size_of::()); - self.write_mem(addr, val_buf)?; + unsafe { + let val_buf: &[u8] = + slice::from_raw_parts(ptr::from_ref(val) as *const u8, size_of::()); + self.write_mem(addr, val_buf)?; - Ok(()) + Ok(()) + } } /// Read a value from a guest address. @@ -804,9 +811,11 @@ impl Qemu { /// /// Please refer to [`CPU::read_mem`] for more details. pub unsafe fn read_mem_unchecked(&self, addr: GuestAddr, buf: &mut [u8]) { - self.current_cpu() - .unwrap_or_else(|| self.cpu_from_index(0)) - .read_mem_unchecked(addr, buf); + unsafe { + self.current_cpu() + .unwrap_or_else(|| self.cpu_from_index(0)) + .read_mem_unchecked(addr, buf); + } } /// Write a value to a guest address. @@ -819,9 +828,11 @@ impl Qemu { /// This may only be safely used for valid guest addresses. /// Please refer to [`CPU::write_mem`] for more details. pub unsafe fn write_mem_unchecked(&self, addr: GuestAddr, buf: &[u8]) { - self.current_cpu() - .unwrap_or_else(|| self.cpu_from_index(0)) - .write_mem_unchecked(addr, buf); + unsafe { + self.current_cpu() + .unwrap_or_else(|| self.cpu_from_index(0)) + .write_mem_unchecked(addr, buf); + } } #[must_use] @@ -923,13 +934,15 @@ impl Qemu { /// Calling this multiple times concurrently will access static variables and is unsafe. #[expect(clippy::type_complexity)] pub unsafe fn add_gdb_cmd(&self, callback: Box bool>) { - let fat: Box = Box::new(transmute::< - Box FnMut(&'a Qemu, &'b str) -> bool>, - FatPtr, - >(callback)); - libafl_qemu_add_gdb_cmd(Some(gdb_cmd), ptr::from_ref(&*fat) as *mut c_void); - let commands_ptr = &raw mut GDB_COMMANDS; - (*commands_ptr).push(fat); + unsafe { + let fat: Box = Box::new(transmute::< + Box FnMut(&'a Qemu, &'b str) -> bool>, + FatPtr, + >(callback)); + libafl_qemu_add_gdb_cmd(Some(gdb_cmd), ptr::from_ref(&*fat) as *mut c_void); + let commands_ptr = &raw mut GDB_COMMANDS; + (*commands_ptr).push(fat); + } } pub fn gdb_reply(&self, output: &str) { diff --git a/libafl_qemu/src/qemu/systemmode.rs b/libafl_qemu/src/qemu/systemmode.rs index cbdfd5d9a5..d890888c70 100644 --- a/libafl_qemu/src/qemu/systemmode.rs +++ b/libafl_qemu/src/qemu/systemmode.rs @@ -1,5 +1,5 @@ use std::{ - ffi::{c_void, CStr, CString}, + ffi::{CStr, CString, c_void}, marker::PhantomData, mem::MaybeUninit, ptr::null_mut, @@ -8,16 +8,16 @@ use std::{ use bytes_utils::SegmentedBuf; use libafl_qemu_sys::{ - libafl_load_qemu_snapshot, libafl_page_from_addr, libafl_qemu_current_paging_id, - libafl_save_qemu_snapshot, qemu_cleanup, qemu_main_loop, vm_start, GuestAddr, GuestPhysAddr, - GuestUsize, GuestVirtAddr, + GuestAddr, GuestPhysAddr, GuestUsize, GuestVirtAddr, libafl_load_qemu_snapshot, + libafl_page_from_addr, libafl_qemu_current_paging_id, libafl_save_qemu_snapshot, qemu_cleanup, + qemu_main_loop, vm_start, }; use libc::EXIT_SUCCESS; use num_traits::Zero; use crate::{ - FastSnapshotPtr, GuestAddrKind, MemAccessInfo, Qemu, QemuMemoryChunk, QemuSnapshotCheckResult, - CPU, + CPU, FastSnapshotPtr, GuestAddrKind, MemAccessInfo, Qemu, QemuMemoryChunk, + QemuSnapshotCheckResult, }; pub(super) extern "C" fn qemu_cleanup_atexit() { @@ -148,13 +148,15 @@ impl CPU { /// if a problem occurred during the operation, there will be no feedback pub unsafe fn read_mem_unchecked(&self, addr: GuestAddr, buf: &mut [u8]) { // TODO use gdbstub's target_cpu_memory_rw_debug - libafl_qemu_sys::cpu_memory_rw_debug( - self.ptr, - addr as GuestVirtAddr, - buf.as_mut_ptr() as *mut _, - buf.len(), - false, - ); + unsafe { + libafl_qemu_sys::cpu_memory_rw_debug( + self.ptr, + addr as GuestVirtAddr, + buf.as_mut_ptr() as *mut _, + buf.len(), + false, + ); + } } /// Write a value to a guest address, taking into account the potential MMU / MPU. @@ -164,13 +166,15 @@ impl CPU { /// if a problem occurred during the operation, there will be no feedback pub unsafe fn write_mem_unchecked(&self, addr: GuestAddr, buf: &[u8]) { // TODO use gdbstub's target_cpu_memory_rw_debug - libafl_qemu_sys::cpu_memory_rw_debug( - self.ptr, - addr as GuestVirtAddr, - buf.as_ptr() as *mut _, - buf.len(), - true, - ); + unsafe { + libafl_qemu_sys::cpu_memory_rw_debug( + self.ptr, + addr as GuestVirtAddr, + buf.as_ptr() as *mut _, + buf.len(), + true, + ); + } } } @@ -189,12 +193,14 @@ impl Qemu { /// Nothing bad will happen if the operation is incorrect, but it will be silently skipped. // TODO: use address_space_rw and check for the result MemTxResult pub unsafe fn write_phys_mem(&self, paddr: GuestPhysAddr, buf: &[u8]) { - libafl_qemu_sys::cpu_physical_memory_rw( - paddr, - buf.as_ptr() as *mut _, - buf.len() as u64, - true, - ); + unsafe { + libafl_qemu_sys::cpu_physical_memory_rw( + paddr, + buf.as_ptr() as *mut _, + buf.len() as u64, + true, + ); + } } /// Read a value from a physical guest address, including ROM areas. @@ -205,18 +211,22 @@ impl Qemu { /// Nothing bad will happen if the operation is incorrect, but it will be silently skipped. // TODO: use address_space_rw and check for the result MemTxResult pub unsafe fn read_phys_mem(&self, paddr: GuestPhysAddr, buf: &mut [u8]) { - libafl_qemu_sys::cpu_physical_memory_rw( - paddr, - buf.as_mut_ptr() as *mut _, - buf.len() as u64, - false, - ); + unsafe { + libafl_qemu_sys::cpu_physical_memory_rw( + paddr, + buf.as_mut_ptr() as *mut _, + buf.len() as u64, + false, + ); + } } #[expect(clippy::trivially_copy_pass_by_ref)] pub(super) unsafe fn run_inner(&self) { - vm_start(); - qemu_main_loop(); + unsafe { + vm_start(); + qemu_main_loop(); + } } pub fn save_snapshot(&self, name: &str, sync: bool) { @@ -260,7 +270,9 @@ impl Qemu { #[expect(clippy::missing_safety_doc)] pub unsafe fn restore_fast_snapshot(&self, snapshot: FastSnapshotPtr) { - libafl_qemu_sys::syx_snapshot_root_restore(snapshot); + unsafe { + libafl_qemu_sys::syx_snapshot_root_restore(snapshot); + } } #[must_use] @@ -269,7 +281,7 @@ impl Qemu { &self, ref_snapshot: FastSnapshotPtr, ) -> QemuSnapshotCheckResult { - let check_result = libafl_qemu_sys::syx_snapshot_check(ref_snapshot); + let check_result = unsafe { libafl_qemu_sys::syx_snapshot_check(ref_snapshot) }; QemuSnapshotCheckResult::new(check_result.nb_inconsistencies) } diff --git a/libafl_qemu/src/qemu/usermode.rs b/libafl_qemu/src/qemu/usermode.rs index 152b42a2dd..81ab682b84 100644 --- a/libafl_qemu/src/qemu/usermode.rs +++ b/libafl_qemu/src/qemu/usermode.rs @@ -5,16 +5,16 @@ use std::{ use libafl_bolts::os::unix_signals::Signal; use libafl_qemu_sys::{ + GuestAddr, GuestUsize, IntervalTreeNode, IntervalTreeRoot, MapInfo, MmapPerms, VerifyAccess, exec_path, free_self_maps, guest_base, libafl_force_dfl, libafl_get_brk, libafl_get_initial_brk, libafl_load_addr, libafl_maps_first, libafl_maps_next, libafl_qemu_run, - libafl_set_brk, mmap_next_start, pageflags_get_root, read_self_maps, GuestAddr, GuestUsize, - IntervalTreeNode, IntervalTreeRoot, MapInfo, MmapPerms, VerifyAccess, + libafl_set_brk, mmap_next_start, pageflags_get_root, read_self_maps, }; use libc::{c_int, c_uchar, siginfo_t, strlen}; #[cfg(feature = "python")] -use pyo3::{pyclass, pymethods, IntoPyObject, Py, PyRef, PyRefMut, Python}; +use pyo3::{IntoPyObject, Py, PyRef, PyRefMut, Python, pyclass, pymethods}; -use crate::{qemu::QEMU_IS_RUNNING, Qemu, CPU}; +use crate::{CPU, Qemu, qemu::QEMU_IS_RUNNING}; pub struct QemuMappingsViewer<'a> { qemu: &'a Qemu, @@ -122,11 +122,7 @@ impl Iterator for GuestMaps { let ret = ret.assume_init(); - if ret.is_valid { - Some(ret.into()) - } else { - None - } + if ret.is_valid { Some(ret.into()) } else { None } } } } @@ -160,8 +156,10 @@ impl CPU { /// It just adds `guest_base` and writes to that location, without checking the bounds. /// This may only be safely used for valid guest addresses! pub unsafe fn read_mem_unchecked(&self, addr: GuestAddr, buf: &mut [u8]) { - let host_addr = Qemu::get().unwrap().g2h(addr); - copy_nonoverlapping(host_addr, buf.as_mut_ptr(), buf.len()); + unsafe { + let host_addr = Qemu::get().unwrap().g2h(addr); + copy_nonoverlapping(host_addr, buf.as_mut_ptr(), buf.len()); + } } /// Write a value to a guest address. @@ -172,8 +170,10 @@ impl CPU { /// It just adds `guest_base` and writes to that location, without checking the bounds. /// This may only be safely used for valid guest addresses! pub unsafe fn write_mem_unchecked(&self, addr: GuestAddr, buf: &[u8]) { - let host_addr = Qemu::get().unwrap().g2h(addr); - copy_nonoverlapping(buf.as_ptr(), host_addr, buf.len()); + unsafe { + let host_addr = Qemu::get().unwrap().g2h(addr); + copy_nonoverlapping(buf.as_ptr(), host_addr, buf.len()); + } } #[must_use] @@ -253,7 +253,9 @@ impl Qemu { } pub(super) unsafe fn run_inner(self) { - libafl_qemu_run(); + unsafe { + libafl_qemu_run(); + } } #[must_use] @@ -391,7 +393,9 @@ impl Qemu { info: *mut siginfo_t, puc: *mut c_void, ) { - libafl_qemu_sys::libafl_qemu_native_signal_handler(host_sig, info, puc); + unsafe { + libafl_qemu_sys::libafl_qemu_native_signal_handler(host_sig, info, puc); + } } /// Emulate a signal coming from the target @@ -401,9 +405,11 @@ impl Qemu { /// This may raise a signal to host. Some signals could have a funky behaviour. /// SIGSEGV is safe to use. pub unsafe fn target_signal(&self, signal: Signal) { - QEMU_IS_RUNNING = true; - libafl_qemu_sys::libafl_set_in_target_signal_ctx(); - libc::raise(signal.into()); + unsafe { + QEMU_IS_RUNNING = true; + libafl_qemu_sys::libafl_set_in_target_signal_ctx(); + libc::raise(signal.into()); + } } } @@ -411,11 +417,11 @@ impl Qemu { pub mod pybind { use libafl_qemu_sys::{GuestAddr, MmapPerms}; use pyo3::{ + Bound, PyObject, PyResult, Python, conversion::FromPyObject, exceptions::PyValueError, pymethods, types::{PyAnyMethods, PyInt}, - Bound, PyObject, PyResult, Python, }; use crate::{pybind::Qemu, qemu::hooks::SyscallHookResult}; diff --git a/libafl_qemu/src/sync_exit.rs b/libafl_qemu/src/sync_exit.rs index d9634e758c..399c770fda 100644 --- a/libafl_qemu/src/sync_exit.rs +++ b/libafl_qemu/src/sync_exit.rs @@ -2,7 +2,7 @@ use std::fmt::Debug; use enum_map::Enum; -use crate::{get_exit_arch_regs, GuestReg, Regs, CPU}; +use crate::{CPU, GuestReg, Regs, get_exit_arch_regs}; #[derive(Debug, Clone, Enum)] pub enum ExitArgs { diff --git a/libafl_sugar/Cargo.toml b/libafl_sugar/Cargo.toml index b32a3ff708..ea66e85e6f 100644 --- a/libafl_sugar/Cargo.toml +++ b/libafl_sugar/Cargo.toml @@ -8,7 +8,7 @@ repository = "https://github.com/AFLplusplus/LibAFL/" readme = "../README.md" license = "MIT OR Apache-2.0" keywords = ["fuzzing"] -edition = "2021" +edition = "2024" build = "build.rs" categories = [ "development-tools::testing", diff --git a/libafl_sugar/src/forkserver.rs b/libafl_sugar/src/forkserver.rs index 2e285897ee..c536f69711 100644 --- a/libafl_sugar/src/forkserver.rs +++ b/libafl_sugar/src/forkserver.rs @@ -3,8 +3,9 @@ use std::{fs, net::SocketAddr, path::PathBuf, time::Duration}; use libafl::{ + Error, HasMetadata, corpus::{CachedOnDiskCorpus, Corpus, OnDiskCorpus}, - events::{launcher::Launcher, EventConfig, EventRestarter, LlmpRestartingEventManager}, + events::{EventConfig, EventRestarter, LlmpRestartingEventManager, launcher::Launcher}, executors::forkserver::ForkserverExecutor, feedback_or, feedback_or_fast, feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback}, @@ -13,22 +14,21 @@ use libafl::{ monitors::MultiMonitor, mutators::{ havoc_mutations::havoc_mutations, - scheduled::{tokens_mutations, StdScheduledMutator}, + scheduled::{StdScheduledMutator, tokens_mutations}, token_mutations::Tokens, }, observers::{CanTrack, HitcountsMapObserver, StdMapObserver, TimeObserver}, schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler}, stages::StdMutationalStage, state::{HasCorpus, StdState}, - Error, HasMetadata, }; use libafl_bolts::{ + AsSliceMut, core_affinity::Cores, nonzero, rands::StdRand, shmem::{ShMem, ShMemProvider, UnixShMemProvider}, - tuples::{tuple_list, Handled, Merge}, - AsSliceMut, + tuples::{Handled, Merge, tuple_list}, }; use typed_builder::TypedBuilder; @@ -125,11 +125,15 @@ impl ForkserverBytesCoverageSugar<'_> { // Coverage map shared between target and fuzzer let mut shmem = shmem_provider_client.new_shmem(MAP_SIZE).unwrap(); - shmem.write_to_env("__AFL_SHM_ID").unwrap(); + unsafe { + shmem.write_to_env("__AFL_SHM_ID").unwrap(); + } let shmem_map = shmem.as_slice_mut(); // To let know the AFL++ binary that we have a big map - std::env::set_var("AFL_MAP_SIZE", format!("{MAP_SIZE}")); + unsafe { + std::env::set_var("AFL_MAP_SIZE", format!("{MAP_SIZE}")); + } // Create an observation channel using the coverage map let edges_observer = unsafe { diff --git a/libafl_sugar/src/inmemory.rs b/libafl_sugar/src/inmemory.rs index e26765a26d..45e31b4c3f 100644 --- a/libafl_sugar/src/inmemory.rs +++ b/libafl_sugar/src/inmemory.rs @@ -5,9 +5,10 @@ use core::fmt::{self, Debug, Formatter}; use std::{fs, net::SocketAddr, path::PathBuf, time::Duration}; use libafl::{ + Error, HasMetadata, corpus::{CachedOnDiskCorpus, Corpus, OnDiskCorpus}, - events::{launcher::Launcher, EventConfig, EventRestarter, LlmpRestartingEventManager}, - executors::{inprocess::InProcessExecutor, ExitKind, ShadowExecutor}, + events::{EventConfig, EventRestarter, LlmpRestartingEventManager, launcher::Launcher}, + executors::{ExitKind, ShadowExecutor, inprocess::InProcessExecutor}, feedback_or, feedback_or_fast, feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback}, fuzzer::{Fuzzer, StdFuzzer}, @@ -16,25 +17,24 @@ use libafl::{ monitors::MultiMonitor, mutators::{ havoc_mutations::havoc_mutations, - scheduled::{tokens_mutations, StdScheduledMutator}, + scheduled::{StdScheduledMutator, tokens_mutations}, token_mutations::{I2SRandReplace, Tokens}, }, observers::{CanTrack, HitcountsMapObserver, StdMapObserver, TimeObserver}, schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler}, stages::{ShadowTracingStage, StdMutationalStage}, state::{HasCorpus, StdState}, - Error, HasMetadata, }; use libafl_bolts::{ + AsSlice, core_affinity::Cores, nonzero, ownedref::OwnedMutSlice, rands::StdRand, shmem::{ShMemProvider, StdShMemProvider}, - tuples::{tuple_list, Handled, Merge}, - AsSlice, + tuples::{Handled, Merge, tuple_list}, }; -use libafl_targets::{edges_map_mut_ptr, CmpLogObserver}; +use libafl_targets::{CmpLogObserver, edges_map_mut_ptr}; use typed_builder::TypedBuilder; use crate::{CORPUS_CACHE_SIZE, DEFAULT_TIMEOUT_SECS}; diff --git a/libafl_sugar/src/qemu.rs b/libafl_sugar/src/qemu.rs index 199acc58b5..7dc98aeeb2 100644 --- a/libafl_sugar/src/qemu.rs +++ b/libafl_sugar/src/qemu.rs @@ -3,8 +3,9 @@ use core::fmt::{self, Debug, Formatter}; use std::{fs, net::SocketAddr, path::PathBuf, time::Duration}; use libafl::{ + HasMetadata, corpus::{CachedOnDiskCorpus, Corpus, OnDiskCorpus}, - events::{launcher::Launcher, EventConfig, EventRestarter, LlmpRestartingEventManager}, + events::{EventConfig, EventRestarter, LlmpRestartingEventManager, launcher::Launcher}, executors::{ExitKind, ShadowExecutor}, feedback_or, feedback_or_fast, feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback}, @@ -13,31 +14,30 @@ use libafl::{ inputs::{BytesInput, HasTargetBytes}, monitors::MultiMonitor, mutators::{ - havoc_mutations::havoc_mutations, - scheduled::{tokens_mutations, StdScheduledMutator}, - token_mutations::Tokens, I2SRandReplace, + havoc_mutations::havoc_mutations, + scheduled::{StdScheduledMutator, tokens_mutations}, + token_mutations::Tokens, }, observers::{CanTrack, HitcountsMapObserver, TimeObserver, VariableMapObserver}, schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler}, stages::{ShadowTracingStage, StdMutationalStage}, state::{HasCorpus, StdState}, - HasMetadata, }; use libafl_bolts::{ + AsSlice, core_affinity::Cores, nonzero, ownedref::OwnedMutSlice, rands::StdRand, shmem::{ShMemProvider, StdShMemProvider}, - tuples::{tuple_list, Handled, Merge}, - AsSlice, + tuples::{Handled, Merge, tuple_list}, }; #[cfg(not(any(feature = "mips", feature = "hexagon")))] use libafl_qemu::modules::CmpLogModule; pub use libafl_qemu::qemu::Qemu; -use libafl_qemu::{modules::edges::StdEdgeCoverageModule, Emulator, QemuExecutor}; -use libafl_targets::{edges_map_mut_ptr, CmpLogObserver, EDGES_MAP_DEFAULT_SIZE, MAX_EDGES_FOUND}; +use libafl_qemu::{Emulator, QemuExecutor, modules::edges::StdEdgeCoverageModule}; +use libafl_targets::{CmpLogObserver, EDGES_MAP_DEFAULT_SIZE, MAX_EDGES_FOUND, edges_map_mut_ptr}; use typed_builder::TypedBuilder; use crate::{CORPUS_CACHE_SIZE, DEFAULT_TIMEOUT_SECS}; @@ -223,10 +223,12 @@ where } #[cfg(any(feature = "mips", feature = "hexagon"))] { - tuple_list!(StdEdgeCoverageModule::builder() - .map_observer(edges_observer.as_mut()) - .build() - .unwrap()) + tuple_list!( + StdEdgeCoverageModule::builder() + .map_observer(edges_observer.as_mut()) + .build() + .unwrap() + ) } }; @@ -346,10 +348,12 @@ where } } } else { - let modules = tuple_list!(StdEdgeCoverageModule::builder() - .map_observer(edges_observer.as_mut()) - .build() - .unwrap()); + let modules = tuple_list!( + StdEdgeCoverageModule::builder() + .map_observer(edges_observer.as_mut()) + .build() + .unwrap() + ); let mut harness = |_emulator: &mut Emulator<_, _, _, _, _, _, _>, _state: &mut _, diff --git a/libafl_targets/Cargo.toml b/libafl_targets/Cargo.toml index de33e6f920..6e1839fb9f 100644 --- a/libafl_targets/Cargo.toml +++ b/libafl_targets/Cargo.toml @@ -8,8 +8,8 @@ repository = "https://github.com/AFLplusplus/LibAFL/" readme = "../README.md" license = "MIT OR Apache-2.0" keywords = ["fuzzing", "testing"] -edition = "2021" -rust-version = "1.82" +edition = "2024" +rust-version = "1.85" categories = [ "development-tools::testing", "emulators", diff --git a/libafl_targets/src/call.rs b/libafl_targets/src/call.rs index 8b4253af07..32f2e657f8 100644 --- a/libafl_targets/src/call.rs +++ b/libafl_targets/src/call.rs @@ -6,14 +6,14 @@ use once_cell::sync::Lazy; /// The list of functions that this execution has observed pub static mut FUNCTION_LIST: Lazy> = Lazy::new(HashMap::new); -#[no_mangle] +#[unsafe(no_mangle)] /// The runtime code inserted at every callinst invokation (if you used the function-logging.cc) /// # Safety /// unsafe because it touches the pub static mut `FUNCTION_LIST`. /// May not be called concurrently. pub unsafe extern "C" fn __libafl_target_call_hook(id: usize) { let function_list_ptr = &raw mut FUNCTION_LIST; - let function_list = &mut *function_list_ptr; + let function_list = unsafe { &mut *function_list_ptr }; *function_list.entry(id).or_insert(0) += 1; } diff --git a/libafl_targets/src/cmps/mod.rs b/libafl_targets/src/cmps/mod.rs index 21818e9368..ba7d961a25 100644 --- a/libafl_targets/src/cmps/mod.rs +++ b/libafl_targets/src/cmps/mod.rs @@ -13,8 +13,8 @@ use core::{ }; use libafl::{ - observers::{cmp::AFLppCmpLogHeader, CmpMap, CmpValues, CmplogBytes}, Error, + observers::{CmpMap, CmpValues, CmplogBytes, cmp::AFLppCmpLogHeader}, }; use libafl_bolts::HasLen; use serde::{Deserialize, Deserializer, Serialize, Serializer}; @@ -47,7 +47,7 @@ pub const CMPLOG_KIND_RTN: u8 = 1; #[cfg(feature = "cmplog")] // void __libafl_targets_cmplog_instructions(uintptr_t k, uint8_t shape, uint64_t arg1, uint64_t arg2) -extern "C" { +unsafe extern "C" { /// Logs an instruction for feedback during fuzzing pub fn __libafl_targets_cmplog_instructions(k: usize, shape: u8, arg1: u64, arg2: u64); @@ -62,7 +62,7 @@ extern "C" { pub use libafl_cmplog_map_ptr as CMPLOG_MAP_PTR; /// Value indicating if cmplog is enabled. -#[no_mangle] +#[unsafe(no_mangle)] #[allow(non_upper_case_globals)] // expect breaks here for some reason pub static mut libafl_cmplog_enabled: u8 = 0; @@ -423,7 +423,7 @@ impl CmpMap for CmpLogMap { } /// The global `CmpLog` map for the current `LibAFL` run. -#[no_mangle] +#[unsafe(no_mangle)] #[allow(non_upper_case_globals)] // expect breaks here for some reason pub static mut libafl_cmplog_map: CmpLogMap = CmpLogMap { headers: [CmpLogHeader { @@ -437,7 +437,7 @@ pub static mut libafl_cmplog_map: CmpLogMap = CmpLogMap { }; /// The globale `CmpLog` map, aflpp style -#[no_mangle] +#[unsafe(no_mangle)] #[cfg(feature = "cmplog_extended_instrumentation")] pub static mut libafl_cmplog_map_extended: AFLppCmpLogMap = AFLppCmpLogMap { headers: [AFLppCmpLogHeader::new_with_raw_value(0); CMPLOG_MAP_W], diff --git a/libafl_targets/src/cmps/observers/aflpp.rs b/libafl_targets/src/cmps/observers/aflpp.rs index 28efe97849..f78161a689 100644 --- a/libafl_targets/src/cmps/observers/aflpp.rs +++ b/libafl_targets/src/cmps/observers/aflpp.rs @@ -2,14 +2,14 @@ use alloc::{borrow::Cow, vec::Vec}; use core::fmt::Debug; use libafl::{ + Error, HasMetadata, executors::ExitKind, observers::{ - cmp::{AFLppCmpValuesMetadata, CmpMap, CmpObserver, CmpValues}, Observer, + cmp::{AFLppCmpValuesMetadata, CmpMap, CmpObserver, CmpValues}, }, - Error, HasMetadata, }; -use libafl_bolts::{ownedref::OwnedRefMut, Named}; +use libafl_bolts::{Named, ownedref::OwnedRefMut}; use serde::{Deserialize, Serialize}; use crate::cmps::AFLppCmpLogMap; diff --git a/libafl_targets/src/cmps/observers/cmplog.rs b/libafl_targets/src/cmps/observers/cmplog.rs index eeb15d7782..925b71f4f6 100644 --- a/libafl_targets/src/cmps/observers/cmplog.rs +++ b/libafl_targets/src/cmps/observers/cmplog.rs @@ -5,15 +5,15 @@ use alloc::borrow::Cow; use core::fmt::Debug; use libafl::{ - executors::ExitKind, - observers::{cmp::CmpValuesMetadata, CmpMap, CmpObserver, Observer}, Error, HasMetadata, + executors::ExitKind, + observers::{CmpMap, CmpObserver, Observer, cmp::CmpValuesMetadata}, }; -use libafl_bolts::{ownedref::OwnedMutPtr, Named}; +use libafl_bolts::{Named, ownedref::OwnedMutPtr}; #[cfg(feature = "cmplog")] use crate::cmps::libafl_cmplog_map_ptr; -use crate::cmps::{CmpLogMap, CMPLOG_ENABLED}; +use crate::cmps::{CMPLOG_ENABLED, CmpLogMap}; /// A [`CmpObserver`] observer for `CmpLog` #[derive(Debug)] pub struct CmpLogObserver { diff --git a/libafl_targets/src/cmps/stages/aflpptracing.rs b/libafl_targets/src/cmps/stages/aflpptracing.rs index 71782a46f1..20c3b2cd52 100644 --- a/libafl_targets/src/cmps/stages/aflpptracing.rs +++ b/libafl_targets/src/cmps/stages/aflpptracing.rs @@ -2,17 +2,17 @@ use alloc::borrow::{Cow, ToOwned}; use core::marker::PhantomData; use libafl::{ + Error, HasMetadata, HasNamedMetadata, corpus::HasCurrentCorpusId, executors::{Executor, HasObservers}, inputs::BytesInput, observers::ObserversTuple, - stages::{colorization::TaintMetadata, Restartable, RetryCountRestartHelper, Stage}, + stages::{Restartable, RetryCountRestartHelper, Stage, colorization::TaintMetadata}, state::{HasCorpus, HasCurrentTestcase}, - Error, HasMetadata, HasNamedMetadata, }; use libafl_bolts::{ - tuples::{Handle, MatchNameRef}, Named, + tuples::{Handle, MatchNameRef}, }; use crate::cmps::observers::AFLppCmpLogObserver; diff --git a/libafl_targets/src/coverage.rs b/libafl_targets/src/coverage.rs index d272348deb..2a7e764da9 100644 --- a/libafl_targets/src/coverage.rs +++ b/libafl_targets/src/coverage.rs @@ -10,24 +10,24 @@ use alloc::borrow::Cow; #[cfg(any(target_os = "linux", target_vendor = "apple"))] -use libafl::{mutators::Tokens, Error}; +use libafl::{Error, mutators::Tokens}; use crate::{ACCOUNTING_MAP_SIZE, DDG_MAP_SIZE, EDGES_MAP_ALLOCATED_SIZE, EDGES_MAP_DEFAULT_SIZE}; /// The map for edges. -#[no_mangle] +#[unsafe(no_mangle)] #[allow(non_upper_case_globals)] // expect breaks here for some reason pub static mut __afl_area_ptr_local: [u8; EDGES_MAP_ALLOCATED_SIZE] = [0; EDGES_MAP_ALLOCATED_SIZE]; pub use __afl_area_ptr_local as EDGES_MAP; /// The map for data dependency -#[no_mangle] +#[unsafe(no_mangle)] #[allow(non_upper_case_globals)] // expect breaks here for some reason pub static mut __ddg_area_ptr_local: [u8; DDG_MAP_SIZE] = [0; DDG_MAP_SIZE]; pub use __ddg_area_ptr_local as DDG_MAP; /// The map for accounting mem writes. -#[no_mangle] +#[unsafe(no_mangle)] #[allow(non_upper_case_globals)] // expect breaks here for some reason pub static mut __afl_acc_memop_ptr_local: [u32; ACCOUNTING_MAP_SIZE] = [0; ACCOUNTING_MAP_SIZE]; pub use __afl_acc_memop_ptr_local as ACCOUNTING_MEMOP_MAP; @@ -38,7 +38,7 @@ pub use __afl_acc_memop_ptr_local as ACCOUNTING_MEMOP_MAP; /// You can use this for the initial map size for the observer only if you compute this time at compilation time. pub static mut MAX_EDGES_FOUND: usize = 0; -extern "C" { +unsafe extern "C" { /// The area pointer points to the edges map. pub static mut __afl_area_ptr: *mut u8; @@ -79,7 +79,7 @@ pub fn autotokens() -> Result { /// The actual size we use for the map of edges. /// This is used for forkserver backend #[allow(non_upper_case_globals)] // expect breaks here for some reason -#[no_mangle] +#[unsafe(no_mangle)] pub static mut __afl_map_size: usize = EDGES_MAP_DEFAULT_SIZE; #[cfg(any( @@ -115,7 +115,7 @@ use libafl_bolts::ownedref::OwnedMutSlice; feature = "sancov_ctx" ))] pub unsafe fn edges_map_mut_slice<'a>() -> OwnedMutSlice<'a, u8> { - OwnedMutSlice::from_raw_parts_mut(edges_map_mut_ptr(), edges_max_num()) + unsafe { OwnedMutSlice::from_raw_parts_mut(edges_map_mut_ptr(), edges_max_num()) } } /// Gets a new [`StdMapObserver`] from the current [`edges_map_mut_slice`]. @@ -156,7 +156,7 @@ pub unsafe fn std_edges_map_observer<'a, S>(name: S) -> StdMapObserver<'a, u8, f where S: Into>, { - StdMapObserver::from_mut_slice(name, edges_map_mut_slice()) + unsafe { StdMapObserver::from_mut_slice(name, edges_map_mut_slice()) } } /// Gets the current edges map pt @@ -210,10 +210,10 @@ mod swap { use core::fmt::Debug; use libafl::{ - observers::{DifferentialObserver, Observer, StdMapObserver}, Error, + observers::{DifferentialObserver, Observer, StdMapObserver}, }; - use libafl_bolts::{ownedref::OwnedMutSlice, AsSliceMut, Named}; + use libafl_bolts::{AsSliceMut, Named, ownedref::OwnedMutSlice}; use serde::{Deserialize, Serialize}; use super::EDGES_MAP_PTR; diff --git a/libafl_targets/src/drcov.rs b/libafl_targets/src/drcov.rs index 8b9fa30221..cdd5d6900d 100644 --- a/libafl_targets/src/drcov.rs +++ b/libafl_targets/src/drcov.rs @@ -479,7 +479,10 @@ impl DrCovReader { if let Some(own_module) = self.module_by_id(module.id) { // Module exists, make sure it's the same. if own_module.base != module.base || own_module.end != module.end { - return Err(Error::illegal_argument(format!("Module id of file to merge doesn't fit! Own modules: {:#x?}, other modules: {:#x?}", self.module_entries, other.module_entries))); + return Err(Error::illegal_argument(format!( + "Module id of file to merge doesn't fit! Own modules: {:#x?}, other modules: {:#x?}", + self.module_entries, other.module_entries + ))); } } else { // We don't know the module. Insert as new module. diff --git a/libafl_targets/src/forkserver.rs b/libafl_targets/src/forkserver.rs index ed9a595c6e..79212bddd0 100644 --- a/libafl_targets/src/forkserver.rs +++ b/libafl_targets/src/forkserver.rs @@ -1,6 +1,6 @@ //! Forkserver logic into targets -extern "C" { +unsafe extern "C" { /// Map a shared memory region for the edge coverage map. fn __afl_map_shm(); /// Start the forkserver. diff --git a/libafl_targets/src/libfuzzer/mod.rs b/libafl_targets/src/libfuzzer/mod.rs index 4cd967808b..44962cd422 100644 --- a/libafl_targets/src/libfuzzer/mod.rs +++ b/libafl_targets/src/libfuzzer/mod.rs @@ -13,7 +13,7 @@ mod observers; #[cfg(feature = "libfuzzer_oom")] pub use observers::*; -extern "C" { +unsafe extern "C" { // int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) fn LLVMFuzzerTestOneInput(data: *const u8, size: usize) -> i32; diff --git a/libafl_targets/src/libfuzzer/mutators.rs b/libafl_targets/src/libfuzzer/mutators.rs index d970eaa135..7ea691bf5b 100644 --- a/libafl_targets/src/libfuzzer/mutators.rs +++ b/libafl_targets/src/libfuzzer/mutators.rs @@ -10,6 +10,7 @@ use std::{ }; use libafl::{ + Error, corpus::Corpus, inputs::{BytesInput, HasMutatorBytes, ResizableMutator}, mutators::{ @@ -17,11 +18,10 @@ use libafl::{ }, random_corpus_id_with_disabled, state::{HasCorpus, HasMaxSize, HasRand}, - Error, }; -use libafl_bolts::{rands::Rand, AsSlice, HasLen, Named}; +use libafl_bolts::{AsSlice, HasLen, Named, rands::Rand}; -extern "C" { +unsafe extern "C" { fn libafl_targets_has_libfuzzer_custom_mutator() -> bool; fn libafl_targets_libfuzzer_custom_mutator( data: *mut u8, @@ -68,7 +68,7 @@ thread_local! { /// Mutator which is available for user-defined mutator/crossover /// See: [Structure-Aware Fuzzing with libFuzzer](https://github.com/google/fuzzing/blob/master/docs/structure-aware-fuzzing.md) #[allow(non_snake_case)] // expect breaks here for some reason -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn LLVMFuzzerMutate(data: *mut u8, size: usize, max_size: usize) -> usize { MUTATOR.with(|mutator| { if let Ok(mut mutator) = mutator.try_borrow_mut() { @@ -111,7 +111,10 @@ impl<'a, M, S> MutatorProxy<'a, M, S> { /// Create a weak version of the proxy, which will become unusable when the custom mutator /// is no longer permitted to be executed. #[allow(clippy::type_complexity)] // no longer a problem in nightly - fn weak(&self) -> WeakMutatorProxy FnMut(&'b mut S)) -> bool, M, S> { + fn weak( + &self, + ) -> WeakMutatorProxy FnMut(&'b mut S)) -> bool + use, M, S> + { let state = Rc::downgrade(&self.state); WeakMutatorProxy { accessor: move |f: &mut dyn for<'b> FnMut(&'b mut S)| { @@ -215,8 +218,8 @@ impl LLVMCustomMutator { /// Will create the specified libfuzzer custom mutator `mutate` fn. /// Only safe if the custom mutator implementation is correct. pub unsafe fn mutate(mutator: SM) -> Result { - if libafl_targets_has_libfuzzer_custom_mutator() { - Ok(Self::mutate_unchecked(mutator)) + if unsafe { libafl_targets_has_libfuzzer_custom_mutator() } { + Ok(unsafe { Self::mutate_unchecked(mutator) }) } else { Err(Error::illegal_state( "Cowardly refusing to create a LLVMFuzzerMutator if a custom mutator is not defined.", @@ -244,8 +247,8 @@ impl LLVMCustomMutator { /// Will create the specified libfuzzer custom crossover mutator. /// Only safe if the custom mutator crossover implementation is correct. pub unsafe fn crossover(mutator: SM) -> Result { - if libafl_targets_has_libfuzzer_custom_crossover() { - Ok(Self::crossover_unchecked(mutator)) + if unsafe { libafl_targets_has_libfuzzer_custom_crossover() } { + Ok(unsafe { Self::crossover_unchecked(mutator) }) } else { Err(Error::illegal_state( "Cowardly refusing to create a LLVMFuzzerMutator if a custom crossover is not defined.", @@ -273,11 +276,15 @@ where { type Mutations = SM::Mutations; fn mutations(&self) -> &Self::Mutations { - unimplemented!("It is unsafe to provide reference-based access to the mutators as they are behind a RefCell.") + unimplemented!( + "It is unsafe to provide reference-based access to the mutators as they are behind a RefCell." + ) } fn mutations_mut(&mut self) -> &mut Self::Mutations { - unimplemented!("It is unsafe to provide reference-based access to the mutators as they are behind a RefCell.") + unimplemented!( + "It is unsafe to provide reference-based access to the mutators as they are behind a RefCell." + ) } } @@ -351,7 +358,9 @@ where } if new_len > max_len { - return Err(Error::illegal_state(format!("LLVMFuzzerCustomMutator returned more bytes than allowed. Expected up to {max_len} but got {new_len}"))); + return Err(Error::illegal_state(format!( + "LLVMFuzzerCustomMutator returned more bytes than allowed. Expected up to {max_len} but got {new_len}" + ))); } input.resize(new_len, 0); Ok(MutationResult::Mutated) @@ -447,7 +456,9 @@ where } if new_len > max_len { - return Err(Error::illegal_state(format!("LLVMFuzzerCustomCrossOver returned more bytes than allowed. Expected up to {max_len} but got {new_len}"))); + return Err(Error::illegal_state(format!( + "LLVMFuzzerCustomCrossOver returned more bytes than allowed. Expected up to {max_len} but got {new_len}" + ))); } input.resize(new_len, 0); diff --git a/libafl_targets/src/libfuzzer/observers/oom.rs b/libafl_targets/src/libfuzzer/observers/oom.rs index 35d59d511d..ff3701ff6c 100644 --- a/libafl_targets/src/libfuzzer/observers/oom.rs +++ b/libafl_targets/src/libfuzzer/observers/oom.rs @@ -3,16 +3,16 @@ use core::{ffi::c_void, fmt::Debug}; use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; use libafl::{ + Error, executors::ExitKind, feedbacks::{Feedback, StateInitializer}, observers::Observer, - Error, }; use libafl_bolts::Named; use libc::SIGABRT; use serde::{Deserialize, Serialize}; -extern "C" { +unsafe extern "C" { fn libafl_check_malloc_size(ptr: *const c_void) -> usize; } @@ -29,7 +29,7 @@ static MALLOC_SIZE: AtomicUsize = AtomicUsize::new(0); /// /// # Safety /// Is only safe to call with valid freshly allocated pointers backed by allocations of `size`. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn __sanitizer_malloc_hook(ptr: *const c_void, size: usize) { if RUNNING.load(Ordering::Relaxed) { let size = match unsafe { libafl_check_malloc_size(ptr) } { @@ -54,7 +54,7 @@ pub unsafe extern "C" fn __sanitizer_malloc_hook(ptr: *const c_void, size: usize /// /// # Safety /// Is only safe to call with valid allocated pointers, about to be freed. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn __sanitizer_free_hook(ptr: *const c_void) { if RUNNING.load(Ordering::Relaxed) { let size = unsafe { libafl_check_malloc_size(ptr) }; diff --git a/libafl_targets/src/sancov_8bit.rs b/libafl_targets/src/sancov_8bit.rs index e15f311a4c..e44a41dfbe 100644 --- a/libafl_targets/src/sancov_8bit.rs +++ b/libafl_targets/src/sancov_8bit.rs @@ -1,19 +1,25 @@ //! [`LLVM` `8-bit-counters`](https://clang.llvm.org/docs/SanitizerCoverage.html#tracing-pcs-with-guards) runtime for `LibAFL`. use alloc::vec::Vec; -use libafl_bolts::{ownedref::OwnedMutSlice, AsSlice, AsSliceMut}; +use libafl_bolts::{AsSlice, AsSliceMut, ownedref::OwnedMutSlice}; /// A [`Vec`] of `8-bit-counters` maps for multiple modules. /// They are initialized by calling [`__sanitizer_cov_8bit_counters_init`]( pub static mut COUNTERS_MAPS: Vec> = Vec::new(); -/// Gets a pointer to [`COUNTER_MAPS`] -fn counter_maps_ptr() -> *const Vec> { +/// Gets a pointer to [`COUNTERS_MAPS`] +/// +/// # Safety +/// The resulting pointer points to a global. Handle with care! +pub unsafe fn counters_maps_ptr() -> *const Vec> { &raw const COUNTERS_MAPS } -/// Gets a pointer to [`COUNTER_MAPS`], mut -fn counter_maps_ptr_mut() -> *mut Vec> { +/// Gets a pointer to [`COUNTERS_MAPS`], mut +/// +/// # Safety +/// The resulting pointer points to a global. Handle with care! +pub unsafe fn counters_maps_ptr_mut() -> *mut Vec> { &raw mut COUNTERS_MAPS } @@ -23,10 +29,10 @@ fn counter_maps_ptr_mut() -> *mut Vec> { /// You are responsible for ensuring there is no multi-mutability! #[must_use] pub unsafe fn extra_counters() -> Vec> { - let counter_maps = &*counter_maps_ptr(); + let counter_maps = unsafe { &*counters_maps_ptr() }; counter_maps .iter() - .map(|counters| { + .map(|counters| unsafe { OwnedMutSlice::from_raw_parts_mut( counters.as_slice().as_ptr().cast_mut(), counters.as_slice().len(), @@ -39,11 +45,11 @@ pub unsafe fn extra_counters() -> Vec> { /// /// # Safety /// Start and stop are being dereferenced. -#[no_mangle] +#[unsafe(no_mangle)] #[expect(clippy::cast_sign_loss)] pub unsafe extern "C" fn __sanitizer_cov_8bit_counters_init(start: *mut u8, stop: *mut u8) { unsafe { - let counter_maps = &mut *counter_maps_ptr_mut(); + let counter_maps = &mut *counters_maps_ptr_mut(); for existing in counter_maps { let range = existing.as_slice_mut().as_mut_ptr() ..=existing @@ -60,7 +66,7 @@ pub unsafe extern "C" fn __sanitizer_cov_8bit_counters_init(start: *mut u8, stop } } - let counter_maps = &mut *counter_maps_ptr_mut(); + let counter_maps = &mut *counters_maps_ptr_mut(); // we didn't overlap; keep going counter_maps.push(OwnedMutSlice::from_raw_parts_mut( start, @@ -70,7 +76,7 @@ pub unsafe extern "C" fn __sanitizer_cov_8bit_counters_init(start: *mut u8, stop } #[cfg(feature = "observers")] -pub use self::observers::{counters_maps_observer, CountersMultiMapObserver}; +pub use self::observers::{CountersMultiMapObserver, counters_maps_observer}; #[cfg(feature = "observers")] mod observers { @@ -80,23 +86,23 @@ mod observers { hash::{Hash, Hasher}, iter::Flatten, mem::size_of, - slice::{from_raw_parts, Iter, IterMut}, + slice::{Iter, IterMut, from_raw_parts}, }; use libafl::{ - observers::{DifferentialObserver, MapObserver, Observer}, Error, + observers::{DifferentialObserver, MapObserver, Observer}, }; use libafl_bolts::{ - ownedref::OwnedMutSlice, AsIter, AsIterMut, AsSlice, AsSliceMut, HasLen, Named, + AsIter, AsIterMut, AsSlice, AsSliceMut, HasLen, Named, ownedref::OwnedMutSlice, }; use meminterval::IntervalTree; use serde::{Deserialize, Serialize}; - use super::{counter_maps_ptr, counter_maps_ptr_mut}; + use super::{counters_maps_ptr, counters_maps_ptr_mut}; #[must_use] - #[export_name = "counters_maps_observer"] + #[unsafe(export_name = "counters_maps_observer")] /// Create a new [`CountersMultiMapObserver`] of the [`super::COUNTERS_MAPS`]. /// /// This is a special [`libafl::observers::MultiMapObserver`] for the [`super::COUNTERS_MAPS`] and may be used when @@ -169,7 +175,7 @@ mod observers { impl Hash for CountersMultiMapObserver { fn hash(&self, hasher: &mut H) { - for map in unsafe { &*counter_maps_ptr() } { + for map in unsafe { &*counters_maps_ptr() } { let slice = map.as_slice(); let ptr = slice.as_ptr(); let map_size = slice.len() / size_of::(); @@ -200,7 +206,7 @@ mod observers { let elem = self.intervals.query(idx..=idx).next().unwrap(); let i = elem.value; let j = idx - elem.interval.start; - unsafe { (*counter_maps_ptr())[*i].as_slice()[j] } + unsafe { (*counters_maps_ptr())[*i].as_slice()[j] } } #[inline] @@ -208,7 +214,7 @@ mod observers { let elem = self.intervals.query_mut(idx..=idx).next().unwrap(); let i = elem.value; let j = idx - elem.interval.start; - unsafe { (*counter_maps_ptr_mut())[*i].as_slice_mut()[j] = val }; + unsafe { (*counters_maps_ptr_mut())[*i].as_slice_mut()[j] = val }; } #[inline] @@ -219,7 +225,7 @@ mod observers { fn count_bytes(&self) -> u64 { let initial = self.initial(); let mut res = 0; - for map in unsafe { &*counter_maps_ptr() } { + for map in unsafe { &*counters_maps_ptr() } { for x in map.as_slice() { if *x != initial { res += 1; @@ -231,7 +237,7 @@ mod observers { fn reset_map(&mut self) -> Result<(), Error> { let initial = self.initial(); - for map in unsafe { &mut *counter_maps_ptr_mut() } { + for map in unsafe { &mut *counters_maps_ptr_mut() } { for x in map.as_slice_mut() { *x = initial; } @@ -272,7 +278,7 @@ mod observers { fn maybe_differential(name: &'static str) -> Self { let mut idx = 0; let mut intervals = IntervalTree::new(); - for (v, x) in unsafe { &*counter_maps_ptr() }.iter().enumerate() { + for (v, x) in unsafe { &*counters_maps_ptr() }.iter().enumerate() { let l = x.as_slice().len(); intervals.insert(idx..(idx + l), v); idx += l; @@ -308,7 +314,7 @@ mod observers { let mut idx = 0; let mut v = 0; let mut intervals = IntervalTree::new(); - unsafe { &mut *counter_maps_ptr_mut() } + unsafe { &mut *counters_maps_ptr_mut() } .iter_mut() .for_each(|m| { let l = m.as_slice_mut().len(); @@ -333,7 +339,7 @@ mod observers { fn as_iter(&'it self) -> Self::IntoIter { unsafe { - let counters_maps = &*counter_maps_ptr(); + let counters_maps = &*counters_maps_ptr(); counters_maps.iter().flatten() } } @@ -345,7 +351,7 @@ mod observers { fn as_iter_mut(&'it mut self) -> Self::IntoIterMut { unsafe { - let counters_maps = &mut *counter_maps_ptr_mut(); + let counters_maps = &mut *counters_maps_ptr_mut(); counters_maps.iter_mut().flatten() } } @@ -356,7 +362,7 @@ mod observers { type IntoIter = Flatten>>; fn into_iter(self) -> Self::IntoIter { - unsafe { &*counter_maps_ptr() }.iter().flatten() + unsafe { &*counters_maps_ptr() }.iter().flatten() } } @@ -367,7 +373,9 @@ mod observers { type IntoIter = Flatten>>; fn into_iter(self) -> Self::IntoIter { - unsafe { &mut *counter_maps_ptr_mut() }.iter_mut().flatten() + unsafe { &mut *counters_maps_ptr_mut() } + .iter_mut() + .flatten() } } diff --git a/libafl_targets/src/sancov_cmp.rs b/libafl_targets/src/sancov_cmp.rs index 3cd796dd58..fc923efd0f 100644 --- a/libafl_targets/src/sancov_cmp.rs +++ b/libafl_targets/src/sancov_cmp.rs @@ -8,7 +8,7 @@ use core::{ use crate::CMPLOG_MAP_W; -extern "C" { +unsafe extern "C" { /// Trace an 8 bit `cmp` pub fn __sanitizer_cov_trace_cmp1(v0: u8, v1: u8); @@ -38,7 +38,7 @@ extern "C" { /// overriding `__sanitizer_weak_hook_memcmp` /// # Safety /// this function has raw pointer access -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn __sanitizer_weak_hook_memcmp( called_pc: *const c_void, s1: *const c_void, @@ -46,16 +46,24 @@ pub unsafe extern "C" fn __sanitizer_weak_hook_memcmp( n: usize, result: c_int, ) { - if result != 0 { - let k: usize = called_pc as usize; - let k = (k >> 4) ^ (k << 8); - let k = k & (CMPLOG_MAP_W - 1); - __libafl_targets_cmplog_routines_len(k, s1 as *const u8, s2 as *const u8, cmp::min(n, 32)); + unsafe { + if result != 0 { + let k: usize = called_pc as usize; + let k = (k >> 4) ^ (k << 8); + let k = k & (CMPLOG_MAP_W - 1); + __libafl_targets_cmplog_routines_len( + k, + s1 as *const u8, + s2 as *const u8, + cmp::min(n, 32), + ); + } } } -#[no_mangle] +#[unsafe(no_mangle)] /// overriding `__sanitizer_weak_hook_strncmp` +/// /// # Safety /// this function has raw pointer access pub unsafe extern "C" fn __sanitizer_weak_hook_strncmp( @@ -65,26 +73,28 @@ pub unsafe extern "C" fn __sanitizer_weak_hook_strncmp( n: usize, result: c_int, ) { - if result != 0 { - let n = cmp::min(n, 32); - let k: usize = called_pc as usize; - let k = (k >> 4) ^ (k << 8); - let k = k & (CMPLOG_MAP_W - 1); - let mut actual_len = 0; - while actual_len < n { - let c1 = ptr::read(s1.add(actual_len)); - let c2 = ptr::read(s2.add(actual_len)); + unsafe { + if result != 0 { + let n = cmp::min(n, 32); + let k: usize = called_pc as usize; + let k = (k >> 4) ^ (k << 8); + let k = k & (CMPLOG_MAP_W - 1); + let mut actual_len = 0; + while actual_len < n { + let c1 = ptr::read(s1.add(actual_len)); + let c2 = ptr::read(s2.add(actual_len)); - if c1 == 0 || c2 == 0 { - break; + if c1 == 0 || c2 == 0 { + break; + } + actual_len += 1; } - actual_len += 1; + __libafl_targets_cmplog_routines_len(k, s1 as *const u8, s2 as *const u8, actual_len); } - __libafl_targets_cmplog_routines_len(k, s1 as *const u8, s2 as *const u8, actual_len); } } -#[no_mangle] +#[unsafe(no_mangle)] /// overriding `__sanitizer_weak_hook_strncasecmps` /// # Safety /// this function has raw pointer access @@ -95,10 +105,12 @@ pub unsafe extern "C" fn __sanitizer_weak_hook_strncasecmp( n: usize, result: c_int, ) { - __sanitizer_weak_hook_strncmp(called_pc, s1, s2, n, result); + unsafe { + __sanitizer_weak_hook_strncmp(called_pc, s1, s2, n, result); + } } -#[no_mangle] +#[unsafe(no_mangle)] /// overriding `__sanitizer_weak_hook_strcmp` /// # Safety /// this function has raw pointer access @@ -108,25 +120,27 @@ pub unsafe extern "C" fn __sanitizer_weak_hook_strcmp( s2: *const c_char, result: c_int, ) { - if result != 0 { - let k: usize = called_pc as usize; - let k = (k >> 4) ^ (k << 8); - let k = k & (CMPLOG_MAP_W - 1); - let mut actual_len = 0; - while actual_len < 32 { - let c1 = ptr::read(s1.add(actual_len)); - let c2 = ptr::read(s2.add(actual_len)); + unsafe { + if result != 0 { + let k: usize = called_pc as usize; + let k = (k >> 4) ^ (k << 8); + let k = k & (CMPLOG_MAP_W - 1); + let mut actual_len = 0; + while actual_len < 32 { + let c1 = ptr::read(s1.add(actual_len)); + let c2 = ptr::read(s2.add(actual_len)); - if c1 == 0 || c2 == 0 { - break; + if c1 == 0 || c2 == 0 { + break; + } + actual_len += 1; } - actual_len += 1; + __libafl_targets_cmplog_routines_len(k, s1 as *const u8, s2 as *const u8, actual_len); } - __libafl_targets_cmplog_routines_len(k, s1 as *const u8, s2 as *const u8, actual_len); } } -#[no_mangle] +#[unsafe(no_mangle)] /// overriding `__sanitizer_weak_hook_strcmp` /// # Safety /// this function has raw pointer access @@ -136,5 +150,7 @@ pub unsafe extern "C" fn __sanitizer_weak_hook_strcasecmp( s2: *const c_char, result: c_int, ) { - __sanitizer_weak_hook_strcmp(called_pc, s1, s2, result); + unsafe { + __sanitizer_weak_hook_strcmp(called_pc, s1, s2, result); + } } diff --git a/libafl_targets/src/sancov_pcguard.rs b/libafl_targets/src/sancov_pcguard.rs index bec95b5f97..4001f71490 100644 --- a/libafl_targets/src/sancov_pcguard.rs +++ b/libafl_targets/src/sancov_pcguard.rs @@ -12,6 +12,9 @@ use core::{mem::align_of, slice}; ))] use libafl::executors::hooks::ExecutorHook; +#[cfg(any(feature = "sancov_ngram4", feature = "sancov_ngram8"))] +#[allow(unused_imports)] // only used in an unused function +use crate::EDGES_MAP_DEFAULT_SIZE; #[cfg(any( feature = "pointer_maps", feature = "sancov_pcguard_edges", @@ -22,11 +25,8 @@ use libafl::executors::hooks::ExecutorHook; ))] use crate::coverage::EDGES_MAP; use crate::coverage::MAX_EDGES_FOUND; -#[cfg(any(feature = "sancov_ngram4", feature = "sancov_ngram8"))] -#[allow(unused_imports)] // only used in an unused function -use crate::EDGES_MAP_DEFAULT_SIZE; #[cfg(feature = "pointer_maps")] -use crate::{coverage::EDGES_MAP_PTR, EDGES_MAP_ALLOCATED_SIZE}; +use crate::{EDGES_MAP_ALLOCATED_SIZE, coverage::EDGES_MAP_PTR}; #[cfg(all(feature = "sancov_pcguard_edges", feature = "sancov_pcguard_hitcounts"))] #[cfg(not(any(doc, feature = "clippy")))] @@ -167,7 +167,9 @@ unsafe fn update_ngram(pos: usize) -> usize { #[cfg(feature = "sancov_ngram4")] { let prev_array_4_ptr = &raw mut PREV_ARRAY_4; - let prev_array_4 = &mut *prev_array_4_ptr; + // # Safety + // the array is valid, this function is called from a single thread. + let prev_array_4 = unsafe { &mut *prev_array_4_ptr }; *prev_array_4 = prev_array_4.rotate_elements_right::<1>(); prev_array_4.shl_assign(SHR_4); prev_array_4.as_mut_array()[0] = pos as u32; @@ -176,7 +178,7 @@ unsafe fn update_ngram(pos: usize) -> usize { #[cfg(feature = "sancov_ngram8")] { let prev_array_8_ptr = &raw mut PREV_ARRAY_8; - let prev_array_8 = &mut *prev_array_8_ptr; + let prev_array_8 = unsafe { &mut *prev_array_8_ptr }; *prev_array_8 = prev_array_8.rotate_elements_right::<1>(); prev_array_8.shl_assign(SHR_8); prev_array_8.as_mut_array()[0] = pos as u32; @@ -192,7 +194,7 @@ unsafe fn update_ngram(pos: usize) -> usize { pos } -extern "C" { +unsafe extern "C" { /// The ctx variable pub static mut __afl_prev_ctx: u32; } @@ -202,50 +204,52 @@ extern "C" { /// # Safety /// Dereferences `guard`, reads the position from there, then dereferences the [`EDGES_MAP`] at that position. /// Should usually not be called directly. -#[no_mangle] +#[unsafe(no_mangle)] #[allow(unused_assignments)] // cfg dependent pub unsafe extern "C" fn __sanitizer_cov_trace_pc_guard(guard: *mut u32) { - #[allow(unused_variables, unused_mut)] // cfg dependent - let mut pos = *guard as usize; + unsafe { + #[allow(unused_variables, unused_mut)] // cfg dependent + let mut pos = *guard as usize; - #[cfg(any(feature = "sancov_ngram4", feature = "sancov_ngram8"))] - { - pos = update_ngram(pos); - // println!("Wrinting to {} {}", pos, EDGES_MAP_DEFAULT_SIZE); - } + #[cfg(any(feature = "sancov_ngram4", feature = "sancov_ngram8"))] + { + pos = update_ngram(pos); + // println!("Wrinting to {} {}", pos, EDGES_MAP_DEFAULT_SIZE); + } - #[cfg(feature = "sancov_ctx")] - { - pos ^= __afl_prev_ctx as usize; - // println!("Wrinting to {} {}", pos, EDGES_MAP_DEFAULT_SIZE); - } + #[cfg(feature = "sancov_ctx")] + { + pos ^= __afl_prev_ctx as usize; + // println!("Wrinting to {} {}", pos, EDGES_MAP_DEFAULT_SIZE); + } - #[cfg(feature = "pointer_maps")] - { - #[cfg(feature = "sancov_pcguard_edges")] + #[cfg(feature = "pointer_maps")] { - EDGES_MAP_PTR.add(pos).write(1); + #[cfg(feature = "sancov_pcguard_edges")] + { + EDGES_MAP_PTR.add(pos).write(1); + } + #[cfg(feature = "sancov_pcguard_hitcounts")] + { + let addr = EDGES_MAP_PTR.add(pos); + let val = addr.read().wrapping_add(1); + addr.write(val); + } } - #[cfg(feature = "sancov_pcguard_hitcounts")] + #[cfg(not(feature = "pointer_maps"))] + #[cfg(any(feature = "sancov_pcguard_hitcounts", feature = "sancov_pcguard_edges"))] { - let addr = EDGES_MAP_PTR.add(pos); - let val = addr.read().wrapping_add(1); - addr.write(val); - } - } - #[cfg(not(feature = "pointer_maps"))] - #[cfg(any(feature = "sancov_pcguard_hitcounts", feature = "sancov_pcguard_edges"))] - { - let edges_map_ptr = &raw mut EDGES_MAP; - let edges_map = &mut *edges_map_ptr; - #[cfg(feature = "sancov_pcguard_edges")] - { - *(edges_map).get_unchecked_mut(pos) = 1; - } - #[cfg(feature = "sancov_pcguard_hitcounts")] - { - let val = (*edges_map.get_unchecked(pos)).wrapping_add(1); - *edges_map.get_unchecked_mut(pos) = val; + let edges_map_ptr = &raw mut EDGES_MAP; + let edges_map = &mut *edges_map_ptr; + #[cfg(feature = "sancov_pcguard_edges")] + { + *(edges_map).get_unchecked_mut(pos) = 1; + } + #[cfg(feature = "sancov_pcguard_hitcounts")] + { + let val = (*edges_map.get_unchecked(pos)).wrapping_add(1); + *edges_map.get_unchecked_mut(pos) = val; + } } } } @@ -254,56 +258,63 @@ pub unsafe extern "C" fn __sanitizer_cov_trace_pc_guard(guard: *mut u32) { /// /// # Safety /// Dereferences at `start` and writes to it. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn __sanitizer_cov_trace_pc_guard_init(mut start: *mut u32, stop: *mut u32) { - #[cfg(feature = "pointer_maps")] - if EDGES_MAP_PTR.is_null() { - EDGES_MAP_PTR = &raw mut EDGES_MAP as *mut u8; - } - - if start == stop || *start != 0 { - return; - } - - while start < stop { - *start = MAX_EDGES_FOUND as u32; - start = start.offset(1); - + unsafe { #[cfg(feature = "pointer_maps")] - { - MAX_EDGES_FOUND = MAX_EDGES_FOUND.wrapping_add(1) % EDGES_MAP_ALLOCATED_SIZE; + if EDGES_MAP_PTR.is_null() { + EDGES_MAP_PTR = &raw mut EDGES_MAP as *mut u8; } - #[cfg(not(feature = "pointer_maps"))] - { - let edges_map_ptr = &raw const EDGES_MAP; - let edges_map_len = (*edges_map_ptr).len(); - MAX_EDGES_FOUND = MAX_EDGES_FOUND.wrapping_add(1); - assert!((MAX_EDGES_FOUND <= edges_map_len), "The number of edges reported by SanitizerCoverage exceed the size of the edges map ({edges_map_len}). Use the LIBAFL_EDGES_MAP_DEFAULT_SIZE env to increase it at compile time."); + + if start == stop || *start != 0 { + return; + } + + while start < stop { + *start = MAX_EDGES_FOUND as u32; + start = start.offset(1); + + #[cfg(feature = "pointer_maps")] + { + MAX_EDGES_FOUND = MAX_EDGES_FOUND.wrapping_add(1) % EDGES_MAP_ALLOCATED_SIZE; + } + #[cfg(not(feature = "pointer_maps"))] + { + let edges_map_ptr = &raw const EDGES_MAP; + let edges_map_len = (*edges_map_ptr).len(); + MAX_EDGES_FOUND = MAX_EDGES_FOUND.wrapping_add(1); + assert!( + (MAX_EDGES_FOUND <= edges_map_len), + "The number of edges reported by SanitizerCoverage exceed the size of the edges map ({edges_map_len}). Use the LIBAFL_EDGES_MAP_DEFAULT_SIZE env to increase it at compile time." + ); + } } } } -#[no_mangle] +#[unsafe(no_mangle)] unsafe extern "C" fn __sanitizer_cov_pcs_init(pcs_beg: *const usize, pcs_end: *const usize) { // "The Unsafe Code Guidelines also notably defines that usize and isize are respectively compatible with uintptr_t and intptr_t defined in C." - let len = pcs_end.offset_from(pcs_beg); - let Ok(len) = usize::try_from(len) else { - panic!("Invalid PC Table bounds - start: {pcs_beg:x?} end: {pcs_end:x?}") - }; - assert_eq!( - len % 2, - 0, - "PC Table size is not evens - start: {pcs_beg:x?} end: {pcs_end:x?}" - ); - assert_eq!( - (pcs_beg as usize) % align_of::(), - 0, - "Unaligned PC Table - start: {pcs_beg:x?} end: {pcs_end:x?}" - ); + unsafe { + let len = pcs_end.offset_from(pcs_beg); + let Ok(len) = usize::try_from(len) else { + panic!("Invalid PC Table bounds - start: {pcs_beg:x?} end: {pcs_end:x?}") + }; + assert_eq!( + len % 2, + 0, + "PC Table size is not evens - start: {pcs_beg:x?} end: {pcs_end:x?}" + ); + assert_eq!( + (pcs_beg as usize) % align_of::(), + 0, + "Unaligned PC Table - start: {pcs_beg:x?} end: {pcs_end:x?}" + ); - let pc_tables_ptr = &raw mut PC_TABLES; - let pc_tables = &mut *pc_tables_ptr; - pc_tables.push(slice::from_raw_parts(pcs_beg as *const PcTableEntry, len)); + let pc_tables_ptr = &raw mut PC_TABLES; + let pc_tables = &mut *pc_tables_ptr; + pc_tables.push(slice::from_raw_parts(pcs_beg as *const PcTableEntry, len)); + } } /// An entry to the `sanitizer_cov` `pc_table` diff --git a/libafl_targets/src/value_profile.rs b/libafl_targets/src/value_profile.rs index 66121db89a..a1f37af05a 100644 --- a/libafl_targets/src/value_profile.rs +++ b/libafl_targets/src/value_profile.rs @@ -3,7 +3,7 @@ use crate::CMP_MAP_SIZE; /// The constant cmplog map for the current `LibAFL` target -#[no_mangle] +#[unsafe(no_mangle)] pub static mut libafl_cmp_map: [u8; CMP_MAP_SIZE] = [0; CMP_MAP_SIZE]; pub use libafl_cmp_map as CMP_MAP; @@ -14,7 +14,7 @@ extern { fn return_address() -> usize; } -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn __sanitizer_cov_trace_cmp1(arg1: u8, arg2: u8) { let mut pos = return_address(); pos = (pos >> 4) ^ (pos << 8); diff --git a/libafl_targets/src/windows_asan.rs b/libafl_targets/src/windows_asan.rs index 561d90ea7c..f93f40f099 100644 --- a/libafl_targets/src/windows_asan.rs +++ b/libafl_targets/src/windows_asan.rs @@ -1,19 +1,19 @@ //! Setup asan death callbback use libafl::{ + HasObjective, events::{EventFirer, EventRestarter}, - executors::{hooks::windows::windows_asan_handler::asan_death_handler, Executor, HasObservers}, + executors::{Executor, HasObservers, hooks::windows::windows_asan_handler::asan_death_handler}, feedbacks::Feedback, inputs::Input, observers::ObserversTuple, state::{HasCurrentTestcase, HasExecutions, HasSolutions}, - HasObjective, }; /// Asan death callback type pub type CB = unsafe extern "C" fn() -> (); -extern "C" { +unsafe extern "C" { fn __sanitizer_set_death_callback(cb: Option); } @@ -39,5 +39,7 @@ where Z: HasObjective, I: Input + Clone, { - __sanitizer_set_death_callback(Some(asan_death_handler::)); + unsafe { + __sanitizer_set_death_callback(Some(asan_death_handler::)); + } } diff --git a/libafl_tinyinst/Cargo.toml b/libafl_tinyinst/Cargo.toml index 86565f6bd7..2ef0d9873e 100644 --- a/libafl_tinyinst/Cargo.toml +++ b/libafl_tinyinst/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "libafl_tinyinst" version.workspace = true -edition = "2021" +edition = "2024" authors = [ "elbiazo ", "Dongjia Zhang ", diff --git a/libafl_tinyinst/src/executor.rs b/libafl_tinyinst/src/executor.rs index 871f7d258b..84f261dcde 100644 --- a/libafl_tinyinst/src/executor.rs +++ b/libafl_tinyinst/src/executor.rs @@ -2,18 +2,18 @@ use core::{marker::PhantomData, ptr, time::Duration}; use std::fmt::{Debug, Formatter}; use libafl::{ + Error, executors::{Executor, ExitKind, HasObservers}, inputs::HasTargetBytes, state::HasExecutions, - Error, }; use libafl_bolts::{ - fs::{InputFile, INPUTFILE_STD}, + AsSlice, AsSliceMut, + fs::{INPUTFILE_STD, InputFile}, shmem::{NopShMem, NopShMemProvider, ShMem, ShMemProvider}, tuples::RefIndexable, - AsSlice, AsSliceMut, }; -use tinyinst::tinyinst::{litecov::RunResult, TinyInst}; +use tinyinst::tinyinst::{TinyInst, litecov::RunResult}; /// [`TinyInst`](https://github.com/googleprojectzero/TinyInst) executor pub struct TinyInstExecutor { diff --git a/libafl_unicorn/Cargo.toml b/libafl_unicorn/Cargo.toml index 3f9cab69a6..32c2e6847e 100644 --- a/libafl_unicorn/Cargo.toml +++ b/libafl_unicorn/Cargo.toml @@ -8,7 +8,7 @@ repository = "https://github.com/AFLplusplus/" readme = "../README.md" license = "MIT OR Apache-2.0" keywords = ["fuzzing", "unicorn"] -edition = "2021" +edition = "2024" categories = [ "development-tools::testing", "emulators", diff --git a/libafl_unicorn/src/emu.rs b/libafl_unicorn/src/emu.rs index ade935fe29..f2e67f640b 100644 --- a/libafl_unicorn/src/emu.rs +++ b/libafl_unicorn/src/emu.rs @@ -1,11 +1,11 @@ use capstone::{ - arch::{self, BuildsCapstone, BuildsCapstoneSyntax}, Capstone, + arch::{self, BuildsCapstone, BuildsCapstoneSyntax}, }; pub use libafl_targets::{EDGES_MAP, EDGES_MAP_PTR}; use unicorn_engine::{ - unicorn_const::{Arch, Permission}, RegisterARM, RegisterARM64, RegisterX86, Unicorn, + unicorn_const::{Arch, Permission}, }; use crate::helper::get_stack_pointer; diff --git a/libafl_unicorn/src/helper.rs b/libafl_unicorn/src/helper.rs index 3fbe8fa6c1..45e8379778 100644 --- a/libafl_unicorn/src/helper.rs +++ b/libafl_unicorn/src/helper.rs @@ -1,4 +1,4 @@ -use unicorn_engine::{unicorn_const::Arch, RegisterARM, RegisterARM64, RegisterX86}; +use unicorn_engine::{RegisterARM, RegisterARM64, RegisterX86, unicorn_const::Arch}; pub fn get_stack_pointer(emu: &unicorn_engine::Unicorn<()>) -> u64 { match emu.get_arch() { diff --git a/utils/build_and_test_fuzzers/Cargo.toml b/utils/build_and_test_fuzzers/Cargo.toml index 379a09888c..f4d8be987b 100644 --- a/utils/build_and_test_fuzzers/Cargo.toml +++ b/utils/build_and_test_fuzzers/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "build_and_test_fuzzers" version.workspace = true -edition = "2021" +edition = "2024" description = "Get diffing fuzzers from the last commit" repository = "https://github.com/AFLplusplus/LibAFL/" license = "MIT OR Apache-2.0" diff --git a/utils/deexit/Cargo.toml b/utils/deexit/Cargo.toml index 092fd52467..5f8a94d0b8 100644 --- a/utils/deexit/Cargo.toml +++ b/utils/deexit/Cargo.toml @@ -5,7 +5,7 @@ authors = [ ] name = "deexit" version.workspace = true -edition = "2021" +edition = "2024" description = "DeExit: Replace exits with aborts to catch them during in-process fuzzing" documentation = "https://docs.rs/libafl" repository = "https://github.com/AFLplusplus/LibAFL/" diff --git a/utils/deexit/src/lib.rs b/utils/deexit/src/lib.rs index 53e88a5e58..ed38dffa39 100644 --- a/utils/deexit/src/lib.rs +++ b/utils/deexit/src/lib.rs @@ -2,12 +2,12 @@ //! If you are on `MacOS`, use the env variables `DYLD_FORCE_FLAT_NAMESPACE=1 DYLD_INSERT_LIBRARIES="path/to/target/release/libdeexit.dylib" tool` //! On Linux, use `LD_PRELOAD="path/to/target/release/libdeexit.so" tool`. -extern "C" { +unsafe extern "C" { fn abort(); } /// Hooked `exit` function -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn exit(status: i32) { println!("DeExit: The target called exit with status code {status}"); unsafe { diff --git a/utils/desyscall/Cargo.toml b/utils/desyscall/Cargo.toml index 0a39ca5284..ec32f289e6 100644 --- a/utils/desyscall/Cargo.toml +++ b/utils/desyscall/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "desyscall" version = "0.15.1" -edition = "2021" +edition = "2024" description = "DeSyscall: Hooks syscalls for reduces overhead during in-process fuzzing" repository = "https://github.com/AFLplusplus/LibAFL/" license = "MIT OR Apache-2.0" diff --git a/utils/desyscall/src/file.rs b/utils/desyscall/src/file.rs index 9a0ffaa17e..088025f24a 100644 --- a/utils/desyscall/src/file.rs +++ b/utils/desyscall/src/file.rs @@ -2,7 +2,7 @@ use libc::{c_int, size_t, ssize_t}; use crate::{Context, Pointer}; -extern "C" { +unsafe extern "C" { // ssize_t __libafl_raw_write(int fd, const void *buf, size_t count); fn __libafl_raw_write(fd: c_int, buf: Pointer, count: size_t) -> ssize_t; // ssize_t __libafl_raw_read(int fd, void *buf, size_t count) @@ -12,7 +12,7 @@ extern "C" { /// # Safety /// Call to functions using syscalls #[expect(clippy::cast_possible_wrap)] -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn write(fd: c_int, buf: Pointer, count: size_t) -> ssize_t { let ctx = Context::get(); @@ -25,7 +25,7 @@ pub unsafe extern "C" fn write(fd: c_int, buf: Pointer, count: size_t) -> ssize_ /// # Safety /// Call to functions using syscalls -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn read(fd: c_int, buf: Pointer, count: size_t) -> ssize_t { let ctx = Context::get(); diff --git a/utils/desyscall/src/lib.rs b/utils/desyscall/src/lib.rs index d8ba74e37a..614e62c66f 100644 --- a/utils/desyscall/src/lib.rs +++ b/utils/desyscall/src/lib.rs @@ -87,14 +87,14 @@ impl Context { } #[cfg(target_os = "linux")] -extern "C" { +unsafe extern "C" { fn __libafl_raw_exit_group(status: c_int); } // void _exit(int status); /// # Safety /// Call to function using syscalls -#[no_mangle] +#[unsafe(no_mangle)] #[cfg(target_os = "linux")] pub unsafe extern "C" fn _exit(status: c_int) { let ctx = Context::get(); diff --git a/utils/desyscall/src/mmap.rs b/utils/desyscall/src/mmap.rs index f101ec18e7..898646c272 100644 --- a/utils/desyscall/src/mmap.rs +++ b/utils/desyscall/src/mmap.rs @@ -9,7 +9,7 @@ use crate::{Context, Mapping, Pointer}; const PAGE_SIZE: usize = 4096; -extern "C" { +unsafe extern "C" { //void* __libafl_raw_mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); fn __libafl_raw_mmap( addr: *mut c_void, @@ -41,7 +41,7 @@ extern "C" { /// # Safety /// Call to functions using syscalls -#[no_mangle] +#[unsafe(no_mangle)] #[expect(clippy::too_many_lines)] #[cfg(not(windows))] pub unsafe extern "C" fn mmap( @@ -227,7 +227,7 @@ pub unsafe extern "C" fn mmap( /// # Safety /// Call to functions using syscalls -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn munmap(addr: *mut c_void, length: size_t) -> c_int { let ctx = Context::get(); @@ -318,7 +318,7 @@ pub unsafe extern "C" fn munmap(addr: *mut c_void, length: size_t) -> c_int { /// # Safety /// Calling to functions using syscalls -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn mprotect(addr: *mut c_void, length: size_t, prot: c_int) -> c_int { let ctx = Context::get(); @@ -443,7 +443,7 @@ pub unsafe extern "C" fn mprotect(addr: *mut c_void, length: size_t, prot: c_int /// # Safety /// Call to functions using syscalls -#[no_mangle] +#[unsafe(no_mangle)] #[cfg(not(windows))] pub unsafe extern "C" fn madvise(addr: *mut c_void, length: size_t, advice: c_int) -> c_int { let ctx = Context::get(); diff --git a/utils/drcov_utils/Cargo.toml b/utils/drcov_utils/Cargo.toml index ab635e185c..5394fceed9 100644 --- a/utils/drcov_utils/Cargo.toml +++ b/utils/drcov_utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "drcov_utils" -edition = "2021" +edition = "2024" version.workspace = true description = "Utility functions to work with DrCov coverage files" repository = "https://github.com/AFLplusplus/LibAFL/" diff --git a/utils/drcov_utils/src/bin/drcov_dump_addrs.rs b/utils/drcov_utils/src/bin/drcov_dump_addrs.rs index 121fc20b99..28a4e7ad6c 100644 --- a/utils/drcov_utils/src/bin/drcov_dump_addrs.rs +++ b/utils/drcov_utils/src/bin/drcov_dump_addrs.rs @@ -1,5 +1,5 @@ use std::{ - fs::{create_dir_all, File}, + fs::{File, create_dir_all}, io::Write, path::PathBuf, }; diff --git a/utils/gdb_qemu/gdb_demo/Cargo.toml b/utils/gdb_qemu/gdb_demo/Cargo.toml index d43fed6f8e..985a9bb434 100644 --- a/utils/gdb_qemu/gdb_demo/Cargo.toml +++ b/utils/gdb_qemu/gdb_demo/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "gdb_demo" version = "0.15.1" -edition = "2021" +edition = "2024" [build-dependencies] vergen = { version = "8.1.1", features = [ diff --git a/utils/gdb_qemu/gdb_demo/src/main.rs b/utils/gdb_qemu/gdb_demo/src/main.rs index 445dbe62c3..821edcf746 100644 --- a/utils/gdb_qemu/gdb_demo/src/main.rs +++ b/utils/gdb_qemu/gdb_demo/src/main.rs @@ -6,7 +6,7 @@ use clap::Parser; use crate::args::Args; -#[no_mangle] +#[unsafe(no_mangle)] extern "C" fn run_test(num: usize) { println!("OUT - test: {num:}"); if num & 1 == 0 { @@ -14,7 +14,7 @@ extern "C" fn run_test(num: usize) { } } -#[no_mangle] +#[unsafe(no_mangle)] extern "C" fn test(num: usize) { for i in 0..num { run_test(i); diff --git a/utils/gdb_qemu/gdb_qemu/Cargo.toml b/utils/gdb_qemu/gdb_qemu/Cargo.toml index 67dd350c7a..c27b638e61 100644 --- a/utils/gdb_qemu/gdb_qemu/Cargo.toml +++ b/utils/gdb_qemu/gdb_qemu/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "gdb_qemu" version = "0.15.1" -edition = "2021" +edition = "2024" [build-dependencies] vergen = { version = "8.1.1", features = [ diff --git a/utils/gramatron/construct_automata/Cargo.toml b/utils/gramatron/construct_automata/Cargo.toml index d43563fd11..18ca9f3f41 100644 --- a/utils/gramatron/construct_automata/Cargo.toml +++ b/utils/gramatron/construct_automata/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "construct_automata" version.workspace = true -edition = "2021" +edition = "2024" authors = [ "Andrea Fioraldi ", "Dominik Maier ", diff --git a/utils/libafl_benches/Cargo.toml b/utils/libafl_benches/Cargo.toml index c55b83db8a..82d5c5d3ef 100644 --- a/utils/libafl_benches/Cargo.toml +++ b/utils/libafl_benches/Cargo.toml @@ -5,7 +5,7 @@ authors = [ ] name = "libafl_benches" version.workspace = true -edition = "2021" +edition = "2024" description = "LibAFL Benchmarks" documentation = "https://docs.rs/libafl" repository = "https://github.com/AFLplusplus/LibAFL/" diff --git a/utils/libafl_benches/benches/hash_speeds.rs b/utils/libafl_benches/benches/hash_speeds.rs index a929a6a51e..527118aa22 100644 --- a/utils/libafl_benches/benches/hash_speeds.rs +++ b/utils/libafl_benches/benches/hash_speeds.rs @@ -5,7 +5,7 @@ use std::{ num::NonZero, }; -use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use criterion::{Criterion, black_box, criterion_group, criterion_main}; use libafl_bolts::rands::{Rand, StdRand}; //use xxhash_rust::const_xxh3; use xxhash_rust::xxh3; diff --git a/utils/libafl_benches/benches/rand_speeds.rs b/utils/libafl_benches/benches/rand_speeds.rs index 378fb09ff8..5a85894854 100644 --- a/utils/libafl_benches/benches/rand_speeds.rs +++ b/utils/libafl_benches/benches/rand_speeds.rs @@ -1,6 +1,6 @@ //! Compare the speed of rand implementations -use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use criterion::{Criterion, black_box, criterion_group, criterion_main}; use libafl_bolts::rands::{ Lehmer64Rand, Rand, RomuDuoJrRand, RomuTrioRand, Sfc64Rand, XorShift64Rand, Xoshiro256PlusPlusRand, diff --git a/utils/libafl_fmt/Cargo.toml b/utils/libafl_fmt/Cargo.toml index 10fcbb15d8..d18700cb5c 100644 --- a/utils/libafl_fmt/Cargo.toml +++ b/utils/libafl_fmt/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "libafl_fmt" version = "0.15.1" -edition = "2021" +edition = "2024" description = "Format the LibAFL repository" authors = ["Romain Malmain "] license = "MIT OR Apache-2.0" diff --git a/utils/libafl_fmt/src/main.rs b/utils/libafl_fmt/src/main.rs index 7429c6efb3..293510dd82 100644 --- a/utils/libafl_fmt/src/main.rs +++ b/utils/libafl_fmt/src/main.rs @@ -138,7 +138,8 @@ async fn run_cargo_fmt(cargo_file_path: PathBuf, is_check: bool, verbose: bool) return Err(io::Error::new( ErrorKind::Other, format!( - "Cargo fmt failed. Run cargo fmt for {cargo_file_path:#?}.\nstdout: {stdout}\nstderr: {stderr}\ncommand: {fmt_command:?}"), + "Cargo fmt failed. Run cargo fmt for {cargo_file_path:#?}.\nstdout: {stdout}\nstderr: {stderr}\ncommand: {fmt_command:?}" + ), )); } diff --git a/utils/libafl_jumper/Cargo.toml b/utils/libafl_jumper/Cargo.toml index 0d29ce9476..a90e993ead 100644 --- a/utils/libafl_jumper/Cargo.toml +++ b/utils/libafl_jumper/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libafl_jumper" -edition = "2021" +edition = "2024" version.workspace = true description = "LibAFL_Jumper: Jump to any address in memory." repository = "https://github.com/AFLplusplus/LibAFL/" diff --git a/utils/libafl_jumper/src/main.rs b/utils/libafl_jumper/src/main.rs index c0507de0ec..2d9c75724b 100644 --- a/utils/libafl_jumper/src/main.rs +++ b/utils/libafl_jumper/src/main.rs @@ -25,7 +25,7 @@ fn panic(_panic: &PanicInfo<'_>) -> ! { /// /// Man ALL IS LOŚ͖̩͇̗̪̏̈́T ALL I​S LOST the pon̷y he comes he c̶̮omes he comes the ich​or permeates all MY FACE MY FACE ᵒh god no NO NOO̼O​O NΘ stop the an​*̶͑̾̾​̅ͫ͏̙̤g͇̫͛͆̾ͫ̑͆l͖͉̗̩̳̟̍ͫͥͨe̠̅s ͎a̧͈͖r̽̾̈́͒͑e n​ot rè̑ͧ̌aͨl̘̝̙̃ͤ͂̾̆ ZA̡͊͠͝LGΌ ISͮ̂҉̯͈͕̹̘̱ TO͇̹̺ͅƝ̴ȳ̳ TH̘Ë͖́̉ ͠P̯͍̭O̚​N̐Y̡ H̸̡̪̯ͨ͊̽̅̾̎Ȩ̬̩̾͛ͪ̈́̀́͘ ̶̧̨̱̹̭̯ͧ̾ͬC̷̙̲̝͖ͭ̏ͥͮ͟Oͮ͏̮̪̝͍M̲̖͊̒ͪͩͬ̚̚͜Ȇ̴̟̟͙̞ͩ͌͝S̨̥̫͎̭ͯ̿̔̀ͅ #[inline(never)] -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn libafl_jmp(target: *mut c_void) -> ! { #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] asm!( @@ -97,7 +97,7 @@ fn main() { /// Main for `no_std` - that's the one we will use inside LibAFL_QEMU. #[cfg(not(feature = "std"))] -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn main(argc: i32, argv: *const *const u8) -> ! { if argc < 2 || argv.is_null() { // No params - nothing we can do. @@ -140,7 +140,7 @@ fn decode_hex_and_jmp(hex_string: &str) -> ! { #[cfg(test)] mod test { - extern "C" { + unsafe extern "C" { fn exit(ret: i32); } diff --git a/utils/multi_machine_generator/Cargo.toml b/utils/multi_machine_generator/Cargo.toml index 626fd4c31b..fb94d5371a 100644 --- a/utils/multi_machine_generator/Cargo.toml +++ b/utils/multi_machine_generator/Cargo.toml @@ -5,7 +5,7 @@ version = "0.15.1" description = "Generator for multi-machine setup" license = "MIT OR Apache-2.0" keywords = ["fuzzing", "testing", "security"] -edition = "2021" +edition = "2024" [dependencies] petgraph = "0.6" diff --git a/utils/multi_machine_generator/src/graph.rs b/utils/multi_machine_generator/src/graph.rs index f65703f2cf..98de0b44b8 100644 --- a/utils/multi_machine_generator/src/graph.rs +++ b/utils/multi_machine_generator/src/graph.rs @@ -3,7 +3,7 @@ use std::{ mem, }; -use petgraph::{graph::NodeIndex, Direction, Graph}; +use petgraph::{Direction, Graph, graph::NodeIndex}; use serde::Serialize; /// A node of the network diff --git a/utils/noaslr/demo/Cargo.toml b/utils/noaslr/demo/Cargo.toml index 5285e2a348..bb8389e088 100644 --- a/utils/noaslr/demo/Cargo.toml +++ b/utils/noaslr/demo/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "noaslr_demo" version = "0.15.1" -edition = "2021" +edition = "2024" [build-dependencies] vergen = { version = "8.1.1", features = [ diff --git a/utils/noaslr/libnoaslr/Cargo.toml b/utils/noaslr/libnoaslr/Cargo.toml index 9a5fe8cdb0..6e78680274 100644 --- a/utils/noaslr/libnoaslr/Cargo.toml +++ b/utils/noaslr/libnoaslr/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "libnoaslr" version = "0.15.1" -edition = "2021" +edition = "2024" [lib] name = "noaslr" diff --git a/utils/noaslr/libnoaslr/src/lib.rs b/utils/noaslr/libnoaslr/src/lib.rs index 777396628d..5932c69379 100644 --- a/utils/noaslr/libnoaslr/src/lib.rs +++ b/utils/noaslr/libnoaslr/src/lib.rs @@ -47,7 +47,7 @@ fn libnoaslr() -> Result<()> { #[cfg(target_os = "freebsd")] fn libnoaslr() -> Result<()> { - extern "C" { + unsafe extern "C" { fn exect( c: *const libc::c_char, args: *const *const libc::c_char, diff --git a/utils/noaslr/noaslr/Cargo.toml b/utils/noaslr/noaslr/Cargo.toml index ff64b9a3b4..bd56a4dd63 100644 --- a/utils/noaslr/noaslr/Cargo.toml +++ b/utils/noaslr/noaslr/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "noaslr" version = "0.15.1" -edition = "2021" +edition = "2024" [build-dependencies] vergen = { version = "8.1.1", features = [ diff --git a/utils/noaslr/noaslr/src/args.rs b/utils/noaslr/noaslr/src/args.rs index 96a1197b4e..97d4d5d698 100644 --- a/utils/noaslr/noaslr/src/args.rs +++ b/utils/noaslr/noaslr/src/args.rs @@ -1,6 +1,6 @@ use std::iter; -use clap::{builder::Str, Parser}; +use clap::{Parser, builder::Str}; #[derive(Default)] pub struct Version; diff --git a/utils/noaslr/noaslr/src/main.rs b/utils/noaslr/noaslr/src/main.rs index 1b9f146b92..b94815cb19 100644 --- a/utils/noaslr/noaslr/src/main.rs +++ b/utils/noaslr/noaslr/src/main.rs @@ -3,7 +3,7 @@ mod args; #[cfg(not(any(target_os = "linux", target_os = "android")))] use { crate::args::Args, - anyhow::{anyhow, Result}, + anyhow::{Result, anyhow}, clap::Parser, nix::unistd::execvp, std::ffi::CString, @@ -11,7 +11,7 @@ use { #[cfg(any(target_os = "linux", target_os = "android"))] use { crate::args::Args, - anyhow::{anyhow, Result}, + anyhow::{Result, anyhow}, clap::Parser, nix::{ sys::{personality, personality::Persona},