From a7b19fa4d7deae0ea95f8211b50a817682379836 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Fri, 11 Jul 2025 04:11:45 +0200 Subject: [PATCH 01/18] Initial split [WIP] --- Cargo.toml | 10 + crates/build_id2/Cargo.toml | 38 + crates/build_id2/LICENSE-APACHE | 1 + crates/build_id2/LICENSE-MIT | 1 + crates/build_id2/README.md | 58 ++ .../src/build_id.rs => build_id2/src/lib.rs} | 55 +- crates/core_affinity2/Cargo.toml | 53 ++ crates/core_affinity2/LICENSE-APACHE | 1 + crates/core_affinity2/LICENSE-MIT | 1 + crates/core_affinity2/README.md | 58 ++ .../src/lib.rs} | 74 +- crates/fast_rands/Cargo.toml | 64 ++ crates/fast_rands/LICENSE-APACHE | 1 + crates/fast_rands/LICENSE-MIT | 1 + crates/fast_rands/README.md | 58 ++ .../rands/mod.rs => fast_rands/src/lib.rs} | 104 ++- .../rands => fast_rands/src}/loaded_dice.rs | 26 +- crates/libafl/Cargo.toml | 9 +- crates/libafl_bolts/Cargo.toml | 45 +- crates/libafl_bolts/src/compress.rs | 8 +- crates/libafl_bolts/src/lib.rs | 771 +----------------- crates/libafl_bolts/src/os/mod.rs | 3 - crates/libafl_bolts/src/staterestore.rs | 6 +- crates/libafl_bolts/src/tuples.rs | 107 ++- crates/libafl_core/Cargo.toml | 59 ++ crates/libafl_core/LICENSE-APACHE | 1 + crates/libafl_core/LICENSE-MIT | 1 + crates/libafl_core/README.md | 58 ++ crates/libafl_core/src/lib.rs | 719 ++++++++++++++++ crates/ll_mp/Cargo.toml | 85 ++ crates/ll_mp/LICENSE-APACHE | 1 + crates/ll_mp/LICENSE-MIT | 1 + crates/ll_mp/README.md | 58 ++ crates/ll_mp/examples/llmp_test/main.rs | 254 ++++++ .../src/llmp.rs => ll_mp/src/lib.rs} | 60 +- crates/minibsod/Cargo.toml | 56 ++ crates/minibsod/LICENSE-APACHE | 1 + crates/minibsod/LICENSE-MIT | 1 + crates/minibsod/README.md | 58 ++ crates/minibsod/src/lib.rs | 0 crates/ownedref/Cargo.toml | 56 ++ crates/ownedref/LICENSE-APACHE | 1 + crates/ownedref/LICENSE-MIT | 1 + crates/ownedref/README.md | 58 ++ .../src/ownedref.rs => ownedref/src/lib.rs} | 78 +- .../src/subrange.rs | 2 +- crates/serde_anymap/Cargo.toml | 56 ++ crates/serde_anymap/LICENSE-APACHE | 1 + crates/serde_anymap/LICENSE-MIT | 1 + crates/serde_anymap/README.md | 58 ++ crates/serde_anymap/src/lib.rs | 0 crates/shmem_providers/Cargo.toml | 69 ++ crates/shmem_providers/LICENSE-APACHE | 1 + crates/shmem_providers/LICENSE-MIT | 1 + crates/shmem_providers/README.md | 58 ++ .../shmem.rs => shmem_providers/src/lib.rs} | 84 +- .../src/os => shmem_providers/src}/pipes.rs | 0 .../src}/unix_shmem_server.rs | 5 +- crates/signal_handler/Cargo.toml | 56 ++ crates/signal_handler/LICENSE-APACHE | 1 + crates/signal_handler/LICENSE-MIT | 1 + crates/signal_handler/README.md | 58 ++ crates/signal_handler/src/lib.rs | 0 crates/tuplelist_ex/Cargo.toml | 56 ++ crates/tuplelist_ex/LICENSE-APACHE | 1 + crates/tuplelist_ex/LICENSE-MIT | 1 + crates/tuplelist_ex/README.md | 58 ++ crates/tuplelist_ex/src/lib.rs | 0 68 files changed, 2828 insertions(+), 900 deletions(-) create mode 100644 crates/build_id2/Cargo.toml create mode 120000 crates/build_id2/LICENSE-APACHE create mode 120000 crates/build_id2/LICENSE-MIT create mode 100644 crates/build_id2/README.md rename crates/{libafl_bolts/src/build_id.rs => build_id2/src/lib.rs} (70%) create mode 100644 crates/core_affinity2/Cargo.toml create mode 120000 crates/core_affinity2/LICENSE-APACHE create mode 120000 crates/core_affinity2/LICENSE-MIT create mode 100644 crates/core_affinity2/README.md rename crates/{libafl_bolts/src/core_affinity.rs => core_affinity2/src/lib.rs} (94%) create mode 100644 crates/fast_rands/Cargo.toml create mode 120000 crates/fast_rands/LICENSE-APACHE create mode 120000 crates/fast_rands/LICENSE-MIT create mode 100644 crates/fast_rands/README.md rename crates/{libafl_bolts/src/rands/mod.rs => fast_rands/src/lib.rs} (88%) rename crates/{libafl_bolts/src/rands => fast_rands/src}/loaded_dice.rs (89%) create mode 100644 crates/libafl_core/Cargo.toml create mode 120000 crates/libafl_core/LICENSE-APACHE create mode 120000 crates/libafl_core/LICENSE-MIT create mode 100644 crates/libafl_core/README.md create mode 100644 crates/libafl_core/src/lib.rs create mode 100644 crates/ll_mp/Cargo.toml create mode 120000 crates/ll_mp/LICENSE-APACHE create mode 120000 crates/ll_mp/LICENSE-MIT create mode 100644 crates/ll_mp/README.md create mode 100644 crates/ll_mp/examples/llmp_test/main.rs rename crates/{libafl_bolts/src/llmp.rs => ll_mp/src/lib.rs} (99%) create mode 100644 crates/minibsod/Cargo.toml create mode 120000 crates/minibsod/LICENSE-APACHE create mode 120000 crates/minibsod/LICENSE-MIT create mode 100644 crates/minibsod/README.md create mode 100644 crates/minibsod/src/lib.rs create mode 100644 crates/ownedref/Cargo.toml create mode 120000 crates/ownedref/LICENSE-APACHE create mode 120000 crates/ownedref/LICENSE-MIT create mode 100644 crates/ownedref/README.md rename crates/{libafl_bolts/src/ownedref.rs => ownedref/src/lib.rs} (96%) rename crates/{libafl_bolts => ownedref}/src/subrange.rs (99%) create mode 100644 crates/serde_anymap/Cargo.toml create mode 120000 crates/serde_anymap/LICENSE-APACHE create mode 120000 crates/serde_anymap/LICENSE-MIT create mode 100644 crates/serde_anymap/README.md create mode 100644 crates/serde_anymap/src/lib.rs create mode 100644 crates/shmem_providers/Cargo.toml create mode 120000 crates/shmem_providers/LICENSE-APACHE create mode 120000 crates/shmem_providers/LICENSE-MIT create mode 100644 crates/shmem_providers/README.md rename crates/{libafl_bolts/src/shmem.rs => shmem_providers/src/lib.rs} (97%) rename crates/{libafl_bolts/src/os => shmem_providers/src}/pipes.rs (100%) rename crates/{libafl_bolts/src/os => shmem_providers/src}/unix_shmem_server.rs (99%) create mode 100644 crates/signal_handler/Cargo.toml create mode 120000 crates/signal_handler/LICENSE-APACHE create mode 120000 crates/signal_handler/LICENSE-MIT create mode 100644 crates/signal_handler/README.md create mode 100644 crates/signal_handler/src/lib.rs create mode 100644 crates/tuplelist_ex/Cargo.toml create mode 120000 crates/tuplelist_ex/LICENSE-APACHE create mode 120000 crates/tuplelist_ex/LICENSE-MIT create mode 100644 crates/tuplelist_ex/README.md create mode 100644 crates/tuplelist_ex/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 834eeedfc7c..0bb69c606a0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,9 @@ [workspace] resolver = "2" members = [ + "crates/build_id2", + "crates/core_affinity2", + "crates/fast_rands", "crates/libafl", "crates/libafl_asan", "crates/libafl_asan/libafl_asan_fuzz", @@ -9,6 +12,7 @@ members = [ "crates/libafl_cc", "crates/libafl_concolic/symcc_runtime", "crates/libafl_concolic/symcc_libafl", + "crates/libafl_core", "crates/libafl_derive", "crates/libafl_frida", "crates/libafl_intelpt", @@ -24,6 +28,8 @@ members = [ "crates/libafl_sugar", "crates/libafl_concolic/test/dump_constraints", "crates/libafl_concolic/test/runtime_test", + "crates/ll_mp", + "crates/shmem_providers", "utils/build_and_test_fuzzers", "utils/deexit", "utils/drcov_utils", @@ -64,9 +70,11 @@ readme = "./README.md" [workspace.dependencies] # Internal deps +fast_rands = { path = "./crates/fast_rands", version = "0.15.3", default-features = false } libafl = { path = "./crates/libafl", version = "0.15.3", default-features = false } libafl_bolts = { path = "./crates/libafl_bolts", version = "0.15.3", default-features = false } libafl_cc = { path = "./crates/libafl_cc", version = "0.15.3", default-features = false } +libafl_core = { path = "./crates/libafl_core", version = "0.15.3", default-features = false } symcc_runtime = { path = "./crates/libafl_concolic/symcc_runtime", version = "0.15.2", default-features = false } symcc_libafl = { path = "./crates/libafl_concolic/symcc_libafl", version = "0.15.3", default-features = false } libafl_derive = { path = "./crates/libafl_derive", version = "0.15.3", default-features = false } @@ -80,6 +88,8 @@ libafl_qemu = { path = "./crates/libafl_qemu", version = "0.15.3", default-featu libafl_qemu_build = { path = "./crates/libafl_qemu/libafl_qemu_build", version = "0.15.3", default-features = false } libafl_qemu_sys = { path = "./crates/libafl_qemu/libafl_qemu_sys", version = "0.15.3", default-features = false } libafl_sugar = { path = "./crates/libafl_sugar", version = "0.15.3", default-features = false } +ll_mp = { path = "./crates/ll_mp", version = "0.15.3", default-features = false } +shmem_providers = { path = "./crates/shmem_providers", version = "0.15.3", default-features = false } dump_constraints = { path = "./crates/libafl_concolic/test/dump_constraints", version = "0.15.2", default-features = false } runtime_test = { path = "./crates/libafl_concolic/test/runtime_test", version = "0.15.2", default-features = false } build_and_test_fuzzers = { path = "./utils/build_and_test_fuzzers", version = "0.15.2", default-features = false } diff --git a/crates/build_id2/Cargo.toml b/crates/build_id2/Cargo.toml new file mode 100644 index 00000000000..9e9526fcf7d --- /dev/null +++ b/crates/build_id2/Cargo.toml @@ -0,0 +1,38 @@ +[package] +name = "build_id2" +version.workspace = true +authors = [ + "Andrea Fioraldi ", + "Dominik Maier ", +] +description = "Updated and maintained build id library" +documentation = "https://docs.rs/libafl" +repository = "https://github.com/AFLplusplus/LibAFL/" +readme = "./README.md" +license = "MIT OR Apache-2.0" +keywords = ["os", "build-id"] +edition = "2024" +rust-version = "1.87" +categories = [ + "os", +] + +[package.metadata.docs.rs] +features = ["document-features"] +all-features = true + +[features] +default = [ +] + +[build-dependencies] +rustversion = { workspace = true } + +[dev-dependencies] + +[dependencies] +uuid = { workspace = true } +ahash = { workspace = true } + +[lints] +workspace = true diff --git a/crates/build_id2/LICENSE-APACHE b/crates/build_id2/LICENSE-APACHE new file mode 120000 index 00000000000..965b606f331 --- /dev/null +++ b/crates/build_id2/LICENSE-APACHE @@ -0,0 +1 @@ +../LICENSE-APACHE \ No newline at end of file diff --git a/crates/build_id2/LICENSE-MIT b/crates/build_id2/LICENSE-MIT new file mode 120000 index 00000000000..76219eb72e8 --- /dev/null +++ b/crates/build_id2/LICENSE-MIT @@ -0,0 +1 @@ +../LICENSE-MIT \ No newline at end of file diff --git a/crates/build_id2/README.md b/crates/build_id2/README.md new file mode 100644 index 00000000000..0a638ac1244 --- /dev/null +++ b/crates/build_id2/README.md @@ -0,0 +1,58 @@ +# LibAFL_bolts: OS and Fuzzer Dev's Libary Collection. + + LibAFL logo + +The `libafl_bolts` crate exposes a lot of low-level features of LibAFL for projects that are unrelated to fuzzing, or just fuzzers completely different to LibAFL. +Some cross-platform things in bolts include (but are not limited to): + +* SerdeAnyMap: a map that stores and retrieves elements by type and is serializable and deserializable +* ShMem: A cross-platform (Windows, Linux, Android, MacOS) shared memory implementation +* LLMP: A fast, lock-free IPC mechanism via SharedMap +* Core_affinity: A maintained version of `core_affinity` that can be used to get core information and bind processes to cores +* Rands: Fast random number generators for fuzzing (like [RomuRand](https://www.romu-random.org/)) +* MiniBSOD: get and print information about the current process state including important registers. +* Tuples: Haskel-like compile-time tuple lists +* Os: OS specific stuff like signal handling, windows exception handling, pipes, and helpers for `fork` + +LibAFL_bolts is written and maintained by + +* [Andrea Fioraldi](https://twitter.com/andreafioraldi) +* [Dominik Maier](https://twitter.com/domenuk) +* [s1341](https://twitter.com/srubenst1341) +* [Dongjia Zhang](https://github.com/tokatoka) +* [Addison Crump](https://github.com/addisoncrump) + +## Contributing + +For bugs, feel free to open issues or contact us directly. Thank you for your support. <3 + +Even though we will gladly assist you in finishing up your PR, try to +- keep all the crates compiling with *stable* rust (hide the eventual non-stable code under [`cfg`s](https://github.com/AFLplusplus/LibAFL/blob/main/libafl/build.rs#L26)) +- run `cargo nightly fmt` on your code before pushing +- check the output of `cargo clippy --all` or `./clippy.sh` +- run `cargo build --no-default-features` to check for `no_std` compatibility (and possibly add `#[cfg(feature = "std")]`) to hide parts of your code. + +Some of the parts in this list may be hard, don't be afraid to open a PR if you cannot fix them by yourself, so we can help. + +#### License + + +Licensed under either of Apache License, Version +2.0 or MIT license at your option. + + +
+ + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in this crate by you, as defined in the Apache-2.0 license, shall +be dual licensed as above, without any additional terms or conditions. + + +
+ + +Dependencies under more restrictive licenses, such as GPL or AGPL, can be enabled +using the respective feature in each crate when it is present, such as the +'agpl' feature of the libafl crate. + diff --git a/crates/libafl_bolts/src/build_id.rs b/crates/build_id2/src/lib.rs similarity index 70% rename from crates/libafl_bolts/src/build_id.rs rename to crates/build_id2/src/lib.rs index 876ac1a6610..5abe977e49f 100644 --- a/crates/libafl_bolts/src/build_id.rs +++ b/crates/build_id2/src/lib.rs @@ -1,16 +1,59 @@ //! Based on //! (C) Alec Mocatta under license MIT or Apache 2 +//! +//! Maintained by the LibAFL team. +#![doc = include_str!("../../../README.md")] +/*! */ +#![cfg_attr(not(test), warn( + missing_debug_implementations, + missing_docs, + //trivial_casts, + trivial_numeric_casts, + unused_extern_crates, + unused_import_braces, + unused_qualifications, + //unused_results +))] +#![cfg_attr(test, deny( + missing_debug_implementations, + missing_docs, + //trivial_casts, + trivial_numeric_casts, + unused_extern_crates, + unused_import_braces, + unused_qualifications, + unused_must_use, + //unused_results +))] +#![cfg_attr( + test, + deny( + bad_style, + dead_code, + improper_ctypes, + non_shorthand_field_patterns, + no_mangle_generic_items, + overflowing_literals, + path_statements, + patterns_in_fns_without_body, + unconditional_recursion, + unused, + unused_allocation, + unused_comparisons, + unused_parens, + while_true + ) +)] use core::{ any::TypeId, hash::{Hash, Hasher}, }; -use std::{env, fs::File, io, sync::OnceLock}; +use std::{env, fs::File, hash::BuildHasher, io, sync::OnceLock}; +use ahash::RandomState; use uuid::Uuid; -use crate::hasher_std; - static BUILD_ID: OnceLock = OnceLock::new(); /// Returns a [Uuid] uniquely representing the build of the current binary. @@ -29,8 +72,8 @@ static BUILD_ID: OnceLock = OnceLock::new(); /// # Examples /// /// ``` -/// # let remote_build_id = libafl_bolts::build_id::get(); -/// let local_build_id = libafl_bolts::build_id::get(); +/// # let remote_build_id = build_id2::get(); +/// let local_build_id = build_id2::get(); /// if local_build_id == remote_build_id { /// println!("We're running the same binary as remote!"); /// } else { @@ -79,7 +122,7 @@ fn from_type_id(mut hasher: H) -> H { } fn calculate() -> Uuid { - let hasher = hasher_std(); + let hasher = RandomState::with_seeds(0, 0, 0, 0).build_hasher(); let hasher = from_exe(hasher.clone()).unwrap_or(hasher); let mut hasher = from_type_id(hasher); diff --git a/crates/core_affinity2/Cargo.toml b/crates/core_affinity2/Cargo.toml new file mode 100644 index 00000000000..9d9fff5c447 --- /dev/null +++ b/crates/core_affinity2/Cargo.toml @@ -0,0 +1,53 @@ +[package] +name = "core_affinity2" +version.workspace = true +authors = [ + "Andrea Fioraldi ", + "Dominik Maier ", +] +description = "Core Affinity crate to bind to cores, cross platform" +documentation = "https://docs.rs/libafl" +repository = "https://github.com/AFLplusplus/LibAFL/" +readme = "./README.md" +license = "MIT OR Apache-2.0" +keywords = ["os", "core-affinity", "no-std"] +edition = "2024" +rust-version = "1.87" +categories = [ + "embedded", + "os", + "no-std", +] + +[package.metadata.docs.rs] +features = ["document-features"] +all-features = true + +[features] +default = [ + "std", +] +document-features = ["dep:document-features"] + +#! # Feature Flags +#! ### General Features + +## Enables features that need rust's `std` lib to work, like print, env, ... support +std = [ + "libafl_core/std" +] + +[build-dependencies] +rustversion = { workspace = true } + +[dev-dependencies] + +[dependencies] +# Document all features of this crate (for `cargo doc`) +document-features = { workspace = true, optional = true } +serde = { workspace = true, features = ["alloc", "derive"] } +libafl_core = { workspace = true, features = ["alloc"] } +libc = { workspace = true } + +[lints] +workspace = true diff --git a/crates/core_affinity2/LICENSE-APACHE b/crates/core_affinity2/LICENSE-APACHE new file mode 120000 index 00000000000..965b606f331 --- /dev/null +++ b/crates/core_affinity2/LICENSE-APACHE @@ -0,0 +1 @@ +../LICENSE-APACHE \ No newline at end of file diff --git a/crates/core_affinity2/LICENSE-MIT b/crates/core_affinity2/LICENSE-MIT new file mode 120000 index 00000000000..76219eb72e8 --- /dev/null +++ b/crates/core_affinity2/LICENSE-MIT @@ -0,0 +1 @@ +../LICENSE-MIT \ No newline at end of file diff --git a/crates/core_affinity2/README.md b/crates/core_affinity2/README.md new file mode 100644 index 00000000000..0a638ac1244 --- /dev/null +++ b/crates/core_affinity2/README.md @@ -0,0 +1,58 @@ +# LibAFL_bolts: OS and Fuzzer Dev's Libary Collection. + + LibAFL logo + +The `libafl_bolts` crate exposes a lot of low-level features of LibAFL for projects that are unrelated to fuzzing, or just fuzzers completely different to LibAFL. +Some cross-platform things in bolts include (but are not limited to): + +* SerdeAnyMap: a map that stores and retrieves elements by type and is serializable and deserializable +* ShMem: A cross-platform (Windows, Linux, Android, MacOS) shared memory implementation +* LLMP: A fast, lock-free IPC mechanism via SharedMap +* Core_affinity: A maintained version of `core_affinity` that can be used to get core information and bind processes to cores +* Rands: Fast random number generators for fuzzing (like [RomuRand](https://www.romu-random.org/)) +* MiniBSOD: get and print information about the current process state including important registers. +* Tuples: Haskel-like compile-time tuple lists +* Os: OS specific stuff like signal handling, windows exception handling, pipes, and helpers for `fork` + +LibAFL_bolts is written and maintained by + +* [Andrea Fioraldi](https://twitter.com/andreafioraldi) +* [Dominik Maier](https://twitter.com/domenuk) +* [s1341](https://twitter.com/srubenst1341) +* [Dongjia Zhang](https://github.com/tokatoka) +* [Addison Crump](https://github.com/addisoncrump) + +## Contributing + +For bugs, feel free to open issues or contact us directly. Thank you for your support. <3 + +Even though we will gladly assist you in finishing up your PR, try to +- keep all the crates compiling with *stable* rust (hide the eventual non-stable code under [`cfg`s](https://github.com/AFLplusplus/LibAFL/blob/main/libafl/build.rs#L26)) +- run `cargo nightly fmt` on your code before pushing +- check the output of `cargo clippy --all` or `./clippy.sh` +- run `cargo build --no-default-features` to check for `no_std` compatibility (and possibly add `#[cfg(feature = "std")]`) to hide parts of your code. + +Some of the parts in this list may be hard, don't be afraid to open a PR if you cannot fix them by yourself, so we can help. + +#### License + + +Licensed under either of Apache License, Version +2.0 or MIT license at your option. + + +
+ + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in this crate by you, as defined in the Apache-2.0 license, shall +be dual licensed as above, without any additional terms or conditions. + + +
+ + +Dependencies under more restrictive licenses, such as GPL or AGPL, can be enabled +using the respective feature in each crate when it is present, such as the +'agpl' feature of the libafl crate. + diff --git a/crates/libafl_bolts/src/core_affinity.rs b/crates/core_affinity2/src/lib.rs similarity index 94% rename from crates/libafl_bolts/src/core_affinity.rs rename to crates/core_affinity2/src/lib.rs index ae8bad52173..13edd67cda7 100644 --- a/crates/libafl_bolts/src/core_affinity.rs +++ b/crates/core_affinity2/src/lib.rs @@ -6,11 +6,11 @@ //! //! ```rust //! # use std::thread; -//! use libafl_bolts::core_affinity; +//! use core_affinity2; //! //! // Retrieve the IDs of all active CPU cores. //! # #[cfg(not(miri))] -//! let core_ids = core_affinity::get_core_ids().unwrap(); +//! let core_ids = core_affinity2::get_core_ids().unwrap(); //! //! // Create a thread for each active CPU core. //! # #[cfg(not(miri))] @@ -32,16 +32,65 @@ //! ``` //! //! *This file is a fork of * +#![doc = include_str!("../../../README.md")] +/*! */ +#![cfg_attr(feature = "document-features", doc = document_features::document_features!())] +#![no_std] +#![cfg_attr(not(test), warn( + missing_debug_implementations, + missing_docs, + //trivial_casts, + trivial_numeric_casts, + unused_extern_crates, + unused_import_braces, + unused_qualifications, + //unused_results +))] +#![cfg_attr(test, deny( + missing_debug_implementations, + missing_docs, + //trivial_casts, + trivial_numeric_casts, + unused_extern_crates, + unused_import_braces, + unused_qualifications, + unused_must_use, + //unused_results +))] +#![cfg_attr( + test, + deny( + bad_style, + dead_code, + improper_ctypes, + non_shorthand_field_patterns, + no_mangle_generic_items, + overflowing_literals, + path_statements, + patterns_in_fns_without_body, + unconditional_recursion, + unused, + unused_allocation, + unused_comparisons, + unused_parens, + while_true + ) +)] + +#[cfg(feature = "std")] +#[macro_use] +extern crate std; +#[doc(hidden)] +pub extern crate alloc; use alloc::{ string::{String, ToString}, vec::Vec, }; +use libafl_core::Error; use serde::{Deserialize, Serialize}; -use crate::Error; - /// This function tries to retrieve information /// on all the "cores" active on this system. pub fn get_core_ids() -> Result, Error> { @@ -249,8 +298,9 @@ mod linux { #[cfg(target_os = "dragonfly")] const CPU_SETSIZE: libc::c_int = 256; + use libafl_core::Error; + use super::CoreId; - use crate::Error; #[allow(trivial_numeric_casts)] pub fn get_core_ids() -> Result, Error> { @@ -380,7 +430,7 @@ mod haiku { use alloc::vec::Vec; use std::thread::available_parallelism; - use crate::core_affinity::{CoreId, Error}; + use crate::{CoreId, Error}; #[expect(clippy::unnecessary_wraps)] pub fn get_core_ids() -> Result, Error> { @@ -413,7 +463,7 @@ mod windows { Threading::{GetCurrentThread, SetThreadGroupAffinity}, }; - use crate::core_affinity::{CoreId, Error}; + use crate::{CoreId, Error}; pub fn get_core_ids() -> Result, Error> { let mut core_ids: Vec = Vec::new(); @@ -594,6 +644,7 @@ mod apple { use alloc::vec::Vec; use std::thread::available_parallelism; + use libafl_core::Error; #[cfg(target_arch = "x86_64")] use libc::{ KERN_SUCCESS, THREAD_AFFINITY_POLICY, THREAD_AFFINITY_POLICY_COUNT, integer_t, @@ -604,7 +655,6 @@ mod apple { use libc::{pthread_set_qos_class_self_np, qos_class_t::QOS_CLASS_USER_INITIATED}; use super::CoreId; - use crate::Error; #[cfg(target_arch = "x86_64")] #[repr(C)] @@ -691,13 +741,13 @@ mod netbsd { use alloc::vec::Vec; use std::thread::available_parallelism; + use libafl_core::Error; use libc::{ _cpuset, _cpuset_create, _cpuset_destroy, _cpuset_set, _cpuset_size, pthread_self, pthread_setaffinity_np, }; use super::CoreId; - use crate::Error; #[expect(trivial_numeric_casts)] pub fn get_core_ids() -> Result, Error> { @@ -753,8 +803,9 @@ mod openbsd { use alloc::vec::Vec; use std::thread::available_parallelism; + use libafl_core::Error; + use super::CoreId; - use crate::Error; #[expect(trivial_numeric_casts)] pub fn get_core_ids() -> Result, Error> { @@ -781,8 +832,9 @@ mod solaris { use alloc::vec::Vec; use std::thread::available_parallelism; + use libafl_core::Error; + use super::CoreId; - use crate::Error; #[expect(clippy::unnecessary_wraps)] pub fn get_core_ids() -> Result, Error> { diff --git a/crates/fast_rands/Cargo.toml b/crates/fast_rands/Cargo.toml new file mode 100644 index 00000000000..d4f1ae5e32b --- /dev/null +++ b/crates/fast_rands/Cargo.toml @@ -0,0 +1,64 @@ +[package] +name = "fast_rands" +version.workspace = true +authors = [ + "Andrea Fioraldi ", + "Dominik Maier ", +] +description = "Non-cryptographically, but quite fast, RNG implementations" +documentation = "https://docs.rs/libafl" +repository = "https://github.com/AFLplusplus/LibAFL/" +readme = "./README.md" +license = "MIT OR Apache-2.0" +keywords = ["os", "shmem", "no-std"] +edition = "2024" +rust-version = "1.87" +categories = [ + "embedded", + "os", + "no-std", +] + +[package.metadata.docs.rs] +features = ["document-features"] +all-features = true + +[features] +default = [ + "std", + "alloc", +] +document-features = ["dep:document-features"] + +#! # Feature Flags +#! ### General Features + +## Enables features that need rust's `std` lib to work, like print, env, ... support +std = [] + +## Enables all features that allocate in `no_std` +alloc = [] + +## If set, libafl_rand's `rand` implementations will implement `rand_core::CoreRng` +## and, inversely, all seedable `rand_core::RngCore` types can be used as Rng for LibAFL. +rand_trait = ["rand_core"] + +## Enable python support for Rand +python = ["pyo3"] + +[build-dependencies] +rustversion = { workspace = true } + +[dev-dependencies] + +[dependencies] +serde = { workspace = true, default-features = false, features = [ + "derive", +] } # serialization lib +# Document all features of this crate (for `cargo doc`) +document-features = { workspace = true, optional = true } +rand_core ={ version = "0.9.0", optional = true } +pyo3 = { workspace = true, optional = true, features = ["serde", "macros"] } + +[lints] +workspace = true diff --git a/crates/fast_rands/LICENSE-APACHE b/crates/fast_rands/LICENSE-APACHE new file mode 120000 index 00000000000..965b606f331 --- /dev/null +++ b/crates/fast_rands/LICENSE-APACHE @@ -0,0 +1 @@ +../LICENSE-APACHE \ No newline at end of file diff --git a/crates/fast_rands/LICENSE-MIT b/crates/fast_rands/LICENSE-MIT new file mode 120000 index 00000000000..76219eb72e8 --- /dev/null +++ b/crates/fast_rands/LICENSE-MIT @@ -0,0 +1 @@ +../LICENSE-MIT \ No newline at end of file diff --git a/crates/fast_rands/README.md b/crates/fast_rands/README.md new file mode 100644 index 00000000000..0a638ac1244 --- /dev/null +++ b/crates/fast_rands/README.md @@ -0,0 +1,58 @@ +# LibAFL_bolts: OS and Fuzzer Dev's Libary Collection. + + LibAFL logo + +The `libafl_bolts` crate exposes a lot of low-level features of LibAFL for projects that are unrelated to fuzzing, or just fuzzers completely different to LibAFL. +Some cross-platform things in bolts include (but are not limited to): + +* SerdeAnyMap: a map that stores and retrieves elements by type and is serializable and deserializable +* ShMem: A cross-platform (Windows, Linux, Android, MacOS) shared memory implementation +* LLMP: A fast, lock-free IPC mechanism via SharedMap +* Core_affinity: A maintained version of `core_affinity` that can be used to get core information and bind processes to cores +* Rands: Fast random number generators for fuzzing (like [RomuRand](https://www.romu-random.org/)) +* MiniBSOD: get and print information about the current process state including important registers. +* Tuples: Haskel-like compile-time tuple lists +* Os: OS specific stuff like signal handling, windows exception handling, pipes, and helpers for `fork` + +LibAFL_bolts is written and maintained by + +* [Andrea Fioraldi](https://twitter.com/andreafioraldi) +* [Dominik Maier](https://twitter.com/domenuk) +* [s1341](https://twitter.com/srubenst1341) +* [Dongjia Zhang](https://github.com/tokatoka) +* [Addison Crump](https://github.com/addisoncrump) + +## Contributing + +For bugs, feel free to open issues or contact us directly. Thank you for your support. <3 + +Even though we will gladly assist you in finishing up your PR, try to +- keep all the crates compiling with *stable* rust (hide the eventual non-stable code under [`cfg`s](https://github.com/AFLplusplus/LibAFL/blob/main/libafl/build.rs#L26)) +- run `cargo nightly fmt` on your code before pushing +- check the output of `cargo clippy --all` or `./clippy.sh` +- run `cargo build --no-default-features` to check for `no_std` compatibility (and possibly add `#[cfg(feature = "std")]`) to hide parts of your code. + +Some of the parts in this list may be hard, don't be afraid to open a PR if you cannot fix them by yourself, so we can help. + +#### License + + +Licensed under either of Apache License, Version +2.0 or MIT license at your option. + + +
+ + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in this crate by you, as defined in the Apache-2.0 license, shall +be dual licensed as above, without any additional terms or conditions. + + +
+ + +Dependencies under more restrictive licenses, such as GPL or AGPL, can be enabled +using the respective feature in each crate when it is present, such as the +'agpl' feature of the libafl crate. + diff --git a/crates/libafl_bolts/src/rands/mod.rs b/crates/fast_rands/src/lib.rs similarity index 88% rename from crates/libafl_bolts/src/rands/mod.rs rename to crates/fast_rands/src/lib.rs index 14b5c50ce9c..1f2113fa465 100644 --- a/crates/libafl_bolts/src/rands/mod.rs +++ b/crates/fast_rands/src/lib.rs @@ -1,4 +1,54 @@ -//! The random number generators of `LibAFL` +//! The fast random number generators of `LibAFL` +#![doc = include_str!("../../../README.md")] +/*! */ +#![cfg_attr(feature = "document-features", doc = document_features::document_features!())] +#![no_std] +#![cfg_attr(not(test), warn( + missing_debug_implementations, + missing_docs, + //trivial_casts, + trivial_numeric_casts, + unused_extern_crates, + unused_import_braces, + unused_qualifications, + //unused_results +))] +#![cfg_attr(test, deny( + missing_debug_implementations, + missing_docs, + //trivial_casts, + trivial_numeric_casts, + unused_extern_crates, + unused_import_braces, + unused_qualifications, + unused_must_use, + //unused_results +))] +#![cfg_attr( + test, + deny( + bad_style, + dead_code, + improper_ctypes, + non_shorthand_field_patterns, + no_mangle_generic_items, + overflowing_literals, + path_statements, + patterns_in_fns_without_body, + unconditional_recursion, + unused, + unused_allocation, + unused_comparisons, + unused_parens, + while_true + ) +)] + +#[cfg(feature = "std")] +#[macro_use] +extern crate std; +#[doc(hidden)] +pub extern crate alloc; #[cfg(all(not(feature = "std"), target_has_atomic = "ptr"))] use core::sync::atomic::{AtomicUsize, Ordering}; @@ -559,6 +609,41 @@ impl XkcdRand { #[cfg(feature = "python")] /// `Rand` Python bindings pub mod pybind { + + /// Unwrap the mutable body of this wrapper + #[macro_export] + macro_rules! unwrap_me_mut_body { + ($wrapper:expr, $name:ident, $body:block, $wrapper_type:ident, { $($wrapper_option:tt),*}) => { + match &mut $wrapper { + $( + $wrapper_type::$wrapper_option(py_wrapper) => { + Python::with_gil(|py| -> PyResult<_> { + let mut borrowed = py_wrapper.borrow_mut(py); + let $name = &mut borrowed.inner; + Ok($body) + }) + .unwrap() + } + )* + } + }; + ($wrapper:expr, $name:ident, $body:block, $wrapper_type:ident, { $($wrapper_option:tt),*}, { $($wrapper_optional:tt($pw:ident) => $code_block:block)* }) => { + match &mut $wrapper { + $( + $wrapper_type::$wrapper_option(py_wrapper) => { + Python::with_gil(|py| -> PyResult<_> { + let mut borrowed = py_wrapper.borrow_mut(py); + let $name = &mut borrowed.inner; + Ok($body) + }) + .unwrap() + } + )* + $($wrapper_type::$wrapper_optional($pw) => { $code_block })* + } + }; + } + use pyo3::prelude::*; use serde::{Deserialize, Serialize}; @@ -567,9 +652,9 @@ pub mod pybind { #[pyclass(unsendable, name = "StdRand")] #[expect(clippy::unsafe_derive_deserialize)] #[derive(Serialize, Deserialize, Debug, Clone)] - /// Python class for StdRand + /// Python class for [`StdRand`] pub struct PythonStdRand { - /// Rust wrapped StdRand object + /// Rust wrapped [`StdRand`] object pub inner: StdRand, } @@ -644,18 +729,17 @@ pub mod pybind { #[cfg(test)] mod tests { + use core::num::NonZero; + use crate::{ - nonzero, - rands::{ - Rand, RomuDuoJrRand, RomuTrioRand, Sfc64Rand, StdRand, XorShift64Rand, - Xoshiro256PlusPlusRand, - }, + Rand, RomuDuoJrRand, RomuTrioRand, Sfc64Rand, StdRand, XorShift64Rand, + Xoshiro256PlusPlusRand, }; fn test_single_rand(rand: &mut R) { assert_ne!(rand.next(), rand.next()); - assert!(rand.below(nonzero!(100)) < 100); - assert_eq!(rand.below(nonzero!(1)), 0); + assert!(rand.below(NonZero::new(100).unwrap()) < 100); + assert_eq!(rand.below(NonZero::new(1).unwrap()), 0); assert_eq!(rand.between(10, 10), 10); assert!(rand.between(11, 20) > 10); } diff --git a/crates/libafl_bolts/src/rands/loaded_dice.rs b/crates/fast_rands/src/loaded_dice.rs similarity index 89% rename from crates/libafl_bolts/src/rands/loaded_dice.rs rename to crates/fast_rands/src/loaded_dice.rs index 321c653b2cf..75660f88549 100644 --- a/crates/libafl_bolts/src/rands/loaded_dice.rs +++ b/crates/fast_rands/src/loaded_dice.rs @@ -7,8 +7,8 @@ A simple module that implements a random sampler implementing the [alias method] Assume we want to sample from the following distribution: `p(0)=0.5, p(1)=0.3, p(2)=0.1, p(3)=0.1`: ```rust -# extern crate libafl_bolts; -use libafl_bolts::rands::{StdRand, loaded_dice::LoadedDiceSampler}; +# extern crate libafl_rand; +use libafl_rand::{StdRand, loaded_dice::LoadedDiceSampler}; fn main() { let mut rand = StdRand::new(); let mut sampler = LoadedDiceSampler::new(&[0.5, 0.3, 0.1, 0.1]).unwrap(); @@ -23,9 +23,21 @@ Original code by @eqv, see */ use alloc::vec::Vec; +use core::fmt::{self, Debug, Formatter}; use super::Rand; -use crate::Error; + +/// An illegal argument got passed to a function. +pub struct IllegalArgumentError; + +impl Debug for IllegalArgumentError { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!( + f, + "LoadedDiceError(Tried to construct LoadedDiceSampler with empty probs array)" + ) + } +} /// Helper struct for [`LoadedDiceSampler`] #[derive(Debug, Clone, PartialEq)] @@ -54,11 +66,9 @@ pub struct LoadedDiceSampler { impl LoadedDiceSampler { /// Create a new [`LoadedDiceSampler`] with the given probabilities - pub fn new(probs: &[f64]) -> Result { + pub fn new(probs: &[f64]) -> Result { if probs.is_empty() { - return Err(Error::illegal_argument( - "Tried to construct LoadedDiceSampler with empty probs array", - )); + return Err(IllegalArgumentError); } let entries = LoadedDiceSampler::construct_table(probs); Ok(Self { entries }) @@ -113,7 +123,7 @@ mod tests { use alloc::vec::Vec; use super::LoadedDiceSampler; - use crate::rands::{Rand, StdRand}; + use crate::{Rand, StdRand}; #[test] #[expect(clippy::cast_precision_loss)] diff --git a/crates/libafl/Cargo.toml b/crates/libafl/Cargo.toml index ecbd2b0d6fe..c89d8b66f95 100644 --- a/crates/libafl/Cargo.toml +++ b/crates/libafl/Cargo.toml @@ -177,17 +177,17 @@ serdeany_autoreg = ["libafl_bolts/serdeany_autoreg"] llmp_broker_timeouts = ["std"] ## If set, llmp will bind to 0.0.0.0, allowing cross-device communication. Binds to localhost by default. -llmp_bind_public = ["libafl_bolts/llmp_bind_public"] +llmp_bind_public = ["ll_mp/llmp_bind_public"] ## Enables llmp compression using GZip -llmp_compression = ["libafl_bolts/llmp_compression"] +llmp_compression = ["ll_mp/llmp_compression"] ## Enables debug output for LLMP (also needs a `logger` installed) -llmp_debug = ["std", "libafl_bolts/llmp_debug"] +llmp_debug = ["std", "ll_mp/llmp_debug"] ## Reduces the initial map size for llmp llmp_small_maps = [ - "libafl_bolts/llmp_small_maps", + "ll_mp/llmp_small_maps", ] # reduces initial map size for llmp ## Grammar mutator. @@ -222,6 +222,7 @@ static_assertions = { workspace = true } libafl_bolts = { workspace = true, features = ["alloc"] } libafl_derive = { workspace = true, default-features = true, optional = true } libafl_intelpt = { workspace = true, default-features = true, optional = true } +ll_mp = { workspace = true } rustversion = { workspace = true } tuple_list = { version = "0.1.3" } diff --git a/crates/libafl_bolts/Cargo.toml b/crates/libafl_bolts/Cargo.toml index a476ce03720..2197a22829b 100644 --- a/crates/libafl_bolts/Cargo.toml +++ b/crates/libafl_bolts/Cargo.toml @@ -29,8 +29,6 @@ all-features = true default = [ "std", "derive", - "llmp_compression", - "llmp_small_maps", "rand_trait", "gzip", "serdeany_autoreg", @@ -47,6 +45,8 @@ std = [ "hostname", "nix", "serde/std", + "libafl_core/std", + "libafl_core/nix", "uuid", "backtrace", "uds", @@ -56,7 +56,14 @@ std = [ ] ## Enables all features that allocate in `no_std` -alloc = ["serde/alloc", "hashbrown", "postcard", "erased-serde/alloc", "ahash"] +alloc = [ + "serde/alloc", + "hashbrown", + "postcard", + "erased-serde/alloc", + "ahash", + "libafl_core/alloc", +] ## Provide the `#[derive(SerdeAny)]` macro. derive = ["libafl_derive"] @@ -66,7 +73,7 @@ derive = ["libafl_derive"] rand_trait = ["rand_core"] ## Will build the `pyo3` bindings -python = ["pyo3", "std"] +python = ["pyo3", "std", "libafl_core/python"] ## Expose `libafl::prelude` for direct access to all types without additional `use` directives prelude = [] @@ -103,21 +110,6 @@ stable_anymap = [] ## Automatically register all `#[derive(SerdeAny)]` types at startup. serdeany_autoreg = ["ctor"] - -#! ### LLMP features - -## If set, llmp will bind to 0.0.0.0, allowing cross-device communication. Binds to localhost by default. -llmp_bind_public = ["alloc"] - -## Enables llmp compression using GZip -llmp_compression = ["alloc", "gzip"] - -## Enables debug output for LLMP (also needs a `logger` installed) -llmp_debug = ["alloc", "std"] - -## Reduces the initial map size for llmp -llmp_small_maps = ["alloc"] - #! ### Stable SIMD features ## Use the best SIMD implementation by our benchmark. @@ -133,9 +125,12 @@ chrono = "0.4.40" itertools = "0.14.0" [dependencies] +libafl_core = { workspace = true, features=["postcard"] } libafl_derive = { workspace = true, default-features = true, optional = true } static_assertions = { workspace = true } typeid = { workspace = true } +shmem_providers = { workspace = true } +fast_rands = { workspace = true } tuple_list = { version = "0.1.3" } hashbrown = { workspace = true, features = [ @@ -184,9 +179,6 @@ rustversion = { workspace = true } # Document all features of this crate (for `cargo doc`) document-features = { workspace = true, optional = true } -[lints] -workspace = true - [target.'cfg(unix)'.dependencies] libc = { workspace = true } # For (*nix) libc uds = { version = "0.4.2", optional = true, default-features = false } @@ -224,11 +216,6 @@ mach2 = "0.4.2" #opt-level = 3 #debug = true -[[example]] -name = "llmp_test" -path = "./examples/llmp_test/main.rs" -required-features = ["std"] - [[example]] name = "simd" @@ -236,3 +223,7 @@ path = "./examples/simd/simd.rs" bench = true harness = false required-features = ["std", "simd"] + +[lints] +workspace = true + diff --git a/crates/libafl_bolts/src/compress.rs b/crates/libafl_bolts/src/compress.rs index 3cf189638e7..c62d8b5d09e 100644 --- a/crates/libafl_bolts/src/compress.rs +++ b/crates/libafl_bolts/src/compress.rs @@ -62,12 +62,8 @@ impl GzipCompressor { /// Decompression. pub fn decompress(&self, buf: &[u8]) -> Result, Error> { - let decompressed = decompress_to_vec(buf); - - match decompressed { - Ok(buf) => Ok(buf), - Err(_) => Err(Error::compression()), - } + decompress_to_vec(buf) + .map_err(|err| Error::illegal_state(format!("Failed to decompress: {err:?}"))) } } diff --git a/crates/libafl_bolts/src/lib.rs b/crates/libafl_bolts/src/lib.rs index 27268dac104..33460148bf5 100644 --- a/crates/libafl_bolts/src/lib.rs +++ b/crates/libafl_bolts/src/lib.rs @@ -46,21 +46,6 @@ ) )] -/// We need some sort of "[`String`]" for errors in `no_alloc`... -/// We can only support `'static` without allocator, so let's do that. -#[cfg(not(feature = "alloc"))] -type String = &'static str; - -/// A simple non-allocating "format" string wrapper for no-std. -/// -/// Problem is that we really need a non-allocating format... -/// This one simply returns the `fmt` string. -/// Good enough for simple errors, for anything else, use the `alloc` feature. -#[cfg(not(feature = "alloc"))] -macro_rules! format { - ($fmt:literal) => {{ $fmt }}; -} - #[cfg(feature = "std")] #[macro_use] extern crate std; @@ -96,10 +81,8 @@ pub mod minibsod; pub mod os; #[cfg(feature = "alloc")] pub mod ownedref; -pub mod rands; #[cfg(feature = "alloc")] pub mod serdeany; -pub mod shmem; #[cfg(feature = "std")] pub mod staterestore; #[cfg(feature = "alloc")] @@ -120,6 +103,10 @@ pub use target_args::*; pub mod simd; +pub use libafl_core::Error; +pub use fast_rands as rands; +pub use shmem_providers as shmem; + /// The purpose of this module is to alleviate imports of the bolts by adding a glob import. #[cfg(feature = "prelude")] pub mod bolts_prelude { @@ -148,7 +135,7 @@ pub mod bolts_prelude { #[cfg(all(unix, feature = "std"))] use alloc::boxed::Box; #[cfg(feature = "alloc")] -use alloc::{borrow::Cow, string::ToString, vec::Vec}; +use alloc::string::ToString; #[cfg(all(not(feature = "xxh3"), feature = "alloc"))] use core::hash::BuildHasher; #[cfg(any(feature = "xxh3", feature = "alloc"))] @@ -169,7 +156,6 @@ use std::{ // TODO: re-enable once is resolved. #[cfg(all(not(feature = "xxh3"), feature = "alloc"))] use ahash::RandomState; -use log::SetLoggerError; use serde::{Deserialize, Serialize}; #[cfg(feature = "xxh3")] use xxhash_rust::xxh3::xxh3_64; @@ -181,65 +167,18 @@ use xxhash_rust::xxh3::xxh3_64; )] pub struct ClientId(pub u32); -use core::{ - array::TryFromSliceError, - fmt::{self, Display}, - num::{ParseIntError, TryFromIntError}, - ops::{Deref, DerefMut}, - time, -}; -#[cfg(feature = "std")] -use std::{env::VarError, io}; +#[cfg(feature = "alloc")] +use alloc::string::String; +use core::time; #[cfg(feature = "libafl_derive")] pub use libafl_derive::SerdeAny; #[cfg(feature = "std")] use log::{Metadata, Record}; -#[cfg(feature = "alloc")] -use { - alloc::string::{FromUtf8Error, String}, - core::cell::{BorrowError, BorrowMutError}, - core::str::Utf8Error, -}; /// Localhost addr, this is used, for example, for LLMP Client, which connects to this address pub const IP_LOCALHOST: &str = "127.0.0.1"; -/// We need fixed names for many parts of this lib. -#[cfg(feature = "alloc")] -pub trait Named { - /// Provide the name of this element. - fn name(&self) -> &Cow<'static, str>; -} - -#[cfg(feature = "errors_backtrace")] -/// Error Backtrace type when `errors_backtrace` feature is enabled (== [`backtrace::Backtrace`]) -pub type ErrorBacktrace = backtrace::Backtrace; - -#[cfg(not(feature = "errors_backtrace"))] -#[derive(Debug, Default)] -/// ZST to use when `errors_backtrace` is disabled -pub struct ErrorBacktrace; - -#[cfg(not(feature = "errors_backtrace"))] -impl ErrorBacktrace { - /// Nop - #[must_use] - pub fn new() -> Self { - Self - } -} - -#[cfg(feature = "errors_backtrace")] -fn display_error_backtrace(f: &mut fmt::Formatter, err: &ErrorBacktrace) -> fmt::Result { - write!(f, "\nBacktrace: {err:?}") -} -#[cfg(not(feature = "errors_backtrace"))] -#[expect(clippy::unnecessary_wraps)] -fn display_error_backtrace(_f: &mut fmt::Formatter, _err: &ErrorBacktrace) -> fmt::Result { - fmt::Result::Ok(()) -} - /// Returns the standard input [`Hasher`] /// /// Returns the hasher for the input with a given hash, depending on features: @@ -300,418 +239,6 @@ pub fn generic_hash_std(input: &I) -> u64 { hasher.finish() } -/// Main error struct for `LibAFL` -#[derive(Debug)] -pub enum Error { - /// Serialization error - Serialize(String, ErrorBacktrace), - /// Compression error - #[cfg(feature = "gzip")] - Compression(ErrorBacktrace), - /// Optional val was supposed to be set, but isn't. - EmptyOptional(String, ErrorBacktrace), - /// Key not in Map - KeyNotFound(String, ErrorBacktrace), - /// Key already exists and should not overwrite - KeyExists(String, ErrorBacktrace), - /// No elements in the current item - Empty(String, ErrorBacktrace), - /// End of iteration - IteratorEnd(String, ErrorBacktrace), - /// This is not supported (yet) - NotImplemented(String, ErrorBacktrace), - /// You're holding it wrong - IllegalState(String, ErrorBacktrace), - /// The argument passed to this method or function is not valid - IllegalArgument(String, ErrorBacktrace), - /// The performed action is not supported on the current platform - Unsupported(String, ErrorBacktrace), - /// Shutting down, not really an error. - ShuttingDown, - /// OS error, wrapping a [`io::Error`] - #[cfg(feature = "std")] - OsError(io::Error, String, ErrorBacktrace), - /// Something else happened - Unknown(String, ErrorBacktrace), - /// Error with the corpora - InvalidCorpus(String, ErrorBacktrace), - /// Error specific to a runtime like QEMU or Frida - Runtime(String, ErrorBacktrace), - /// The `Input` was invalid. - InvalidInput(String, ErrorBacktrace), -} - -impl Error { - /// Serialization error - #[must_use] - pub fn serialize(arg: S) -> Self - where - S: Into, - { - Error::Serialize(arg.into(), ErrorBacktrace::new()) - } - - #[cfg(feature = "gzip")] - /// Compression error - #[must_use] - pub fn compression() -> Self { - Error::Compression(ErrorBacktrace::new()) - } - - /// Optional val was supposed to be set, but isn't. - #[must_use] - pub fn empty_optional(arg: S) -> Self - where - S: Into, - { - Error::EmptyOptional(arg.into(), ErrorBacktrace::new()) - } - - /// The `Input` was invalid - #[must_use] - pub fn invalid_input(reason: S) -> Self - where - S: Into, - { - Error::InvalidInput(reason.into(), ErrorBacktrace::new()) - } - - /// Key not in Map - #[must_use] - pub fn key_not_found(arg: S) -> Self - where - S: Into, - { - Error::KeyNotFound(arg.into(), ErrorBacktrace::new()) - } - - /// Key already exists in Map - #[must_use] - pub fn key_exists(arg: S) -> Self - where - S: Into, - { - Error::KeyExists(arg.into(), ErrorBacktrace::new()) - } - - /// No elements in the current item - #[must_use] - pub fn empty(arg: S) -> Self - where - S: Into, - { - Error::Empty(arg.into(), ErrorBacktrace::new()) - } - - /// End of iteration - #[must_use] - pub fn iterator_end(arg: S) -> Self - where - S: Into, - { - Error::IteratorEnd(arg.into(), ErrorBacktrace::new()) - } - - /// This is not supported (yet) - #[must_use] - pub fn not_implemented(arg: S) -> Self - where - S: Into, - { - Error::NotImplemented(arg.into(), ErrorBacktrace::new()) - } - - /// You're holding it wrong - #[must_use] - pub fn illegal_state(arg: S) -> Self - where - S: Into, - { - Error::IllegalState(arg.into(), ErrorBacktrace::new()) - } - - /// The argument passed to this method or function is not valid - #[must_use] - pub fn illegal_argument(arg: S) -> Self - where - S: Into, - { - Error::IllegalArgument(arg.into(), ErrorBacktrace::new()) - } - - /// Shutting down, not really an error. - #[must_use] - pub fn shutting_down() -> Self { - Error::ShuttingDown - } - - /// This operation is not supported on the current architecture or platform - #[must_use] - pub fn unsupported(arg: S) -> Self - where - S: Into, - { - Error::Unsupported(arg.into(), ErrorBacktrace::new()) - } - - /// OS error with additional message - #[cfg(feature = "std")] - #[must_use] - pub fn os_error(err: io::Error, msg: S) -> Self - where - S: Into, - { - Error::OsError(err, msg.into(), ErrorBacktrace::new()) - } - - /// OS error from [`io::Error::last_os_error`] with additional message - #[cfg(feature = "std")] - #[must_use] - pub fn last_os_error(msg: S) -> Self - where - S: Into, - { - Error::OsError( - io::Error::last_os_error(), - msg.into(), - ErrorBacktrace::new(), - ) - } - - /// Something else happened - #[must_use] - pub fn unknown(arg: S) -> Self - where - S: Into, - { - Error::Unknown(arg.into(), ErrorBacktrace::new()) - } - - /// Error with corpora - #[must_use] - pub fn invalid_corpus(arg: S) -> Self - where - S: Into, - { - Error::InvalidCorpus(arg.into(), ErrorBacktrace::new()) - } - - /// Error specific to some runtime, like QEMU or Frida - #[must_use] - pub fn runtime(arg: S) -> Self - where - S: Into, - { - Error::Runtime(arg.into(), ErrorBacktrace::new()) - } -} - -impl core::error::Error for Error { - #[cfg(feature = "std")] - fn source(&self) -> Option<&(dyn core::error::Error + 'static)> { - if let Self::OsError(err, _, _) = self { - Some(err) - } else { - None - } - } -} - -impl Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - Self::Serialize(s, b) => { - write!(f, "Error in Serialization: `{0}`", &s)?; - display_error_backtrace(f, b) - } - #[cfg(feature = "gzip")] - Self::Compression(b) => { - write!(f, "Error in decompression")?; - display_error_backtrace(f, b) - } - Self::EmptyOptional(s, b) => { - write!(f, "Optional value `{0}` was not set", &s)?; - display_error_backtrace(f, b) - } - Self::KeyNotFound(s, b) => { - write!(f, "Key: `{0}` - not found", &s)?; - display_error_backtrace(f, b) - } - Self::KeyExists(s, b) => { - write!(f, "Key: `{0}` - already exists", &s)?; - display_error_backtrace(f, b) - } - Self::Empty(s, b) => { - write!(f, "No items in {0}", &s)?; - display_error_backtrace(f, b) - } - Self::IteratorEnd(s, b) => { - write!(f, "All elements have been processed in {0} iterator", &s)?; - display_error_backtrace(f, b) - } - Self::NotImplemented(s, b) => { - write!(f, "Not implemented: {0}", &s)?; - display_error_backtrace(f, b) - } - Self::IllegalState(s, b) => { - write!(f, "Illegal state: {0}", &s)?; - display_error_backtrace(f, b) - } - Self::IllegalArgument(s, b) => { - write!(f, "Illegal argument: {0}", &s)?; - display_error_backtrace(f, b) - } - Self::Unsupported(s, b) => { - write!( - f, - "The operation is not supported on the current platform: {0}", - &s - )?; - display_error_backtrace(f, b) - } - Self::ShuttingDown => write!(f, "Shutting down!"), - #[cfg(feature = "std")] - Self::OsError(err, s, b) => { - write!(f, "OS error: {0}: {1}", &s, err)?; - display_error_backtrace(f, b) - } - Self::Unknown(s, b) => { - write!(f, "Unknown error: {0}", &s)?; - display_error_backtrace(f, b) - } - Self::InvalidCorpus(s, b) => { - write!(f, "Invalid corpus: {0}", &s)?; - display_error_backtrace(f, b) - } - Self::Runtime(s, b) => { - write!(f, "Runtime error: {0}", &s)?; - display_error_backtrace(f, b) - } - Self::InvalidInput(s, b) => { - write!(f, "Encountered an invalid input: {0}", &s)?; - display_error_backtrace(f, b) - } - } - } -} - -#[cfg(feature = "alloc")] -impl From for Error { - fn from(err: BorrowError) -> Self { - Self::illegal_state(format!( - "Couldn't borrow from a RefCell as immutable: {err:?}" - )) - } -} - -#[cfg(feature = "alloc")] -impl From for Error { - fn from(err: BorrowMutError) -> Self { - Self::illegal_state(format!( - "Couldn't borrow from a RefCell as mutable: {err:?}" - )) - } -} - -/// Stringify the postcard serializer error -#[cfg(feature = "alloc")] -impl From for Error { - fn from(err: postcard::Error) -> Self { - Self::serialize(format!("{err:?}")) - } -} - -#[cfg(all(unix, feature = "std"))] -impl From for Error { - fn from(err: nix::Error) -> Self { - Self::unknown(format!("Unix error: {err:?}")) - } -} - -/// Create an AFL Error from io Error -#[cfg(feature = "std")] -impl From for Error { - fn from(err: io::Error) -> Self { - Self::os_error(err, "io::Error ocurred") - } -} - -#[cfg(feature = "alloc")] -impl From for Error { - fn from(err: FromUtf8Error) -> Self { - Self::unknown(format!("Could not convert byte / utf-8: {err:?}")) - } -} - -#[cfg(feature = "alloc")] -impl From for Error { - fn from(err: Utf8Error) -> Self { - Self::unknown(format!("Could not convert byte / utf-8: {err:?}")) - } -} - -#[cfg(feature = "std")] -impl From for Error { - fn from(err: VarError) -> Self { - Self::empty(format!("Could not get env var: {err:?}")) - } -} - -impl From for Error { - #[allow(unused_variables)] // err is unused without std - fn from(err: ParseIntError) -> Self { - Self::unknown(format!("Failed to parse Int: {err:?}")) - } -} - -impl From for Error { - #[allow(unused_variables)] // err is unused without std - fn from(err: TryFromIntError) -> Self { - Self::illegal_state(format!("Expected conversion failed: {err:?}")) - } -} - -impl From for Error { - #[allow(unused_variables)] // err is unused without std - fn from(err: TryFromSliceError) -> Self { - Self::illegal_argument(format!("Could not convert slice: {err:?}")) - } -} - -impl From for Error { - #[allow(unused_variables)] // err is unused without std - fn from(err: SetLoggerError) -> Self { - Self::illegal_state(format!("Failed to register logger: {err:?}")) - } -} - -#[cfg(windows)] -impl From for Error { - #[allow(unused_variables)] // err is unused without std - fn from(err: windows_result::Error) -> Self { - Self::unknown(format!("Windows API error: {err:?}")) - } -} - -#[cfg(feature = "python")] -impl From for Error { - fn from(err: pyo3::PyErr) -> Self { - pyo3::Python::with_gil(|py| { - if err - .matches( - py, - pyo3::types::PyType::new::(py), - ) - .unwrap() - { - Self::shutting_down() - } else { - Self::illegal_state(format!("Python exception: {err:?}")) - } - }) - } -} - /// The purpose of this module is to alleviate imports of many components by adding a glob import. #[cfg(feature = "prelude")] pub mod prelude { @@ -728,197 +255,6 @@ pub unsafe extern "C" fn external_current_millis() -> u64 { 1000 } -/// Trait to convert into an Owned type -pub trait IntoOwned { - /// Returns if the current type is an owned type. - #[must_use] - fn is_owned(&self) -> bool; - - /// Transfer the current type into an owned type. - #[must_use] - fn into_owned(self) -> Self; -} - -/// Can be converted to a slice -pub trait AsSlice<'a> { - /// Type of the entries of this slice - type Entry: 'a; - /// Type of the reference to this slice - type SliceRef: Deref; - - /// Convert to a slice - fn as_slice(&'a self) -> Self::SliceRef; -} - -/// Can be converted to a slice -pub trait AsSizedSlice<'a, const N: usize> { - /// Type of the entries of this slice - type Entry: 'a; - /// Type of the reference to this slice - type SliceRef: Deref; - - /// Convert to a slice - fn as_sized_slice(&'a self) -> Self::SliceRef; -} - -impl<'a, T, R: ?Sized> AsSlice<'a> for R -where - T: 'a, - R: Deref, -{ - type Entry = T; - type SliceRef = &'a [T]; - - fn as_slice(&'a self) -> Self::SliceRef { - self - } -} - -impl<'a, T, const N: usize, R: ?Sized> AsSizedSlice<'a, N> for R -where - T: 'a, - R: Deref, -{ - type Entry = T; - type SliceRef = &'a [T; N]; - - fn as_sized_slice(&'a self) -> Self::SliceRef { - self - } -} - -/// Can be converted to a mutable slice -pub trait AsSliceMut<'a>: AsSlice<'a> { - /// Type of the mutable reference to this slice - type SliceRefMut: DerefMut; - - /// Convert to a slice - fn as_slice_mut(&'a mut self) -> Self::SliceRefMut; -} - -/// Can be converted to a mutable slice -pub trait AsSizedSliceMut<'a, const N: usize>: AsSizedSlice<'a, N> { - /// Type of the mutable reference to this slice - type SliceRefMut: DerefMut; - - /// Convert to a slice - fn as_sized_slice_mut(&'a mut self) -> Self::SliceRefMut; -} - -impl<'a, T, R: ?Sized> AsSliceMut<'a> for R -where - T: 'a, - R: DerefMut, -{ - type SliceRefMut = &'a mut [T]; - - fn as_slice_mut(&'a mut self) -> Self::SliceRefMut { - &mut *self - } -} - -impl<'a, T, const N: usize, R: ?Sized> AsSizedSliceMut<'a, N> for R -where - T: 'a, - R: DerefMut, -{ - type SliceRefMut = &'a mut [T; N]; - - fn as_sized_slice_mut(&'a mut self) -> Self::SliceRefMut { - &mut *self - } -} - -/// Create an `Iterator` from a reference -pub trait AsIter<'it> { - /// The item type - type Item: 'it; - /// The ref type - type Ref: Deref; - /// The iterator type - type IntoIter: Iterator; - - /// Create an iterator from &self - fn as_iter(&'it self) -> Self::IntoIter; -} - -impl<'it, S, T> AsIter<'it> for S -where - S: AsSlice<'it, Entry = T, SliceRef = &'it [T]>, - T: 'it, -{ - type Item = S::Entry; - type Ref = &'it Self::Item; - type IntoIter = core::slice::Iter<'it, Self::Item>; - - fn as_iter(&'it self) -> Self::IntoIter { - self.as_slice().iter() - } -} - -/// Create an `Iterator` from a mutable reference -pub trait AsIterMut<'it>: AsIter<'it> { - /// The ref type - type RefMut: DerefMut; - /// The iterator type - type IntoIterMut: Iterator; - - /// Create an iterator from &mut self - fn as_iter_mut(&'it mut self) -> Self::IntoIterMut; -} - -impl<'it, S, T> AsIterMut<'it> for S -where - S: AsSliceMut<'it, Entry = T, SliceRef = &'it [T], SliceRefMut = &'it mut [T]>, - T: 'it, -{ - type RefMut = &'it mut Self::Item; - type IntoIterMut = core::slice::IterMut<'it, Self::Item>; - - fn as_iter_mut(&'it mut self) -> Self::IntoIterMut { - self.as_slice_mut().iter_mut() - } -} - -/// Has a length field -pub trait HasLen { - /// The length - fn len(&self) -> usize; - - /// Returns `true` if it has no elements. - fn is_empty(&self) -> bool { - self.len() == 0 - } -} - -#[cfg(feature = "alloc")] -impl HasLen for Vec { - #[inline] - fn len(&self) -> usize { - Vec::::len(self) - } -} - -impl HasLen for &mut T { - fn len(&self) -> usize { - self.deref().len() - } -} - -/// Has a ref count -pub trait HasRefCnt { - /// The ref count - fn refcnt(&self) -> isize; - /// The ref count, mutable - fn refcnt_mut(&mut self) -> &mut isize; -} - -/// Trait to truncate slices and maps to a new size -pub trait Truncate { - /// Reduce the size of the slice - fn truncate(&mut self, len: usize); -} - /// Current time #[cfg(feature = "std")] #[must_use] @@ -960,6 +296,29 @@ pub fn current_milliseconds() -> u64 { current_time().as_millis() as u64 } +/// Trait to truncate slices and maps to a new size +pub trait Truncate { + /// Reduce the size of the slice + fn truncate(&mut self, len: usize); +} + +impl Truncate for &[T] { + fn truncate(&mut self, len: usize) { + *self = &self[..len]; + } +} + +impl Truncate for &mut [T] { + fn truncate(&mut self, len: usize) { + let value = core::mem::take(self); + let len = value.len().min(len); + let truncated = value + .get_mut(..len) + .expect("Truncate with len <= len() should always work"); + let _: &mut [T] = core::mem::replace(self, truncated); + } +} + /// Format a `Duration` into a HMS string #[cfg(feature = "alloc")] #[must_use] @@ -1065,8 +424,8 @@ impl SimpleStdoutLogger { /// register stdout logger pub fn set_logger() -> Result<(), Error> { - log::set_logger(&LIBAFL_STDOUT_LOGGER)?; - Ok(()) + log::set_logger(&LIBAFL_STDOUT_LOGGER) + .map_err(|err| Error::illegal_state(format!("Failed to set logger: {err:?}"))) } } @@ -1231,8 +590,8 @@ impl SimpleStderrLogger { /// register stderr logger pub fn set_logger() -> Result<(), Error> { - log::set_logger(&LIBAFL_STDERR_LOGGER)?; - Ok(()) + log::set_logger(&LIBAFL_STDERR_LOGGER) + .map_err(|err| Error::illegal_state(format!("Could not set logger: {err:?}"))) } } @@ -1295,9 +654,9 @@ impl SimpleFdLogger { unsafe { let logger = &mut *logger; logger.set_fd(log_fd); - log::set_logger(logger)?; + log::set_logger(logger) + .map_err(|err| Error::illegal_state(format!("Could not set logger: {err:?}"))) } - Ok(()) } } @@ -1466,39 +825,6 @@ pub mod pybind { }; } - #[macro_export] - macro_rules! unwrap_me_mut_body { - ($wrapper:expr, $name:ident, $body:block, $wrapper_type:ident, { $($wrapper_option:tt),*}) => { - match &mut $wrapper { - $( - $wrapper_type::$wrapper_option(py_wrapper) => { - Python::with_gil(|py| -> PyResult<_> { - let mut borrowed = py_wrapper.borrow_mut(py); - let $name = &mut borrowed.inner; - Ok($body) - }) - .unwrap() - } - )* - } - }; - ($wrapper:expr, $name:ident, $body:block, $wrapper_type:ident, { $($wrapper_option:tt),*}, { $($wrapper_optional:tt($pw:ident) => $code_block:block)* }) => { - match &mut $wrapper { - $( - $wrapper_type::$wrapper_option(py_wrapper) => { - Python::with_gil(|py| -> PyResult<_> { - let mut borrowed = py_wrapper.borrow_mut(py); - let $name = &mut borrowed.inner; - Ok($body) - }) - .unwrap() - } - )* - $($wrapper_type::$wrapper_optional($pw) => { $code_block })* - } - }; - } - #[macro_export] macro_rules! impl_serde_pyobjectwrapper { ($struct_name:ident, $inner:tt) => { @@ -1569,29 +895,6 @@ pub mod pybind { } } -/// Create a [`Vec`] of the given type with `nb_elts` elements, initialized in place. -/// The closure must initialize [`Vec`] (of size `nb_elts` * `sizeo_of::()`). -/// -/// # Safety -/// -/// The input closure should fully initialize the new [`Vec`], not leaving any uninitialized bytes. -// TODO: Use MaybeUninit API at some point. -#[cfg(feature = "alloc")] -#[expect(clippy::uninit_vec)] -pub unsafe fn vec_init(nb_elts: usize, init_fn: F) -> Result, E> -where - F: FnOnce(&mut Vec) -> Result<(), E>, -{ - unsafe { - let mut new_vec: Vec = Vec::with_capacity(nb_elts); - new_vec.set_len(nb_elts); - - init_fn(&mut new_vec)?; - - Ok(new_vec) - } -} - #[cfg(test)] mod tests { diff --git a/crates/libafl_bolts/src/os/mod.rs b/crates/libafl_bolts/src/os/mod.rs index 0bbdd9f0357..1b9d81b1c9f 100644 --- a/crates/libafl_bolts/src/os/mod.rs +++ b/crates/libafl_bolts/src/os/mod.rs @@ -3,9 +3,6 @@ #[cfg(any(unix, all(windows, feature = "std")))] use crate::Error; -#[cfg(all(unix, feature = "std"))] -pub mod unix_shmem_server; - #[cfg(unix)] pub mod unix_signals; #[cfg(unix)] diff --git a/crates/libafl_bolts/src/staterestore.rs b/crates/libafl_bolts/src/staterestore.rs index c75b2772eb6..76e71d22d98 100644 --- a/crates/libafl_bolts/src/staterestore.rs +++ b/crates/libafl_bolts/src/staterestore.rs @@ -17,12 +17,10 @@ use std::{ }; use ahash::RandomState; +use libafl_core::{AsSlice, Error}; use serde::{Serialize, de::DeserializeOwned}; -use crate::{ - AsSlice, Error, - shmem::{ShMem, ShMemProvider}, -}; +use crate::shmem::{ShMem, ShMemProvider}; /// If the saved page content equals exactly this buf, the restarted child wants to exit cleanly. const EXITING_MAGIC: &[u8; 16] = b"LIBAFL_EXIT_NOW\0"; diff --git a/crates/libafl_bolts/src/tuples.rs b/crates/libafl_bolts/src/tuples.rs index 87d8840f967..6ce73ccc115 100644 --- a/crates/libafl_bolts/src/tuples.rs +++ b/crates/libafl_bolts/src/tuples.rs @@ -15,9 +15,6 @@ use core::{ use serde::{Deserialize, Serialize}; pub use tuple_list::{TupleList, tuple_list, tuple_list_type}; -use crate::HasLen; -#[cfg(feature = "alloc")] -use crate::Named; #[cfg(any(feature = "xxh3", feature = "alloc"))] use crate::hash_std; @@ -27,6 +24,74 @@ pub fn type_eq() -> bool { typeid::of::() == typeid::of::() } +/// We need fixed names for many parts of this lib. +#[cfg(feature = "alloc")] +pub trait Named { + /// Provide the name of this element. + fn name(&self) -> &Cow<'static, str>; +} + +#[cfg(feature = "alloc")] +impl Named for () { + #[inline] + fn name(&self) -> &Cow<'static, str> { + static NAME: Cow<'static, str> = Cow::Borrowed("()"); + &NAME + } +} + +/// Has a length field +pub trait HasLen { + /// The length + fn len(&self) -> usize; + + /// Returns `true` if it has no elements. + fn is_empty(&self) -> bool { + self.len() == 0 + } +} + +#[cfg(feature = "alloc")] +impl HasLen for Vec { + #[inline] + fn len(&self) -> usize { + Vec::::len(self) + } +} + +impl HasLen for &mut T { + fn len(&self) -> usize { + self.deref().len() + } +} + +impl HasLen for (Head, Tail) +where + Tail: HasLen, +{ + #[inline] + fn len(&self) -> usize { + self.1.len() + 1 + } +} + +impl HasLen for (Tail,) +where + Tail: HasLen, +{ + #[inline] + fn len(&self) -> usize { + self.0.len() + } +} + +impl HasLen for () { + #[inline] + fn len(&self) -> usize { + 0 + } +} + /// Borrow each member of the tuple pub trait SplitBorrow<'a> { /// The Resulting [`TupleList`], of an [`SplitBorrow::borrow()`] call @@ -110,33 +175,6 @@ where const LEN: usize = 1 + Tail::LEN; } -impl HasLen for (Head, Tail) -where - Tail: HasLen, -{ - #[inline] - fn len(&self) -> usize { - self.1.len() + 1 - } -} - -impl HasLen for (Tail,) -where - Tail: HasLen, -{ - #[inline] - fn len(&self) -> usize { - self.0.len() - } -} - -impl HasLen for () { - #[inline] - fn len(&self) -> usize { - 0 - } -} - /// Finds the `const_name` and `name_id` pub trait HasNameId { /// Gets the `const_name` for this entry @@ -403,15 +441,6 @@ impl NamedTuple for () { } } -#[cfg(feature = "alloc")] -impl Named for () { - #[inline] - fn name(&self) -> &Cow<'static, str> { - static NAME: Cow<'static, str> = Cow::Borrowed("Empty"); - &NAME - } -} - #[cfg(feature = "alloc")] impl NamedTuple for (Head, Tail) where diff --git a/crates/libafl_core/Cargo.toml b/crates/libafl_core/Cargo.toml new file mode 100644 index 00000000000..ceb7f0e93a2 --- /dev/null +++ b/crates/libafl_core/Cargo.toml @@ -0,0 +1,59 @@ +[package] +name = "libafl_core" +version.workspace = true +authors = [ + "Andrea Fioraldi ", + "Dominik Maier ", +] +description = "A platform-independent shared memory library for Rust" +documentation = "https://docs.rs/libafl" +repository = "https://github.com/AFLplusplus/LibAFL/" +readme = "./README.md" +license = "MIT OR Apache-2.0" +keywords = ["os", "shmem", "no-std"] +edition = "2024" +rust-version = "1.87" +categories = ["embedded", "os", "no-std"] + +[package.metadata.docs.rs] +features = ["document-features"] +all-features = true + +[features] +default = [] +document-features = ["dep:document-features"] +#! # Feature Flags +#! ### General Features + +## Enables features that need rust's `std` lib to work, like print, env, ... support +std = [] + +## Enables all features that allocate in `no_std` +alloc = [] + +## Stores the backtraces of all generated `Error`s. Good for debugging, but may come with a slight performance hit. +errors_backtrace = ["dep:backtrace"] + +## Enable python error conversion +python = ["dep:pyo3"] + +## Enables nix error conversion +nix = ["dep:nix"] + +## Enables postcard error conversion +postcard = ["dep:postcard"] + +[build-dependencies] +rustversion = { workspace = true } + +[dev-dependencies] + +[dependencies] +document-features = { workspace = true, optional = true } +backtrace = { workspace = true, default-features = true, optional = true } +postcard = { workspace = true, optional = true } +nix = { workspace = true, optional = true } +pyo3 = { workspace = true, optional = true } + +[lints] +workspace = true diff --git a/crates/libafl_core/LICENSE-APACHE b/crates/libafl_core/LICENSE-APACHE new file mode 120000 index 00000000000..965b606f331 --- /dev/null +++ b/crates/libafl_core/LICENSE-APACHE @@ -0,0 +1 @@ +../LICENSE-APACHE \ No newline at end of file diff --git a/crates/libafl_core/LICENSE-MIT b/crates/libafl_core/LICENSE-MIT new file mode 120000 index 00000000000..76219eb72e8 --- /dev/null +++ b/crates/libafl_core/LICENSE-MIT @@ -0,0 +1 @@ +../LICENSE-MIT \ No newline at end of file diff --git a/crates/libafl_core/README.md b/crates/libafl_core/README.md new file mode 100644 index 00000000000..0a638ac1244 --- /dev/null +++ b/crates/libafl_core/README.md @@ -0,0 +1,58 @@ +# LibAFL_bolts: OS and Fuzzer Dev's Libary Collection. + + LibAFL logo + +The `libafl_bolts` crate exposes a lot of low-level features of LibAFL for projects that are unrelated to fuzzing, or just fuzzers completely different to LibAFL. +Some cross-platform things in bolts include (but are not limited to): + +* SerdeAnyMap: a map that stores and retrieves elements by type and is serializable and deserializable +* ShMem: A cross-platform (Windows, Linux, Android, MacOS) shared memory implementation +* LLMP: A fast, lock-free IPC mechanism via SharedMap +* Core_affinity: A maintained version of `core_affinity` that can be used to get core information and bind processes to cores +* Rands: Fast random number generators for fuzzing (like [RomuRand](https://www.romu-random.org/)) +* MiniBSOD: get and print information about the current process state including important registers. +* Tuples: Haskel-like compile-time tuple lists +* Os: OS specific stuff like signal handling, windows exception handling, pipes, and helpers for `fork` + +LibAFL_bolts is written and maintained by + +* [Andrea Fioraldi](https://twitter.com/andreafioraldi) +* [Dominik Maier](https://twitter.com/domenuk) +* [s1341](https://twitter.com/srubenst1341) +* [Dongjia Zhang](https://github.com/tokatoka) +* [Addison Crump](https://github.com/addisoncrump) + +## Contributing + +For bugs, feel free to open issues or contact us directly. Thank you for your support. <3 + +Even though we will gladly assist you in finishing up your PR, try to +- keep all the crates compiling with *stable* rust (hide the eventual non-stable code under [`cfg`s](https://github.com/AFLplusplus/LibAFL/blob/main/libafl/build.rs#L26)) +- run `cargo nightly fmt` on your code before pushing +- check the output of `cargo clippy --all` or `./clippy.sh` +- run `cargo build --no-default-features` to check for `no_std` compatibility (and possibly add `#[cfg(feature = "std")]`) to hide parts of your code. + +Some of the parts in this list may be hard, don't be afraid to open a PR if you cannot fix them by yourself, so we can help. + +#### License + + +Licensed under either of Apache License, Version +2.0 or MIT license at your option. + + +
+ + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in this crate by you, as defined in the Apache-2.0 license, shall +be dual licensed as above, without any additional terms or conditions. + + +
+ + +Dependencies under more restrictive licenses, such as GPL or AGPL, can be enabled +using the respective feature in each crate when it is present, such as the +'agpl' feature of the libafl crate. + diff --git a/crates/libafl_core/src/lib.rs b/crates/libafl_core/src/lib.rs new file mode 100644 index 00000000000..4867e3a8c5b --- /dev/null +++ b/crates/libafl_core/src/lib.rs @@ -0,0 +1,719 @@ +/*! + * `LibAFL_core` contains core traits used across all crates, including the [`Error`] enum and various traits. + */ +#![doc = include_str!("../../../README.md")] +/*! */ +#![cfg_attr(feature = "document-features", doc = document_features::document_features!())] +#![no_std] +#![cfg_attr(not(test), warn( + missing_debug_implementations, + missing_docs, + //trivial_casts, + trivial_numeric_casts, + unused_extern_crates, + unused_import_braces, + unused_qualifications, + //unused_results +))] +#![cfg_attr(test, deny( + missing_debug_implementations, + missing_docs, + //trivial_casts, + trivial_numeric_casts, + unused_extern_crates, + unused_import_braces, + unused_qualifications, + unused_must_use, + //unused_results +))] +#![cfg_attr( + test, + deny( + bad_style, + dead_code, + improper_ctypes, + non_shorthand_field_patterns, + no_mangle_generic_items, + overflowing_literals, + path_statements, + patterns_in_fns_without_body, + unconditional_recursion, + unused, + unused_allocation, + unused_comparisons, + unused_parens, + while_true + ) +)] + +/// We need some sort of "[`String`]" for errors in `no_alloc`... +/// We can only support `'static` without allocator, so let's do that. +#[cfg(not(feature = "alloc"))] +type String = &'static str; + +/// A simple non-allocating "format" string wrapper for no-std. +/// +/// Problem is that we really need a non-allocating format... +/// This one simply returns the `fmt` string. +/// Good enough for simple errors, for anything else, use the `alloc` feature. +#[cfg(not(feature = "alloc"))] +macro_rules! format { + ($fmt:literal) => {{ $fmt }}; +} + +#[cfg(feature = "std")] +#[macro_use] +extern crate std; +#[cfg(feature = "alloc")] +#[macro_use] +#[doc(hidden)] +pub extern crate alloc; + +#[cfg(feature = "alloc")] +use alloc::vec::Vec; +use core::{ + array::TryFromSliceError, + fmt::{self, Display}, + num::{ParseIntError, TryFromIntError}, + ops::{Deref, DerefMut}, +}; +#[cfg(feature = "std")] +use std::{env::VarError, io}; + +#[cfg(feature = "alloc")] +use { + alloc::string::{FromUtf8Error, String}, + core::cell::{BorrowError, BorrowMutError}, + core::str::Utf8Error, +}; + + + +#[cfg(feature = "errors_backtrace")] +/// Error Backtrace type when `errors_backtrace` feature is enabled (== [`backtrace::Backtrace`]) +pub type ErrorBacktrace = backtrace::Backtrace; + +#[cfg(not(feature = "errors_backtrace"))] +#[derive(Debug, Default)] +/// ZST to use when `errors_backtrace` is disabled +pub struct ErrorBacktrace; + +#[cfg(not(feature = "errors_backtrace"))] +impl ErrorBacktrace { + /// Nop + #[must_use] + pub fn new() -> Self { + Self + } +} + +#[cfg(feature = "errors_backtrace")] +fn display_error_backtrace(f: &mut fmt::Formatter, err: &ErrorBacktrace) -> fmt::Result { + write!(f, "\nBacktrace: {err:?}") +} +#[cfg(not(feature = "errors_backtrace"))] +#[expect(clippy::unnecessary_wraps)] +fn display_error_backtrace(_f: &mut fmt::Formatter, _err: &ErrorBacktrace) -> fmt::Result { + fmt::Result::Ok(()) +} + +/// Main error enum for `LibAFL` +#[derive(Debug)] +pub enum Error { + /// Serialization error + Serialize(String, ErrorBacktrace), + /// Optional val was supposed to be set, but isn't. + EmptyOptional(String, ErrorBacktrace), + /// Key not in Map + KeyNotFound(String, ErrorBacktrace), + /// Key already exists and should not overwrite + KeyExists(String, ErrorBacktrace), + /// No elements in the current item + Empty(String, ErrorBacktrace), + /// End of iteration + IteratorEnd(String, ErrorBacktrace), + /// This is not supported (yet) + NotImplemented(String, ErrorBacktrace), + /// You're holding it wrong + IllegalState(String, ErrorBacktrace), + /// The argument passed to this method or function is not valid + IllegalArgument(String, ErrorBacktrace), + /// The performed action is not supported on the current platform + Unsupported(String, ErrorBacktrace), + /// Shutting down, not really an error. + ShuttingDown, + /// OS error, wrapping a [`io::Error`] + #[cfg(feature = "std")] + OsError(io::Error, String, ErrorBacktrace), + /// Something else happened + Unknown(String, ErrorBacktrace), + /// Error with the corpora + InvalidCorpus(String, ErrorBacktrace), + /// Error specific to a runtime like QEMU or Frida + Runtime(String, ErrorBacktrace), + /// The `Input` was invalid. + InvalidInput(String, ErrorBacktrace), +} + +impl Error { + /// Serialization error + #[must_use] + pub fn serialize(arg: S) -> Self + where + S: Into, + { + Error::Serialize(arg.into(), ErrorBacktrace::new()) + } + + /// Optional val was supposed to be set, but isn't. + #[must_use] + pub fn empty_optional(arg: S) -> Self + where + S: Into, + { + Error::EmptyOptional(arg.into(), ErrorBacktrace::new()) + } + + /// The `Input` was invalid + #[must_use] + pub fn invalid_input(reason: S) -> Self + where + S: Into, + { + Error::InvalidInput(reason.into(), ErrorBacktrace::new()) + } + + /// Key not in Map + #[must_use] + pub fn key_not_found(arg: S) -> Self + where + S: Into, + { + Error::KeyNotFound(arg.into(), ErrorBacktrace::new()) + } + + /// Key already exists in Map + #[must_use] + pub fn key_exists(arg: S) -> Self + where + S: Into, + { + Error::KeyExists(arg.into(), ErrorBacktrace::new()) + } + + /// No elements in the current item + #[must_use] + pub fn empty(arg: S) -> Self + where + S: Into, + { + Error::Empty(arg.into(), ErrorBacktrace::new()) + } + + /// End of iteration + #[must_use] + pub fn iterator_end(arg: S) -> Self + where + S: Into, + { + Error::IteratorEnd(arg.into(), ErrorBacktrace::new()) + } + + /// This is not supported (yet) + #[must_use] + pub fn not_implemented(arg: S) -> Self + where + S: Into, + { + Error::NotImplemented(arg.into(), ErrorBacktrace::new()) + } + + /// You're holding it wrong + #[must_use] + pub fn illegal_state(arg: S) -> Self + where + S: Into, + { + Error::IllegalState(arg.into(), ErrorBacktrace::new()) + } + + /// The argument passed to this method or function is not valid + #[must_use] + pub fn illegal_argument(arg: S) -> Self + where + S: Into, + { + Error::IllegalArgument(arg.into(), ErrorBacktrace::new()) + } + + /// Shutting down, not really an error. + #[must_use] + pub fn shutting_down() -> Self { + Error::ShuttingDown + } + + /// This operation is not supported on the current architecture or platform + #[must_use] + pub fn unsupported(arg: S) -> Self + where + S: Into, + { + Error::Unsupported(arg.into(), ErrorBacktrace::new()) + } + + /// OS error with additional message + #[cfg(feature = "std")] + #[must_use] + pub fn os_error(err: io::Error, msg: S) -> Self + where + S: Into, + { + Error::OsError(err, msg.into(), ErrorBacktrace::new()) + } + + /// OS error from [`io::Error::last_os_error`] with additional message + #[cfg(feature = "std")] + #[must_use] + pub fn last_os_error(msg: S) -> Self + where + S: Into, + { + Error::OsError( + io::Error::last_os_error(), + msg.into(), + ErrorBacktrace::new(), + ) + } + + /// Something else happened + #[must_use] + pub fn unknown(arg: S) -> Self + where + S: Into, + { + Error::Unknown(arg.into(), ErrorBacktrace::new()) + } + + /// Error with corpora + #[must_use] + pub fn invalid_corpus(arg: S) -> Self + where + S: Into, + { + Error::InvalidCorpus(arg.into(), ErrorBacktrace::new()) + } + + /// Error specific to some runtime, like QEMU or Frida + #[must_use] + pub fn runtime(arg: S) -> Self + where + S: Into, + { + Error::Runtime(arg.into(), ErrorBacktrace::new()) + } +} + +impl core::error::Error for Error { + #[cfg(feature = "std")] + fn source(&self) -> Option<&(dyn core::error::Error + 'static)> { + if let Self::OsError(err, _, _) = self { + Some(err) + } else { + None + } + } +} + +impl Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::Serialize(s, b) => { + write!(f, "Error in Serialization: `{0}`", &s)?; + display_error_backtrace(f, b) + } + Self::EmptyOptional(s, b) => { + write!(f, "Optional value `{0}` was not set", &s)?; + display_error_backtrace(f, b) + } + Self::KeyNotFound(s, b) => { + write!(f, "Key: `{0}` - not found", &s)?; + display_error_backtrace(f, b) + } + Self::KeyExists(s, b) => { + write!(f, "Key: `{0}` - already exists", &s)?; + display_error_backtrace(f, b) + } + Self::Empty(s, b) => { + write!(f, "No items in {0}", &s)?; + display_error_backtrace(f, b) + } + Self::IteratorEnd(s, b) => { + write!(f, "All elements have been processed in {0} iterator", &s)?; + display_error_backtrace(f, b) + } + Self::NotImplemented(s, b) => { + write!(f, "Not implemented: {0}", &s)?; + display_error_backtrace(f, b) + } + Self::IllegalState(s, b) => { + write!(f, "Illegal state: {0}", &s)?; + display_error_backtrace(f, b) + } + Self::IllegalArgument(s, b) => { + write!(f, "Illegal argument: {0}", &s)?; + display_error_backtrace(f, b) + } + Self::Unsupported(s, b) => { + write!( + f, + "The operation is not supported on the current platform: {0}", + &s + )?; + display_error_backtrace(f, b) + } + Self::ShuttingDown => write!(f, "Shutting down!"), + #[cfg(feature = "std")] + Self::OsError(err, s, b) => { + write!(f, "OS error: {0}: {1}", &s, err)?; + display_error_backtrace(f, b) + } + Self::Unknown(s, b) => { + write!(f, "Unknown error: {0}", &s)?; + display_error_backtrace(f, b) + } + Self::InvalidCorpus(s, b) => { + write!(f, "Invalid corpus: {0}", &s)?; + display_error_backtrace(f, b) + } + Self::Runtime(s, b) => { + write!(f, "Runtime error: {0}", &s)?; + display_error_backtrace(f, b) + } + Self::InvalidInput(s, b) => { + write!(f, "Encountered an invalid input: {0}", &s)?; + display_error_backtrace(f, b) + } + } + } +} + +#[cfg(feature = "alloc")] +impl From for Error { + fn from(err: BorrowError) -> Self { + Self::illegal_state(format!( + "Couldn't borrow from a RefCell as immutable: {err:?}" + )) + } +} + +#[cfg(feature = "alloc")] +impl From for Error { + fn from(err: BorrowMutError) -> Self { + Self::illegal_state(format!( + "Couldn't borrow from a RefCell as mutable: {err:?}" + )) + } +} + +/// Stringify the postcard serializer error +#[cfg(all(feature = "alloc", feature = "postcard"))] +impl From for Error { + fn from(err: postcard::Error) -> Self { + Self::serialize(format!("{err:?}")) + } +} + +#[cfg(all(unix, feature = "nix"))] +impl From for Error { + fn from(err: nix::Error) -> Self { + Self::unknown(format!("Unix error: {err:?}")) + } +} + +/// Create an AFL Error from io Error +#[cfg(feature = "std")] +impl From for Error { + fn from(err: io::Error) -> Self { + Self::os_error(err, "io::Error ocurred") + } +} + +#[cfg(feature = "alloc")] +impl From for Error { + fn from(err: FromUtf8Error) -> Self { + Self::unknown(format!("Could not convert byte / utf-8: {err:?}")) + } +} + +#[cfg(feature = "alloc")] +impl From for Error { + fn from(err: Utf8Error) -> Self { + Self::unknown(format!("Could not convert byte / utf-8: {err:?}")) + } +} + +#[cfg(feature = "std")] +impl From for Error { + fn from(_err: VarError) -> Self { + Self::illegal_state(format!("Could not get env var: {_err:?}")) + } +} + +impl From for Error { + #[allow(unused_variables)] // err is unused without std + fn from(err: ParseIntError) -> Self { + Self::unknown(format!("Failed to parse Int: {err:?}")) + } +} + +impl From for Error { + #[allow(unused_variables)] // err is unused without std + fn from(err: TryFromIntError) -> Self { + Self::illegal_state(format!("Expected conversion failed: {err:?}")) + } +} + +impl From for Error { + #[allow(unused_variables)] // err is unused without std + fn from(err: TryFromSliceError) -> Self { + Self::illegal_argument(format!("Could not convert slice: {err:?}")) + } +} + +#[cfg(windows)] +impl From for Error { + #[allow(unused_variables)] // err is unused without std + fn from(err: windows_result::Error) -> Self { + Self::unknown(format!("Windows API error: {err:?}")) + } +} + +#[cfg(feature = "python")] +impl From for Error { + fn from(err: pyo3::PyErr) -> Self { + pyo3::Python::with_gil(|py| { + if err + .matches( + py, + pyo3::types::PyType::new::(py), + ) + .unwrap() + { + Self::shutting_down() + } else { + Self::illegal_state(format!("Python exception: {err:?}")) + } + }) + } +} + +/// Trait to convert into an Owned type +pub trait IntoOwned { + /// Returns if the current type is an owned type. + #[must_use] + fn is_owned(&self) -> bool; + + /// Transfer the current type into an owned type. + #[must_use] + fn into_owned(self) -> Self; +} + +/// Can be converted to a slice +pub trait AsSlice<'a> { + /// Type of the entries of this slice + type Entry: 'a; + /// Type of the reference to this slice + type SliceRef: Deref; + + /// Convert to a slice + fn as_slice(&'a self) -> Self::SliceRef; +} + +/// Can be converted to a slice +pub trait AsSizedSlice<'a, const N: usize> { + /// Type of the entries of this slice + type Entry: 'a; + /// Type of the reference to this slice + type SliceRef: Deref; + + /// Convert to a slice + fn as_sized_slice(&'a self) -> Self::SliceRef; +} + +impl<'a, T, R: ?Sized> AsSlice<'a> for R +where + T: 'a, + R: Deref, +{ + type Entry = T; + type SliceRef = &'a [T]; + + fn as_slice(&'a self) -> Self::SliceRef { + self + } +} + +impl<'a, T, const N: usize, R: ?Sized> AsSizedSlice<'a, N> for R +where + T: 'a, + R: Deref, +{ + type Entry = T; + type SliceRef = &'a [T; N]; + + fn as_sized_slice(&'a self) -> Self::SliceRef { + self + } +} + +/// Can be converted to a mutable slice +pub trait AsSliceMut<'a>: AsSlice<'a> { + /// Type of the mutable reference to this slice + type SliceRefMut: DerefMut; + + /// Convert to a slice + fn as_slice_mut(&'a mut self) -> Self::SliceRefMut; +} + +/// Can be converted to a mutable slice +pub trait AsSizedSliceMut<'a, const N: usize>: AsSizedSlice<'a, N> { + /// Type of the mutable reference to this slice + type SliceRefMut: DerefMut; + + /// Convert to a slice + fn as_sized_slice_mut(&'a mut self) -> Self::SliceRefMut; +} + +impl<'a, T, R: ?Sized> AsSliceMut<'a> for R +where + T: 'a, + R: DerefMut, +{ + type SliceRefMut = &'a mut [T]; + + fn as_slice_mut(&'a mut self) -> Self::SliceRefMut { + &mut *self + } +} + +impl<'a, T, const N: usize, R: ?Sized> AsSizedSliceMut<'a, N> for R +where + T: 'a, + R: DerefMut, +{ + type SliceRefMut = &'a mut [T; N]; + + fn as_sized_slice_mut(&'a mut self) -> Self::SliceRefMut { + &mut *self + } +} + +/// Create an `Iterator` from a reference +pub trait AsIter<'it> { + /// The item type + type Item: 'it; + /// The ref type + type Ref: Deref; + /// The iterator type + type IntoIter: Iterator; + + /// Create an iterator from &self + fn as_iter(&'it self) -> Self::IntoIter; +} + +impl<'it, S, T> AsIter<'it> for S +where + S: AsSlice<'it, Entry = T, SliceRef = &'it [T]>, + T: 'it, +{ + type Item = S::Entry; + type Ref = &'it Self::Item; + type IntoIter = core::slice::Iter<'it, Self::Item>; + + fn as_iter(&'it self) -> Self::IntoIter { + self.as_slice().iter() + } +} + +/// Create an `Iterator` from a mutable reference +pub trait AsIterMut<'it>: AsIter<'it> { + /// The ref type + type RefMut: DerefMut; + /// The iterator type + type IntoIterMut: Iterator; + + /// Create an iterator from &mut self + fn as_iter_mut(&'it mut self) -> Self::IntoIterMut; +} + +impl<'it, S, T> AsIterMut<'it> for S +where + S: AsSliceMut<'it, Entry = T, SliceRef = &'it [T], SliceRefMut = &'it mut [T]>, + T: 'it, +{ + type RefMut = &'it mut Self::Item; + type IntoIterMut = core::slice::IterMut<'it, Self::Item>; + + fn as_iter_mut(&'it mut self) -> Self::IntoIterMut { + self.as_slice_mut().iter_mut() + } +} + + +/// Has a ref count +pub trait HasRefCnt { + /// The ref count + fn refcnt(&self) -> isize; + /// The ref count, mutable + fn refcnt_mut(&mut self) -> &mut isize; +} + +/// Zero-cost way to construct [`core::num::NonZeroUsize`] at compile-time. +#[macro_export] +macro_rules! nonzero { + // TODO: Further simplify with `unwrap`/`expect` once MSRV includes + // https://github.com/rust-lang/rust/issues/67441 + ($val:expr) => { + const { + match core::num::NonZero::new($val) { + Some(x) => x, + None => panic!("Value passed to `nonzero!` was zero"), + } + } + }; +} + +/// Get a [`core::ptr::NonNull`] to a global static mut (or similar). +/// +/// The same as [`core::ptr::addr_of_mut`] or `&raw mut`, but wrapped in said [`NonNull`](core::ptr::NonNull). +#[macro_export] +macro_rules! nonnull_raw_mut { + ($val:expr) => { + // # Safety + // The pointer to a value will never be null (unless we're on an archaic OS in a CTF challenge). + unsafe { core::ptr::NonNull::new(&raw mut $val).unwrap_unchecked() } + }; +} + +/// Create a [`Vec`] of the given type with `nb_elts` elements, initialized in place. +/// The closure must initialize [`Vec`] (of size `nb_elts` * `sizeo_of::()`). +/// +/// # Safety +/// +/// The input closure should fully initialize the new [`Vec`], not leaving any uninitialized bytes. +// TODO: Use MaybeUninit API at some point. +#[cfg(feature = "alloc")] +#[expect(clippy::uninit_vec)] +pub unsafe fn vec_init(nb_elts: usize, init_fn: F) -> Result, E> +where + F: FnOnce(&mut Vec) -> Result<(), E>, +{ + unsafe { + let mut new_vec: Vec = Vec::with_capacity(nb_elts); + new_vec.set_len(nb_elts); + + init_fn(&mut new_vec)?; + + Ok(new_vec) + } +} diff --git a/crates/ll_mp/Cargo.toml b/crates/ll_mp/Cargo.toml new file mode 100644 index 00000000000..70e57ecfb4c --- /dev/null +++ b/crates/ll_mp/Cargo.toml @@ -0,0 +1,85 @@ +[package] +name = "ll_mp" +version.workspace = true +authors = [ + "Andrea Fioraldi ", + "Dominik Maier ", +] +description = "A library for low level message passing" +documentation = "https://docs.rs/libafl" +repository = "https://github.com/AFLplusplus/LibAFL/" +readme = "./README.md" +license = "MIT OR Apache-2.0" +keywords = ["os", "ipc", "no-std"] +edition = "2024" +rust-version = "1.87" +categories = [ + "os", + "no-std", +] + +[package.metadata.docs.rs] +features = ["document-features"] +all-features = true + +[features] +default = [ + "std", + "alloc", + "gzip", + "llmp_compression", + "llmp_small_maps", +] +document-features = ["dep:document-features"] + +#! # Feature Flags +#! ### General Features + +## Enables features that need rust's `std` lib to work, like print, env, ... support +std = [ +] + +## Enables all features that allocate in `no_std` +alloc = [] + +## Enables gzip compression in certain parts of the lib +gzip = ["miniz_oxide", "alloc"] + +#! ### LLMP features + +## If set, llmp will bind to 0.0.0.0, allowing cross-device communication. Binds to localhost by default. +llmp_bind_public = ["alloc"] + +## Enables llmp compression using GZip +llmp_compression = ["alloc", "gzip"] + +## Enables debug output for LLMP (also needs a `logger` installed) +llmp_debug = ["alloc", "std"] + +## Reduces the initial map size for llmp +llmp_small_maps = ["alloc"] + + +[build-dependencies] +rustversion = { workspace = true } + +[dev-dependencies] + +[dependencies] +# Document all features of this crate (for `cargo doc`) +document-features = { workspace = true, optional = true } +miniz_oxide = { version = "0.8.0", optional = true } +hostname = { version = "0.4.0", optional = true } # Is there really no gethostname in the stdlib? +postcard = { workspace = true, optional = true } # no_std compatible serde serialization format +log = { workspace = true } +tuple_list = { version = "0.1.3" } +libafl_bolts = { workspace = true } +shmem_providers = { workspace = true } + +[[example]] +name = "llmp_test" +path = "./examples/llmp_test/main.rs" +required-features = ["std"] + +[lints] +workspace = true diff --git a/crates/ll_mp/LICENSE-APACHE b/crates/ll_mp/LICENSE-APACHE new file mode 120000 index 00000000000..965b606f331 --- /dev/null +++ b/crates/ll_mp/LICENSE-APACHE @@ -0,0 +1 @@ +../LICENSE-APACHE \ No newline at end of file diff --git a/crates/ll_mp/LICENSE-MIT b/crates/ll_mp/LICENSE-MIT new file mode 120000 index 00000000000..76219eb72e8 --- /dev/null +++ b/crates/ll_mp/LICENSE-MIT @@ -0,0 +1 @@ +../LICENSE-MIT \ No newline at end of file diff --git a/crates/ll_mp/README.md b/crates/ll_mp/README.md new file mode 100644 index 00000000000..0a638ac1244 --- /dev/null +++ b/crates/ll_mp/README.md @@ -0,0 +1,58 @@ +# LibAFL_bolts: OS and Fuzzer Dev's Libary Collection. + + LibAFL logo + +The `libafl_bolts` crate exposes a lot of low-level features of LibAFL for projects that are unrelated to fuzzing, or just fuzzers completely different to LibAFL. +Some cross-platform things in bolts include (but are not limited to): + +* SerdeAnyMap: a map that stores and retrieves elements by type and is serializable and deserializable +* ShMem: A cross-platform (Windows, Linux, Android, MacOS) shared memory implementation +* LLMP: A fast, lock-free IPC mechanism via SharedMap +* Core_affinity: A maintained version of `core_affinity` that can be used to get core information and bind processes to cores +* Rands: Fast random number generators for fuzzing (like [RomuRand](https://www.romu-random.org/)) +* MiniBSOD: get and print information about the current process state including important registers. +* Tuples: Haskel-like compile-time tuple lists +* Os: OS specific stuff like signal handling, windows exception handling, pipes, and helpers for `fork` + +LibAFL_bolts is written and maintained by + +* [Andrea Fioraldi](https://twitter.com/andreafioraldi) +* [Dominik Maier](https://twitter.com/domenuk) +* [s1341](https://twitter.com/srubenst1341) +* [Dongjia Zhang](https://github.com/tokatoka) +* [Addison Crump](https://github.com/addisoncrump) + +## Contributing + +For bugs, feel free to open issues or contact us directly. Thank you for your support. <3 + +Even though we will gladly assist you in finishing up your PR, try to +- keep all the crates compiling with *stable* rust (hide the eventual non-stable code under [`cfg`s](https://github.com/AFLplusplus/LibAFL/blob/main/libafl/build.rs#L26)) +- run `cargo nightly fmt` on your code before pushing +- check the output of `cargo clippy --all` or `./clippy.sh` +- run `cargo build --no-default-features` to check for `no_std` compatibility (and possibly add `#[cfg(feature = "std")]`) to hide parts of your code. + +Some of the parts in this list may be hard, don't be afraid to open a PR if you cannot fix them by yourself, so we can help. + +#### License + + +Licensed under either of Apache License, Version +2.0 or MIT license at your option. + + +
+ + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in this crate by you, as defined in the Apache-2.0 license, shall +be dual licensed as above, without any additional terms or conditions. + + +
+ + +Dependencies under more restrictive licenses, such as GPL or AGPL, can be enabled +using the respective feature in each crate when it is present, such as the +'agpl' feature of the libafl crate. + diff --git a/crates/ll_mp/examples/llmp_test/main.rs b/crates/ll_mp/examples/llmp_test/main.rs new file mode 100644 index 00000000000..2ac4d09413b --- /dev/null +++ b/crates/ll_mp/examples/llmp_test/main.rs @@ -0,0 +1,254 @@ +/*! +This shows how llmp can be used directly, without libafl abstractions +*/ +extern crate alloc; + +use core::marker::PhantomData; +#[cfg(all(feature = "std", not(target_os = "haiku")))] +use core::num::NonZeroUsize; +#[cfg(not(target_os = "haiku"))] +use core::time::Duration; +#[cfg(all(feature = "std", not(target_os = "haiku")))] +use std::{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}, +}; +use tuple_list::tuple_list; + +#[cfg(all(feature = "std", not(target_os = "haiku")))] +const _TAG_SIMPLE_U32_V1: Tag = Tag(0x5130_0321); +#[cfg(all(feature = "std", not(target_os = "haiku")))] +const _TAG_MATH_RESULT_V1: Tag = Tag(0x7747_4331); +#[cfg(all(feature = "std", not(target_os = "haiku")))] +const _TAG_1MEG_V1: Tag = Tag(0xB111_1161); + +/// The time the broker will wait for things to happen before printing a message +#[cfg(all(feature = "std", not(target_os = "haiku")))] +const BROKER_TIMEOUT: Duration = Duration::from_secs(10); + +/// How long the broker may sleep between forwarding a new chunk of sent messages +#[cfg(all(feature = "std", not(target_os = "haiku")))] +const SLEEP_BETWEEN_FORWARDS: Duration = Duration::from_millis(5); + +#[cfg(all(feature = "std", not(target_os = "haiku")))] +static LOGGER: SimpleStderrLogger = SimpleStderrLogger::new(); + +#[cfg(all(feature = "std", not(target_os = "haiku")))] +fn adder_loop(port: u16) -> Result<(), Box> { + let shmem_provider = StdShMemProvider::new()?; + let mut client = llmp::LlmpClient::create_attach_to_tcp(shmem_provider, port)?; + let mut last_result: u32 = 0; + let mut current_result: u32 = 0; + loop { + let mut msg_counter = 0; + loop { + let Some((sender, tag, buf)) = client.recv_buf()? else { + break; + }; + msg_counter += 1; + match tag { + _TAG_SIMPLE_U32_V1 => { + current_result = + current_result.wrapping_add(u32::from_le_bytes(buf.try_into()?)); + } + _ => println!( + "Adder Client ignored unknown message {:?} from client {:?} with {} bytes", + tag, + sender, + buf.len() + ), + } + } + + if current_result != last_result { + println!("Adder handled {msg_counter} messages, reporting {current_result} to broker"); + + client.send_buf(_TAG_MATH_RESULT_V1, ¤t_result.to_le_bytes())?; + last_result = current_result; + } + + thread::sleep(time::Duration::from_millis(100)); + } +} + +#[cfg(all(feature = "std", not(target_os = "haiku")))] +fn large_msg_loop(port: u16) -> Result<(), Box> { + let mut client = llmp::LlmpClient::create_attach_to_tcp(StdShMemProvider::new()?, port)?; + + #[cfg(not(target_vendor = "apple"))] + let meg_buf = vec![1u8; 1 << 20]; + #[cfg(target_vendor = "apple")] + let meg_buf = vec![1u8; 1 << 19]; + + loop { + client.send_buf(_TAG_1MEG_V1, &meg_buf)?; + #[cfg(not(target_vendor = "apple"))] + println!("Sending the next megabyte"); + #[cfg(target_vendor = "apple")] + println!("Sending the next half megabyte (Apple had issues with >1 meg)"); + thread::sleep(time::Duration::from_millis(100)); + } +} + +pub struct LlmpExampleHook { + phantom: PhantomData, +} + +impl LlmpExampleHook { + #[must_use] + pub fn new() -> Self { + Self { + phantom: PhantomData, + } + } +} + +impl Default for LlmpExampleHook { + fn default() -> Self { + Self::new() + } +} + +#[cfg(all(feature = "std", not(target_os = "haiku")))] +impl LlmpHook for LlmpExampleHook +where + SP: ShMemProvider + 'static, +{ + fn on_new_message( + &mut self, + _broker_inner: &mut LlmpBrokerInner, + client_id: ClientId, + msg_tag: &mut Tag, + _msg_flags: &mut Flags, + msg: &mut [u8], + _new_msgs: &mut Vec<(Tag, Flags, Vec)>, + ) -> Result { + match *msg_tag { + _TAG_SIMPLE_U32_V1 => { + println!( + "Client {:?} sent message: {:?}", + client_id, + u32::from_le_bytes(msg.try_into()?) + ); + Ok(LlmpMsgHookResult::ForwardToClients) + } + _TAG_MATH_RESULT_V1 => { + println!( + "Adder Client has this current result: {:?}", + u32::from_le_bytes(msg.try_into()?) + ); + Ok(LlmpMsgHookResult::Handled) + } + _ => { + println!("Unknown message id received: {msg_tag:?}"); + Ok(LlmpMsgHookResult::ForwardToClients) + } + } + } + + fn on_timeout(&mut self) -> Result<(), Error> { + println!( + "No client did anything for {} seconds..", + BROKER_TIMEOUT.as_secs() + ); + + Ok(()) + } +} + +#[cfg(target_os = "haiku")] +fn main() { + eprintln!("LLMP example is currently not supported on no_std. Implement ShMem for no_std."); +} + +#[cfg(not(target_os = "haiku"))] +fn main() -> Result<(), Box> { + /* The main node has a broker, and a few worker threads */ + + use libafl_bolts::llmp::Broker; + + let mode = std::env::args() + .nth(1) + .expect("no mode specified, chose 'broker', 'b2b', 'ctr', 'adder', 'large', or 'exiting'"); + let port: u16 = std::env::args() + .nth(2) + .unwrap_or_else(|| "1337".into()) + .parse::()?; + // in the b2b use-case, this is our "own" port, we connect to the "normal" broker node on startup. + let b2b_port: u16 = std::env::args() + .nth(3) + .unwrap_or_else(|| "4242".into()) + .parse::()?; + + log::set_logger(&LOGGER).unwrap(); + log::set_max_level(log::LevelFilter::Trace); + println!("Launching in mode {mode} on port {port}"); + + match mode.as_str() { + "broker" => { + let mut broker = llmp::LlmpBroker::new( + StdShMemProvider::new()?, + tuple_list!(LlmpExampleHook::new()), + )?; + broker.inner_mut().launch_tcp_listener_on(port)?; + // Exit when we got at least _n_ nodes, and all of them quit. + broker.set_exit_after(NonZeroUsize::new(1_usize).unwrap()); + broker.loop_with_timeouts(BROKER_TIMEOUT, Some(SLEEP_BETWEEN_FORWARDS)); + } + "b2b" => { + let mut broker = llmp::LlmpBroker::new( + StdShMemProvider::new()?, + tuple_list!(LlmpExampleHook::new()), + )?; + broker.inner_mut().launch_tcp_listener_on(b2b_port)?; + // connect back to the main broker. + broker.inner_mut().connect_b2b(("127.0.0.1", port))?; + broker.loop_with_timeouts(BROKER_TIMEOUT, Some(SLEEP_BETWEEN_FORWARDS)); + } + "ctr" => { + let mut client = + llmp::LlmpClient::create_attach_to_tcp(StdShMemProvider::new()?, port)?; + let mut counter: u32 = 0; + loop { + counter = counter.wrapping_add(1); + client.send_buf(_TAG_SIMPLE_U32_V1, &counter.to_le_bytes())?; + println!("CTR Client writing {counter}"); + thread::sleep(Duration::from_secs(1)); + } + } + "adder" => { + adder_loop(port)?; + } + "large" => { + large_msg_loop(port)?; + } + "exiting" => { + let mut client = + llmp::LlmpClient::create_attach_to_tcp(StdShMemProvider::new()?, port)?; + for i in 0..10_u32 { + client.send_buf(_TAG_SIMPLE_U32_V1, &i.to_le_bytes())?; + println!("Exiting Client writing {i}"); + thread::sleep(Duration::from_millis(10)); + } + log::info!("Exiting Client exits"); + client.sender_mut().send_exiting()?; + + // there is another way to tell that this client wants to exit. + // one is to call client.sender_mut().send_exiting()?; + // you can disconnet the client in this way as long as this client in an unrecoverable state (like in a crash handler) + // another way to do this is through the detach_from_broker() call + // you can call detach_from_broker(port); to notify the broker that this broker wants to exit + // This one is usually for the event restarter to cut off the connection when the client has crashed. + // In that case we don't have access to the llmp client of the client anymore, but we can use detach_from_broker instead + } + _ => { + println!("No valid mode supplied"); + } + } + Ok(()) +} diff --git a/crates/libafl_bolts/src/llmp.rs b/crates/ll_mp/src/lib.rs similarity index 99% rename from crates/libafl_bolts/src/llmp.rs rename to crates/ll_mp/src/lib.rs index 2b55ca5a6e1..21361fd5608 100644 --- a/crates/libafl_bolts/src/llmp.rs +++ b/crates/ll_mp/src/lib.rs @@ -56,6 +56,56 @@ For broker2broker communication, all messages are forwarded via network sockets. Check out the `llmp_test` example in ./examples, or build it with `cargo run --example llmp_test`. */ +#![doc = include_str!("../../../README.md")] +/*! */ +#![cfg_attr(feature = "document-features", doc = document_features::document_features!())] +#![no_std] +#![cfg_attr(not(test), warn( + missing_debug_implementations, + missing_docs, + //trivial_casts, + trivial_numeric_casts, + unused_extern_crates, + unused_import_braces, + unused_qualifications, + //unused_results +))] +#![cfg_attr(test, deny( + missing_debug_implementations, + missing_docs, + //trivial_casts, + trivial_numeric_casts, + unused_extern_crates, + unused_import_braces, + unused_qualifications, + unused_must_use, + //unused_results +))] +#![cfg_attr( + test, + deny( + bad_style, + dead_code, + improper_ctypes, + non_shorthand_field_patterns, + no_mangle_generic_items, + overflowing_literals, + path_statements, + patterns_in_fns_without_body, + unconditional_recursion, + unused, + unused_allocation, + unused_comparisons, + unused_parens, + while_true + ) +)] + +#[cfg(feature = "std")] +#[macro_use] +extern crate std; +#[doc(hidden)] +pub extern crate alloc; #[cfg(feature = "std")] use alloc::boxed::Box; @@ -90,10 +140,14 @@ use std::{ #[cfg(all(debug_assertions, feature = "llmp_debug", feature = "std"))] use backtrace::Backtrace; +use libafl_bolts::{ClientId, Error}; +#[cfg(feature = "std")] +use libafl_bolts::{IP_LOCALHOST, current_time}; #[cfg(all(unix, feature = "std"))] #[cfg(not(any(target_os = "solaris", target_os = "illumos")))] use nix::sys::socket::{self, sockopt::ReusePort}; use serde::{Deserialize, Serialize}; +use shmem_providers::{ShMem, ShMemDescription, ShMemId, ShMemProvider}; #[cfg(feature = "std")] use tuple_list::tuple_list; @@ -103,12 +157,6 @@ use crate::os::unix_signals::setup_signal_handler; use crate::os::unix_signals::{Signal, SignalHandler, siginfo_t, ucontext_t}; #[cfg(all(windows, feature = "std"))] use crate::os::windows_exceptions::{CtrlHandler, setup_ctrl_handler}; -use crate::{ - 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. diff --git a/crates/minibsod/Cargo.toml b/crates/minibsod/Cargo.toml new file mode 100644 index 00000000000..98362da0702 --- /dev/null +++ b/crates/minibsod/Cargo.toml @@ -0,0 +1,56 @@ +[package] +name = "ownedref" +version.workspace = true +authors = [ + "Andrea Fioraldi ", + "Dominik Maier ", +] +description = "Library to pass around references that will be owned types on deserialization" +documentation = "https://docs.rs/libafl" +repository = "https://github.com/AFLplusplus/LibAFL/" +readme = "./README.md" +license = "MIT OR Apache-2.0" +keywords = ["os", "shmem", "no-std"] +edition = "2024" +rust-version = "1.87" +categories = [ + "embedded", + "os", + "no-std", +] + +[package.metadata.docs.rs] +features = ["document-features"] +all-features = true + +[features] +default = [ + "std", + "alloc", +] +document-features = ["dep:document-features"] + +#! # Feature Flags +#! ### General Features + +## Enables features that need rust's `std` lib to work, like print, env, ... support +std = [ +] + +## Enables all features that allocate in `no_std` +alloc = [] + +## Stores the backtraces of all generated `Error`s. Good for debugging, but may come with a slight performance hit. +errors_backtrace = ["backtrace"] + +[build-dependencies] +rustversion = { workspace = true } + +[dev-dependencies] + +[dependencies] +# Document all features of this crate (for `cargo doc`) +document-features = { workspace = true, optional = true } + +[lints] +workspace = true diff --git a/crates/minibsod/LICENSE-APACHE b/crates/minibsod/LICENSE-APACHE new file mode 120000 index 00000000000..965b606f331 --- /dev/null +++ b/crates/minibsod/LICENSE-APACHE @@ -0,0 +1 @@ +../LICENSE-APACHE \ No newline at end of file diff --git a/crates/minibsod/LICENSE-MIT b/crates/minibsod/LICENSE-MIT new file mode 120000 index 00000000000..76219eb72e8 --- /dev/null +++ b/crates/minibsod/LICENSE-MIT @@ -0,0 +1 @@ +../LICENSE-MIT \ No newline at end of file diff --git a/crates/minibsod/README.md b/crates/minibsod/README.md new file mode 100644 index 00000000000..0a638ac1244 --- /dev/null +++ b/crates/minibsod/README.md @@ -0,0 +1,58 @@ +# LibAFL_bolts: OS and Fuzzer Dev's Libary Collection. + + LibAFL logo + +The `libafl_bolts` crate exposes a lot of low-level features of LibAFL for projects that are unrelated to fuzzing, or just fuzzers completely different to LibAFL. +Some cross-platform things in bolts include (but are not limited to): + +* SerdeAnyMap: a map that stores and retrieves elements by type and is serializable and deserializable +* ShMem: A cross-platform (Windows, Linux, Android, MacOS) shared memory implementation +* LLMP: A fast, lock-free IPC mechanism via SharedMap +* Core_affinity: A maintained version of `core_affinity` that can be used to get core information and bind processes to cores +* Rands: Fast random number generators for fuzzing (like [RomuRand](https://www.romu-random.org/)) +* MiniBSOD: get and print information about the current process state including important registers. +* Tuples: Haskel-like compile-time tuple lists +* Os: OS specific stuff like signal handling, windows exception handling, pipes, and helpers for `fork` + +LibAFL_bolts is written and maintained by + +* [Andrea Fioraldi](https://twitter.com/andreafioraldi) +* [Dominik Maier](https://twitter.com/domenuk) +* [s1341](https://twitter.com/srubenst1341) +* [Dongjia Zhang](https://github.com/tokatoka) +* [Addison Crump](https://github.com/addisoncrump) + +## Contributing + +For bugs, feel free to open issues or contact us directly. Thank you for your support. <3 + +Even though we will gladly assist you in finishing up your PR, try to +- keep all the crates compiling with *stable* rust (hide the eventual non-stable code under [`cfg`s](https://github.com/AFLplusplus/LibAFL/blob/main/libafl/build.rs#L26)) +- run `cargo nightly fmt` on your code before pushing +- check the output of `cargo clippy --all` or `./clippy.sh` +- run `cargo build --no-default-features` to check for `no_std` compatibility (and possibly add `#[cfg(feature = "std")]`) to hide parts of your code. + +Some of the parts in this list may be hard, don't be afraid to open a PR if you cannot fix them by yourself, so we can help. + +#### License + + +Licensed under either of Apache License, Version +2.0 or MIT license at your option. + + +
+ + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in this crate by you, as defined in the Apache-2.0 license, shall +be dual licensed as above, without any additional terms or conditions. + + +
+ + +Dependencies under more restrictive licenses, such as GPL or AGPL, can be enabled +using the respective feature in each crate when it is present, such as the +'agpl' feature of the libafl crate. + diff --git a/crates/minibsod/src/lib.rs b/crates/minibsod/src/lib.rs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/crates/ownedref/Cargo.toml b/crates/ownedref/Cargo.toml new file mode 100644 index 00000000000..98362da0702 --- /dev/null +++ b/crates/ownedref/Cargo.toml @@ -0,0 +1,56 @@ +[package] +name = "ownedref" +version.workspace = true +authors = [ + "Andrea Fioraldi ", + "Dominik Maier ", +] +description = "Library to pass around references that will be owned types on deserialization" +documentation = "https://docs.rs/libafl" +repository = "https://github.com/AFLplusplus/LibAFL/" +readme = "./README.md" +license = "MIT OR Apache-2.0" +keywords = ["os", "shmem", "no-std"] +edition = "2024" +rust-version = "1.87" +categories = [ + "embedded", + "os", + "no-std", +] + +[package.metadata.docs.rs] +features = ["document-features"] +all-features = true + +[features] +default = [ + "std", + "alloc", +] +document-features = ["dep:document-features"] + +#! # Feature Flags +#! ### General Features + +## Enables features that need rust's `std` lib to work, like print, env, ... support +std = [ +] + +## Enables all features that allocate in `no_std` +alloc = [] + +## Stores the backtraces of all generated `Error`s. Good for debugging, but may come with a slight performance hit. +errors_backtrace = ["backtrace"] + +[build-dependencies] +rustversion = { workspace = true } + +[dev-dependencies] + +[dependencies] +# Document all features of this crate (for `cargo doc`) +document-features = { workspace = true, optional = true } + +[lints] +workspace = true diff --git a/crates/ownedref/LICENSE-APACHE b/crates/ownedref/LICENSE-APACHE new file mode 120000 index 00000000000..965b606f331 --- /dev/null +++ b/crates/ownedref/LICENSE-APACHE @@ -0,0 +1 @@ +../LICENSE-APACHE \ No newline at end of file diff --git a/crates/ownedref/LICENSE-MIT b/crates/ownedref/LICENSE-MIT new file mode 120000 index 00000000000..76219eb72e8 --- /dev/null +++ b/crates/ownedref/LICENSE-MIT @@ -0,0 +1 @@ +../LICENSE-MIT \ No newline at end of file diff --git a/crates/ownedref/README.md b/crates/ownedref/README.md new file mode 100644 index 00000000000..0a638ac1244 --- /dev/null +++ b/crates/ownedref/README.md @@ -0,0 +1,58 @@ +# LibAFL_bolts: OS and Fuzzer Dev's Libary Collection. + + LibAFL logo + +The `libafl_bolts` crate exposes a lot of low-level features of LibAFL for projects that are unrelated to fuzzing, or just fuzzers completely different to LibAFL. +Some cross-platform things in bolts include (but are not limited to): + +* SerdeAnyMap: a map that stores and retrieves elements by type and is serializable and deserializable +* ShMem: A cross-platform (Windows, Linux, Android, MacOS) shared memory implementation +* LLMP: A fast, lock-free IPC mechanism via SharedMap +* Core_affinity: A maintained version of `core_affinity` that can be used to get core information and bind processes to cores +* Rands: Fast random number generators for fuzzing (like [RomuRand](https://www.romu-random.org/)) +* MiniBSOD: get and print information about the current process state including important registers. +* Tuples: Haskel-like compile-time tuple lists +* Os: OS specific stuff like signal handling, windows exception handling, pipes, and helpers for `fork` + +LibAFL_bolts is written and maintained by + +* [Andrea Fioraldi](https://twitter.com/andreafioraldi) +* [Dominik Maier](https://twitter.com/domenuk) +* [s1341](https://twitter.com/srubenst1341) +* [Dongjia Zhang](https://github.com/tokatoka) +* [Addison Crump](https://github.com/addisoncrump) + +## Contributing + +For bugs, feel free to open issues or contact us directly. Thank you for your support. <3 + +Even though we will gladly assist you in finishing up your PR, try to +- keep all the crates compiling with *stable* rust (hide the eventual non-stable code under [`cfg`s](https://github.com/AFLplusplus/LibAFL/blob/main/libafl/build.rs#L26)) +- run `cargo nightly fmt` on your code before pushing +- check the output of `cargo clippy --all` or `./clippy.sh` +- run `cargo build --no-default-features` to check for `no_std` compatibility (and possibly add `#[cfg(feature = "std")]`) to hide parts of your code. + +Some of the parts in this list may be hard, don't be afraid to open a PR if you cannot fix them by yourself, so we can help. + +#### License + + +Licensed under either of Apache License, Version +2.0 or MIT license at your option. + + +
+ + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in this crate by you, as defined in the Apache-2.0 license, shall +be dual licensed as above, without any additional terms or conditions. + + +
+ + +Dependencies under more restrictive licenses, such as GPL or AGPL, can be enabled +using the respective feature in each crate when it is present, such as the +'agpl' feature of the libafl crate. + diff --git a/crates/libafl_bolts/src/ownedref.rs b/crates/ownedref/src/lib.rs similarity index 96% rename from crates/libafl_bolts/src/ownedref.rs rename to crates/ownedref/src/lib.rs index 10a3f7de857..b29cfa29462 100644 --- a/crates/libafl_bolts/src/ownedref.rs +++ b/crates/ownedref/src/lib.rs @@ -1,5 +1,59 @@ //! Wrappers that abstracts references (or pointers) and owned data accesses. -// The serialization is towards owned, allowing to serialize pointers without troubles. +//! The serialization is towards owned, allowing to serialize pointers without troubles. +#![doc = include_str!("../../../README.md")] +/*! */ +#![cfg_attr(feature = "document-features", doc = document_features::document_features!())] +#![no_std] +#![cfg_attr(not(test), warn( + missing_debug_implementations, + missing_docs, + //trivial_casts, + trivial_numeric_casts, + unused_extern_crates, + unused_import_braces, + unused_qualifications, + //unused_results +))] +#![cfg_attr(test, deny( + missing_debug_implementations, + missing_docs, + //trivial_casts, + trivial_numeric_casts, + unused_extern_crates, + unused_import_braces, + unused_qualifications, + unused_must_use, + //unused_results +))] +#![cfg_attr( + test, + deny( + bad_style, + dead_code, + improper_ctypes, + non_shorthand_field_patterns, + no_mangle_generic_items, + overflowing_literals, + path_statements, + patterns_in_fns_without_body, + unconditional_recursion, + unused, + unused_allocation, + unused_comparisons, + unused_parens, + while_true + ) +)] + +#[cfg(feature = "std")] +#[macro_use] +extern crate std; +#[doc(hidden)] +pub extern crate alloc; + + + +pub mod subrange; use alloc::{boxed::Box, vec::Vec}; use core::{ @@ -11,11 +65,10 @@ use core::{ slice::{Iter, IterMut, SliceIndex}, }; +use libafl_core::{AsSizedSlice, AsSizedSliceMut, AsSlice, AsSliceMut, IntoOwned}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use crate::{ - AsSizedSlice, AsSizedSliceMut, AsSlice, AsSliceMut, IntoOwned, Truncate, shmem::ShMem, -}; +use crate::{Truncate, shmem::ShMem}; /// Constant size array visitor for serde deserialization. /// Mostly taken from @@ -89,23 +142,6 @@ impl UnsafeMarker { } } -impl Truncate for &[T] { - fn truncate(&mut self, len: usize) { - *self = &self[..len]; - } -} - -impl Truncate for &mut [T] { - fn truncate(&mut self, len: usize) { - let value = core::mem::take(self); - let len = value.len().min(len); - let truncated = value - .get_mut(..len) - .expect("Truncate with len <= len() should always work"); - let _: &mut [T] = core::mem::replace(self, truncated); - } -} - /// Wrap a reference and convert to a [`Box`] on serialize #[derive(Debug)] pub enum OwnedRef<'a, T> diff --git a/crates/libafl_bolts/src/subrange.rs b/crates/ownedref/src/subrange.rs similarity index 99% rename from crates/libafl_bolts/src/subrange.rs rename to crates/ownedref/src/subrange.rs index 1228723a3a6..a8132973278 100644 --- a/crates/libafl_bolts/src/subrange.rs +++ b/crates/ownedref/src/subrange.rs @@ -7,8 +7,8 @@ use core::{ }; use crate::{ - HasLen, ownedref::{OwnedMutSlice, OwnedSlice}, + tuples::HasLen, }; /// An immutable contiguous subslice of a byte slice. diff --git a/crates/serde_anymap/Cargo.toml b/crates/serde_anymap/Cargo.toml new file mode 100644 index 00000000000..98362da0702 --- /dev/null +++ b/crates/serde_anymap/Cargo.toml @@ -0,0 +1,56 @@ +[package] +name = "ownedref" +version.workspace = true +authors = [ + "Andrea Fioraldi ", + "Dominik Maier ", +] +description = "Library to pass around references that will be owned types on deserialization" +documentation = "https://docs.rs/libafl" +repository = "https://github.com/AFLplusplus/LibAFL/" +readme = "./README.md" +license = "MIT OR Apache-2.0" +keywords = ["os", "shmem", "no-std"] +edition = "2024" +rust-version = "1.87" +categories = [ + "embedded", + "os", + "no-std", +] + +[package.metadata.docs.rs] +features = ["document-features"] +all-features = true + +[features] +default = [ + "std", + "alloc", +] +document-features = ["dep:document-features"] + +#! # Feature Flags +#! ### General Features + +## Enables features that need rust's `std` lib to work, like print, env, ... support +std = [ +] + +## Enables all features that allocate in `no_std` +alloc = [] + +## Stores the backtraces of all generated `Error`s. Good for debugging, but may come with a slight performance hit. +errors_backtrace = ["backtrace"] + +[build-dependencies] +rustversion = { workspace = true } + +[dev-dependencies] + +[dependencies] +# Document all features of this crate (for `cargo doc`) +document-features = { workspace = true, optional = true } + +[lints] +workspace = true diff --git a/crates/serde_anymap/LICENSE-APACHE b/crates/serde_anymap/LICENSE-APACHE new file mode 120000 index 00000000000..965b606f331 --- /dev/null +++ b/crates/serde_anymap/LICENSE-APACHE @@ -0,0 +1 @@ +../LICENSE-APACHE \ No newline at end of file diff --git a/crates/serde_anymap/LICENSE-MIT b/crates/serde_anymap/LICENSE-MIT new file mode 120000 index 00000000000..76219eb72e8 --- /dev/null +++ b/crates/serde_anymap/LICENSE-MIT @@ -0,0 +1 @@ +../LICENSE-MIT \ No newline at end of file diff --git a/crates/serde_anymap/README.md b/crates/serde_anymap/README.md new file mode 100644 index 00000000000..0a638ac1244 --- /dev/null +++ b/crates/serde_anymap/README.md @@ -0,0 +1,58 @@ +# LibAFL_bolts: OS and Fuzzer Dev's Libary Collection. + + LibAFL logo + +The `libafl_bolts` crate exposes a lot of low-level features of LibAFL for projects that are unrelated to fuzzing, or just fuzzers completely different to LibAFL. +Some cross-platform things in bolts include (but are not limited to): + +* SerdeAnyMap: a map that stores and retrieves elements by type and is serializable and deserializable +* ShMem: A cross-platform (Windows, Linux, Android, MacOS) shared memory implementation +* LLMP: A fast, lock-free IPC mechanism via SharedMap +* Core_affinity: A maintained version of `core_affinity` that can be used to get core information and bind processes to cores +* Rands: Fast random number generators for fuzzing (like [RomuRand](https://www.romu-random.org/)) +* MiniBSOD: get and print information about the current process state including important registers. +* Tuples: Haskel-like compile-time tuple lists +* Os: OS specific stuff like signal handling, windows exception handling, pipes, and helpers for `fork` + +LibAFL_bolts is written and maintained by + +* [Andrea Fioraldi](https://twitter.com/andreafioraldi) +* [Dominik Maier](https://twitter.com/domenuk) +* [s1341](https://twitter.com/srubenst1341) +* [Dongjia Zhang](https://github.com/tokatoka) +* [Addison Crump](https://github.com/addisoncrump) + +## Contributing + +For bugs, feel free to open issues or contact us directly. Thank you for your support. <3 + +Even though we will gladly assist you in finishing up your PR, try to +- keep all the crates compiling with *stable* rust (hide the eventual non-stable code under [`cfg`s](https://github.com/AFLplusplus/LibAFL/blob/main/libafl/build.rs#L26)) +- run `cargo nightly fmt` on your code before pushing +- check the output of `cargo clippy --all` or `./clippy.sh` +- run `cargo build --no-default-features` to check for `no_std` compatibility (and possibly add `#[cfg(feature = "std")]`) to hide parts of your code. + +Some of the parts in this list may be hard, don't be afraid to open a PR if you cannot fix them by yourself, so we can help. + +#### License + + +Licensed under either of Apache License, Version +2.0 or MIT license at your option. + + +
+ + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in this crate by you, as defined in the Apache-2.0 license, shall +be dual licensed as above, without any additional terms or conditions. + + +
+ + +Dependencies under more restrictive licenses, such as GPL or AGPL, can be enabled +using the respective feature in each crate when it is present, such as the +'agpl' feature of the libafl crate. + diff --git a/crates/serde_anymap/src/lib.rs b/crates/serde_anymap/src/lib.rs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/crates/shmem_providers/Cargo.toml b/crates/shmem_providers/Cargo.toml new file mode 100644 index 00000000000..7a1dff7e9b8 --- /dev/null +++ b/crates/shmem_providers/Cargo.toml @@ -0,0 +1,69 @@ +[package] +name = "shmem_providers" +version.workspace = true +authors = [ + "Andrea Fioraldi ", + "Dominik Maier ", +] +description = "Platform independent shared memory providers for Windows, Linux, Android, iOS, ..." +documentation = "https://docs.rs/libafl" +repository = "https://github.com/AFLplusplus/LibAFL/" +readme = "./README.md" +license = "MIT OR Apache-2.0" +keywords = ["os", "shmem", "no-std"] +edition = "2024" +rust-version = "1.87" +categories = ["embedded", "os", "no-std"] + +[package.metadata.docs.rs] +features = ["document-features"] +all-features = true + +[features] +default = ["std", "alloc"] +document-features = ["dep:document-features"] + +#! # Feature Flags +#! ### General Features + +## Enables features that need rust's `std` lib to work, like print, env, ... support +std = ["libafl_core/std", "uds", "nix", "libafl_core/nix", "serial_test"] + +## Enables all features that allocate in `no_std` +alloc = ["libafl_core/alloc", "hashbrown", "postcard"] + +[build-dependencies] +rustversion = { workspace = true } + +[dev-dependencies] + +[dependencies] +# Document all features of this crate (for `cargo doc`) +document-features = { workspace = true, optional = true } +fast_rands = { workspace = true } +libafl_core = { workspace = true, features = ["postcard"] } +log = { workspace = true } +postcard = { workspace = true, optional = true } # no_std compatible serde serialization format +serde = { workspace = true, features = ["derive"] } +hashbrown = { workspace = true, features = [ + "serde", + "ahash", +], default-features = false, optional = true } # A faster hashmap, nostd compatible + +# optional-dev deps (change when target.'cfg(accessible(::std))'.test-dependencies will be stable) +serial_test = { workspace = true, optional = true, default-features = false, features = [ + "logging", +] } + +[target.'cfg(unix)'.dependencies] +libc = { workspace = true } +uds = { version = "0.4.2", optional = true, default-features = false } +nix = { workspace = true, optional = true, default-features = false, features = [ + "fs", + "signal", + "socket", + "poll", +] } + +[lints] +workspace = true diff --git a/crates/shmem_providers/LICENSE-APACHE b/crates/shmem_providers/LICENSE-APACHE new file mode 120000 index 00000000000..965b606f331 --- /dev/null +++ b/crates/shmem_providers/LICENSE-APACHE @@ -0,0 +1 @@ +../LICENSE-APACHE \ No newline at end of file diff --git a/crates/shmem_providers/LICENSE-MIT b/crates/shmem_providers/LICENSE-MIT new file mode 120000 index 00000000000..76219eb72e8 --- /dev/null +++ b/crates/shmem_providers/LICENSE-MIT @@ -0,0 +1 @@ +../LICENSE-MIT \ No newline at end of file diff --git a/crates/shmem_providers/README.md b/crates/shmem_providers/README.md new file mode 100644 index 00000000000..0a638ac1244 --- /dev/null +++ b/crates/shmem_providers/README.md @@ -0,0 +1,58 @@ +# LibAFL_bolts: OS and Fuzzer Dev's Libary Collection. + + LibAFL logo + +The `libafl_bolts` crate exposes a lot of low-level features of LibAFL for projects that are unrelated to fuzzing, or just fuzzers completely different to LibAFL. +Some cross-platform things in bolts include (but are not limited to): + +* SerdeAnyMap: a map that stores and retrieves elements by type and is serializable and deserializable +* ShMem: A cross-platform (Windows, Linux, Android, MacOS) shared memory implementation +* LLMP: A fast, lock-free IPC mechanism via SharedMap +* Core_affinity: A maintained version of `core_affinity` that can be used to get core information and bind processes to cores +* Rands: Fast random number generators for fuzzing (like [RomuRand](https://www.romu-random.org/)) +* MiniBSOD: get and print information about the current process state including important registers. +* Tuples: Haskel-like compile-time tuple lists +* Os: OS specific stuff like signal handling, windows exception handling, pipes, and helpers for `fork` + +LibAFL_bolts is written and maintained by + +* [Andrea Fioraldi](https://twitter.com/andreafioraldi) +* [Dominik Maier](https://twitter.com/domenuk) +* [s1341](https://twitter.com/srubenst1341) +* [Dongjia Zhang](https://github.com/tokatoka) +* [Addison Crump](https://github.com/addisoncrump) + +## Contributing + +For bugs, feel free to open issues or contact us directly. Thank you for your support. <3 + +Even though we will gladly assist you in finishing up your PR, try to +- keep all the crates compiling with *stable* rust (hide the eventual non-stable code under [`cfg`s](https://github.com/AFLplusplus/LibAFL/blob/main/libafl/build.rs#L26)) +- run `cargo nightly fmt` on your code before pushing +- check the output of `cargo clippy --all` or `./clippy.sh` +- run `cargo build --no-default-features` to check for `no_std` compatibility (and possibly add `#[cfg(feature = "std")]`) to hide parts of your code. + +Some of the parts in this list may be hard, don't be afraid to open a PR if you cannot fix them by yourself, so we can help. + +#### License + + +Licensed under either of Apache License, Version +2.0 or MIT license at your option. + + +
+ + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in this crate by you, as defined in the Apache-2.0 license, shall +be dual licensed as above, without any additional terms or conditions. + + +
+ + +Dependencies under more restrictive licenses, such as GPL or AGPL, can be enabled +using the respective feature in each crate when it is present, such as the +'agpl' feature of the libafl crate. + diff --git a/crates/libafl_bolts/src/shmem.rs b/crates/shmem_providers/src/lib.rs similarity index 97% rename from crates/libafl_bolts/src/shmem.rs rename to crates/shmem_providers/src/lib.rs index c4dda359427..6cc718de9bc 100644 --- a/crates/libafl_bolts/src/shmem.rs +++ b/crates/shmem_providers/src/lib.rs @@ -1,5 +1,62 @@ //! A generic shared memory region to be used by any functions (queues or feedbacks //! too.) +#![doc = include_str!("../../../README.md")] +/*! */ +#![cfg_attr(feature = "document-features", doc = document_features::document_features!())] +#![no_std] +#![cfg_attr(not(test), warn( + missing_debug_implementations, + missing_docs, + //trivial_casts, + trivial_numeric_casts, + unused_extern_crates, + unused_import_braces, + unused_qualifications, + //unused_results +))] +#![cfg_attr(test, deny( + missing_debug_implementations, + missing_docs, + //trivial_casts, + trivial_numeric_casts, + unused_extern_crates, + unused_import_braces, + unused_qualifications, + unused_must_use, + //unused_results +))] +#![cfg_attr( + test, + deny( + bad_style, + dead_code, + improper_ctypes, + non_shorthand_field_patterns, + no_mangle_generic_items, + overflowing_literals, + path_statements, + patterns_in_fns_without_body, + unconditional_recursion, + unused, + unused_allocation, + unused_comparisons, + unused_parens, + while_true + ) +)] + +#[cfg(feature = "std")] +#[macro_use] +extern crate std; +#[doc(hidden)] +pub extern crate alloc; + +pub use libafl_core::Error; + +#[cfg(all(unix, feature = "std"))] +pub mod pipes; +#[cfg(all(feature = "std", unix, not(target_os = "haiku")))] +pub mod unix_shmem_server; #[cfg(feature = "alloc")] use alloc::{rc::Rc, string::ToString, vec::Vec}; @@ -29,11 +86,10 @@ 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; +use crate::pipes::Pipe; #[cfg(all(feature = "std", unix, not(target_os = "haiku")))] -pub use crate::os::unix_shmem_server::{ServedShMem, ServedShMemProvider, ShMemService}; +pub use crate::unix_shmem_server::{ServedShMem, ServedShMemProvider, ShMemService}; /// The standard sharedmem provider #[cfg(all(windows, feature = "std"))] @@ -683,16 +739,14 @@ pub mod unix_shmem { }; use std::{io, path::Path, process}; + use fast_rands::{Rand, StdRand}; + use libafl_core::Error; use libc::{ c_int, c_uchar, close, fcntl, ftruncate, mmap, munmap, shm_open, shm_unlink, shmat, shmctl, shmdt, shmget, }; - use crate::{ - Error, - rands::{Rand, StdRand}, - shmem::{ShMem, ShMemId, ShMemProvider}, - }; + use crate::{ShMem, ShMemId, ShMemProvider}; /// The max number of bytes used when generating names for [`MmapShMem`]s. pub const MAX_MMAP_FILENAME_LEN: usize = 20; @@ -1003,7 +1057,7 @@ pub mod unix_shmem { } fn new_shmem(&mut self, map_size: usize) -> Result { - let mut rand = StdRand::with_seed(crate::rands::random_seed()); + let mut rand = StdRand::with_seed(fast_rands::random_seed()); let id = rand.next() as u32; let mut full_file_name = format!("libafl_{}_{}", process::id(), id); // leave one byte space for the null byte. @@ -1798,7 +1852,7 @@ impl ShMemCursor { where SHM: DerefMut, { - use crate::AsSliceMut; + use libafl_core::AsSliceMut; &mut (self.inner.as_slice_mut()[self.pos..]) } } @@ -1852,7 +1906,7 @@ where let effective_new_pos = match pos { std::io::SeekFrom::Start(s) => s, std::io::SeekFrom::End(offset) => { - use crate::AsSlice; + use libafl_core::AsSlice; let map_len = self.inner.as_slice().len(); let signed_pos = i64::try_from(map_len).unwrap(); let effective = signed_pos.checked_add(offset).unwrap(); @@ -1877,12 +1931,10 @@ where #[cfg(all(feature = "std", not(target_os = "haiku")))] #[cfg(test)] mod tests { + use libafl_core::{AsSlice, AsSliceMut, Error}; use serial_test::serial; - use crate::{ - AsSlice, AsSliceMut, Error, - shmem::{ShMemProvider, StdShMemProvider}, - }; + use crate::{ShMemProvider, StdShMemProvider}; #[test] #[serial] @@ -1906,7 +1958,7 @@ mod tests { process::{Command, Stdio}, }; - use crate::shmem::{MmapShMemProvider, ShMem as _, ShMemId}; + use crate::{MmapShMemProvider, ShMem as _, ShMemId}; // relies on the fact that the ID in a ShMemDescription is always a string for MmapShMem match env::var("SHMEM_SIZE") { diff --git a/crates/libafl_bolts/src/os/pipes.rs b/crates/shmem_providers/src/pipes.rs similarity index 100% rename from crates/libafl_bolts/src/os/pipes.rs rename to crates/shmem_providers/src/pipes.rs diff --git a/crates/libafl_bolts/src/os/unix_shmem_server.rs b/crates/shmem_providers/src/unix_shmem_server.rs similarity index 99% rename from crates/libafl_bolts/src/os/unix_shmem_server.rs rename to crates/shmem_providers/src/unix_shmem_server.rs index 04fcb145bf8..98cb6114c42 100644 --- a/crates/libafl_bolts/src/os/unix_shmem_server.rs +++ b/crates/shmem_providers/src/unix_shmem_server.rs @@ -47,10 +47,7 @@ use serde::{Deserialize, Serialize}; #[cfg(all(unix, feature = "std"))] use uds::{UnixListenerExt, UnixSocketAddr, UnixStreamExt}; -use crate::{ - Error, - shmem::{ShMem, ShMemDescription, ShMemId, ShMemProvider}, -}; +use crate::{Error, ShMem, ShMemDescription, ShMemId, ShMemProvider}; /// The default server name for our abstract shmem server #[cfg(all(unix, not(target_vendor = "apple")))] diff --git a/crates/signal_handler/Cargo.toml b/crates/signal_handler/Cargo.toml new file mode 100644 index 00000000000..98362da0702 --- /dev/null +++ b/crates/signal_handler/Cargo.toml @@ -0,0 +1,56 @@ +[package] +name = "ownedref" +version.workspace = true +authors = [ + "Andrea Fioraldi ", + "Dominik Maier ", +] +description = "Library to pass around references that will be owned types on deserialization" +documentation = "https://docs.rs/libafl" +repository = "https://github.com/AFLplusplus/LibAFL/" +readme = "./README.md" +license = "MIT OR Apache-2.0" +keywords = ["os", "shmem", "no-std"] +edition = "2024" +rust-version = "1.87" +categories = [ + "embedded", + "os", + "no-std", +] + +[package.metadata.docs.rs] +features = ["document-features"] +all-features = true + +[features] +default = [ + "std", + "alloc", +] +document-features = ["dep:document-features"] + +#! # Feature Flags +#! ### General Features + +## Enables features that need rust's `std` lib to work, like print, env, ... support +std = [ +] + +## Enables all features that allocate in `no_std` +alloc = [] + +## Stores the backtraces of all generated `Error`s. Good for debugging, but may come with a slight performance hit. +errors_backtrace = ["backtrace"] + +[build-dependencies] +rustversion = { workspace = true } + +[dev-dependencies] + +[dependencies] +# Document all features of this crate (for `cargo doc`) +document-features = { workspace = true, optional = true } + +[lints] +workspace = true diff --git a/crates/signal_handler/LICENSE-APACHE b/crates/signal_handler/LICENSE-APACHE new file mode 120000 index 00000000000..965b606f331 --- /dev/null +++ b/crates/signal_handler/LICENSE-APACHE @@ -0,0 +1 @@ +../LICENSE-APACHE \ No newline at end of file diff --git a/crates/signal_handler/LICENSE-MIT b/crates/signal_handler/LICENSE-MIT new file mode 120000 index 00000000000..76219eb72e8 --- /dev/null +++ b/crates/signal_handler/LICENSE-MIT @@ -0,0 +1 @@ +../LICENSE-MIT \ No newline at end of file diff --git a/crates/signal_handler/README.md b/crates/signal_handler/README.md new file mode 100644 index 00000000000..0a638ac1244 --- /dev/null +++ b/crates/signal_handler/README.md @@ -0,0 +1,58 @@ +# LibAFL_bolts: OS and Fuzzer Dev's Libary Collection. + + LibAFL logo + +The `libafl_bolts` crate exposes a lot of low-level features of LibAFL for projects that are unrelated to fuzzing, or just fuzzers completely different to LibAFL. +Some cross-platform things in bolts include (but are not limited to): + +* SerdeAnyMap: a map that stores and retrieves elements by type and is serializable and deserializable +* ShMem: A cross-platform (Windows, Linux, Android, MacOS) shared memory implementation +* LLMP: A fast, lock-free IPC mechanism via SharedMap +* Core_affinity: A maintained version of `core_affinity` that can be used to get core information and bind processes to cores +* Rands: Fast random number generators for fuzzing (like [RomuRand](https://www.romu-random.org/)) +* MiniBSOD: get and print information about the current process state including important registers. +* Tuples: Haskel-like compile-time tuple lists +* Os: OS specific stuff like signal handling, windows exception handling, pipes, and helpers for `fork` + +LibAFL_bolts is written and maintained by + +* [Andrea Fioraldi](https://twitter.com/andreafioraldi) +* [Dominik Maier](https://twitter.com/domenuk) +* [s1341](https://twitter.com/srubenst1341) +* [Dongjia Zhang](https://github.com/tokatoka) +* [Addison Crump](https://github.com/addisoncrump) + +## Contributing + +For bugs, feel free to open issues or contact us directly. Thank you for your support. <3 + +Even though we will gladly assist you in finishing up your PR, try to +- keep all the crates compiling with *stable* rust (hide the eventual non-stable code under [`cfg`s](https://github.com/AFLplusplus/LibAFL/blob/main/libafl/build.rs#L26)) +- run `cargo nightly fmt` on your code before pushing +- check the output of `cargo clippy --all` or `./clippy.sh` +- run `cargo build --no-default-features` to check for `no_std` compatibility (and possibly add `#[cfg(feature = "std")]`) to hide parts of your code. + +Some of the parts in this list may be hard, don't be afraid to open a PR if you cannot fix them by yourself, so we can help. + +#### License + + +Licensed under either of Apache License, Version +2.0 or MIT license at your option. + + +
+ + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in this crate by you, as defined in the Apache-2.0 license, shall +be dual licensed as above, without any additional terms or conditions. + + +
+ + +Dependencies under more restrictive licenses, such as GPL or AGPL, can be enabled +using the respective feature in each crate when it is present, such as the +'agpl' feature of the libafl crate. + diff --git a/crates/signal_handler/src/lib.rs b/crates/signal_handler/src/lib.rs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/crates/tuplelist_ex/Cargo.toml b/crates/tuplelist_ex/Cargo.toml new file mode 100644 index 00000000000..98362da0702 --- /dev/null +++ b/crates/tuplelist_ex/Cargo.toml @@ -0,0 +1,56 @@ +[package] +name = "ownedref" +version.workspace = true +authors = [ + "Andrea Fioraldi ", + "Dominik Maier ", +] +description = "Library to pass around references that will be owned types on deserialization" +documentation = "https://docs.rs/libafl" +repository = "https://github.com/AFLplusplus/LibAFL/" +readme = "./README.md" +license = "MIT OR Apache-2.0" +keywords = ["os", "shmem", "no-std"] +edition = "2024" +rust-version = "1.87" +categories = [ + "embedded", + "os", + "no-std", +] + +[package.metadata.docs.rs] +features = ["document-features"] +all-features = true + +[features] +default = [ + "std", + "alloc", +] +document-features = ["dep:document-features"] + +#! # Feature Flags +#! ### General Features + +## Enables features that need rust's `std` lib to work, like print, env, ... support +std = [ +] + +## Enables all features that allocate in `no_std` +alloc = [] + +## Stores the backtraces of all generated `Error`s. Good for debugging, but may come with a slight performance hit. +errors_backtrace = ["backtrace"] + +[build-dependencies] +rustversion = { workspace = true } + +[dev-dependencies] + +[dependencies] +# Document all features of this crate (for `cargo doc`) +document-features = { workspace = true, optional = true } + +[lints] +workspace = true diff --git a/crates/tuplelist_ex/LICENSE-APACHE b/crates/tuplelist_ex/LICENSE-APACHE new file mode 120000 index 00000000000..965b606f331 --- /dev/null +++ b/crates/tuplelist_ex/LICENSE-APACHE @@ -0,0 +1 @@ +../LICENSE-APACHE \ No newline at end of file diff --git a/crates/tuplelist_ex/LICENSE-MIT b/crates/tuplelist_ex/LICENSE-MIT new file mode 120000 index 00000000000..76219eb72e8 --- /dev/null +++ b/crates/tuplelist_ex/LICENSE-MIT @@ -0,0 +1 @@ +../LICENSE-MIT \ No newline at end of file diff --git a/crates/tuplelist_ex/README.md b/crates/tuplelist_ex/README.md new file mode 100644 index 00000000000..0a638ac1244 --- /dev/null +++ b/crates/tuplelist_ex/README.md @@ -0,0 +1,58 @@ +# LibAFL_bolts: OS and Fuzzer Dev's Libary Collection. + + LibAFL logo + +The `libafl_bolts` crate exposes a lot of low-level features of LibAFL for projects that are unrelated to fuzzing, or just fuzzers completely different to LibAFL. +Some cross-platform things in bolts include (but are not limited to): + +* SerdeAnyMap: a map that stores and retrieves elements by type and is serializable and deserializable +* ShMem: A cross-platform (Windows, Linux, Android, MacOS) shared memory implementation +* LLMP: A fast, lock-free IPC mechanism via SharedMap +* Core_affinity: A maintained version of `core_affinity` that can be used to get core information and bind processes to cores +* Rands: Fast random number generators for fuzzing (like [RomuRand](https://www.romu-random.org/)) +* MiniBSOD: get and print information about the current process state including important registers. +* Tuples: Haskel-like compile-time tuple lists +* Os: OS specific stuff like signal handling, windows exception handling, pipes, and helpers for `fork` + +LibAFL_bolts is written and maintained by + +* [Andrea Fioraldi](https://twitter.com/andreafioraldi) +* [Dominik Maier](https://twitter.com/domenuk) +* [s1341](https://twitter.com/srubenst1341) +* [Dongjia Zhang](https://github.com/tokatoka) +* [Addison Crump](https://github.com/addisoncrump) + +## Contributing + +For bugs, feel free to open issues or contact us directly. Thank you for your support. <3 + +Even though we will gladly assist you in finishing up your PR, try to +- keep all the crates compiling with *stable* rust (hide the eventual non-stable code under [`cfg`s](https://github.com/AFLplusplus/LibAFL/blob/main/libafl/build.rs#L26)) +- run `cargo nightly fmt` on your code before pushing +- check the output of `cargo clippy --all` or `./clippy.sh` +- run `cargo build --no-default-features` to check for `no_std` compatibility (and possibly add `#[cfg(feature = "std")]`) to hide parts of your code. + +Some of the parts in this list may be hard, don't be afraid to open a PR if you cannot fix them by yourself, so we can help. + +#### License + + +Licensed under either of Apache License, Version +2.0 or MIT license at your option. + + +
+ + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in this crate by you, as defined in the Apache-2.0 license, shall +be dual licensed as above, without any additional terms or conditions. + + +
+ + +Dependencies under more restrictive licenses, such as GPL or AGPL, can be enabled +using the respective feature in each crate when it is present, such as the +'agpl' feature of the libafl crate. + diff --git a/crates/tuplelist_ex/src/lib.rs b/crates/tuplelist_ex/src/lib.rs new file mode 100644 index 00000000000..e69de29bb2d From c1b74f6d39da74e20872ab9901d4b4ce394d2d6d Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Fri, 11 Jul 2025 10:56:18 +0200 Subject: [PATCH 02/18] on avance toujours --- Cargo.toml | 6 + crates/{signal_handler => }/LICENSE-APACHE | 0 crates/{signal_handler => }/LICENSE-MIT | 0 .../Cargo.toml | 7 +- .../LICENSE-APACHE | 0 .../{tuplelist_ex => exceptional}/LICENSE-MIT | 0 .../{signal_handler => exceptional}/README.md | 0 crates/exceptional/src/lib.rs | 65 + .../os => exceptional/src}/unix_signals.rs | 0 .../src}/windows_exceptions.rs | 12 +- .../libafl_bolts/examples/llmp_test/main.rs | 254 ---- crates/libafl_bolts/src/lib.rs | 82 -- crates/libafl_bolts/src/minibsod.rs | 1258 ---------------- crates/libafl_bolts/src/{os/mod.rs => os.rs} | 11 - crates/libafl_bolts/src/simd.rs | 2 +- crates/minibsod/Cargo.toml | 12 +- crates/minibsod/src/lib.rs | 1308 +++++++++++++++++ .../{tuplelist_ex => no_std_time}/Cargo.toml | 7 +- crates/no_std_time/LICENSE-APACHE | 1 + crates/no_std_time/LICENSE-MIT | 1 + .../{tuplelist_ex => no_std_time}/README.md | 0 crates/no_std_time/src/lib.rs | 137 ++ .../src/time_counters.rs} | 0 crates/ownedref/Cargo.toml | 3 - crates/ownedref/src/lib.rs | 2 - crates/serde_anymap/Cargo.toml | 7 +- .../src/anymap.rs | 0 crates/serde_anymap/src/lib.rs | 54 + .../src/serdeany.rs | 0 crates/signal_handler/src/lib.rs | 0 crates/tuple_list_ex/Cargo.toml | 53 + crates/tuple_list_ex/LICENSE-APACHE | 1 + crates/tuple_list_ex/LICENSE-MIT | 1 + crates/tuple_list_ex/README.md | 58 + .../tuples.rs => tuple_list_ex/src/lib.rs} | 52 + crates/tuplelist_ex/src/lib.rs | 0 36 files changed, 1756 insertions(+), 1638 deletions(-) rename crates/{signal_handler => }/LICENSE-APACHE (100%) rename crates/{signal_handler => }/LICENSE-MIT (100%) rename crates/{signal_handler => exceptional}/Cargo.toml (79%) rename crates/{tuplelist_ex => exceptional}/LICENSE-APACHE (100%) rename crates/{tuplelist_ex => exceptional}/LICENSE-MIT (100%) rename crates/{signal_handler => exceptional}/README.md (100%) create mode 100644 crates/exceptional/src/lib.rs rename crates/{libafl_bolts/src/os => exceptional/src}/unix_signals.rs (100%) rename crates/{libafl_bolts/src/os => exceptional/src}/windows_exceptions.rs (98%) delete mode 100644 crates/libafl_bolts/examples/llmp_test/main.rs delete mode 100644 crates/libafl_bolts/src/minibsod.rs rename crates/libafl_bolts/src/{os/mod.rs => os.rs} (96%) rename crates/{tuplelist_ex => no_std_time}/Cargo.toml (79%) create mode 120000 crates/no_std_time/LICENSE-APACHE create mode 120000 crates/no_std_time/LICENSE-MIT rename crates/{tuplelist_ex => no_std_time}/README.md (100%) create mode 100644 crates/no_std_time/src/lib.rs rename crates/{libafl_bolts/src/cpu.rs => no_std_time/src/time_counters.rs} (100%) rename crates/{libafl_bolts => serde_anymap}/src/anymap.rs (100%) rename crates/{libafl_bolts => serde_anymap}/src/serdeany.rs (100%) delete mode 100644 crates/signal_handler/src/lib.rs create mode 100644 crates/tuple_list_ex/Cargo.toml create mode 120000 crates/tuple_list_ex/LICENSE-APACHE create mode 120000 crates/tuple_list_ex/LICENSE-MIT create mode 100644 crates/tuple_list_ex/README.md rename crates/{libafl_bolts/src/tuples.rs => tuple_list_ex/src/lib.rs} (95%) delete mode 100644 crates/tuplelist_ex/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 0bb69c606a0..dd0274a9ab2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,7 @@ resolver = "2" members = [ "crates/build_id2", "crates/core_affinity2", + "crates/exceptional", "crates/fast_rands", "crates/libafl", "crates/libafl_asan", @@ -29,7 +30,12 @@ members = [ "crates/libafl_concolic/test/dump_constraints", "crates/libafl_concolic/test/runtime_test", "crates/ll_mp", + "crates/minibsod", + "crates/no_std_time", + "crates/ownedref", + "crates/serde_anymap", "crates/shmem_providers", + "crates/tuple_list_ex", "utils/build_and_test_fuzzers", "utils/deexit", "utils/drcov_utils", diff --git a/crates/signal_handler/LICENSE-APACHE b/crates/LICENSE-APACHE similarity index 100% rename from crates/signal_handler/LICENSE-APACHE rename to crates/LICENSE-APACHE diff --git a/crates/signal_handler/LICENSE-MIT b/crates/LICENSE-MIT similarity index 100% rename from crates/signal_handler/LICENSE-MIT rename to crates/LICENSE-MIT diff --git a/crates/signal_handler/Cargo.toml b/crates/exceptional/Cargo.toml similarity index 79% rename from crates/signal_handler/Cargo.toml rename to crates/exceptional/Cargo.toml index 98362da0702..14a2aa67834 100644 --- a/crates/signal_handler/Cargo.toml +++ b/crates/exceptional/Cargo.toml @@ -1,11 +1,11 @@ [package] -name = "ownedref" +name = "exceptional" version.workspace = true authors = [ "Andrea Fioraldi ", "Dominik Maier ", ] -description = "Library to pass around references that will be owned types on deserialization" +description = "Everything for your exception and signal handling needs" documentation = "https://docs.rs/libafl" repository = "https://github.com/AFLplusplus/LibAFL/" readme = "./README.md" @@ -40,9 +40,6 @@ std = [ ## Enables all features that allocate in `no_std` alloc = [] -## Stores the backtraces of all generated `Error`s. Good for debugging, but may come with a slight performance hit. -errors_backtrace = ["backtrace"] - [build-dependencies] rustversion = { workspace = true } diff --git a/crates/tuplelist_ex/LICENSE-APACHE b/crates/exceptional/LICENSE-APACHE similarity index 100% rename from crates/tuplelist_ex/LICENSE-APACHE rename to crates/exceptional/LICENSE-APACHE diff --git a/crates/tuplelist_ex/LICENSE-MIT b/crates/exceptional/LICENSE-MIT similarity index 100% rename from crates/tuplelist_ex/LICENSE-MIT rename to crates/exceptional/LICENSE-MIT diff --git a/crates/signal_handler/README.md b/crates/exceptional/README.md similarity index 100% rename from crates/signal_handler/README.md rename to crates/exceptional/README.md diff --git a/crates/exceptional/src/lib.rs b/crates/exceptional/src/lib.rs new file mode 100644 index 00000000000..8e07f958e30 --- /dev/null +++ b/crates/exceptional/src/lib.rs @@ -0,0 +1,65 @@ +/*! + * Everything for your exception and signal handling needs + */ +#![doc = include_str!("../../../README.md")] +/*! */ +#![cfg_attr(feature = "document-features", doc = document_features::document_features!())] +#![no_std] +#![cfg_attr(not(test), warn( + missing_debug_implementations, + missing_docs, + //trivial_casts, + trivial_numeric_casts, + unused_extern_crates, + unused_import_braces, + unused_qualifications, + //unused_results +))] +#![cfg_attr(test, deny( + missing_debug_implementations, + missing_docs, + //trivial_casts, + trivial_numeric_casts, + unused_extern_crates, + unused_import_braces, + unused_qualifications, + unused_must_use, + //unused_results +))] +#![cfg_attr( + test, + deny( + bad_style, + dead_code, + improper_ctypes, + non_shorthand_field_patterns, + no_mangle_generic_items, + overflowing_literals, + path_statements, + patterns_in_fns_without_body, + unconditional_recursion, + unused, + unused_allocation, + unused_comparisons, + unused_parens, + while_true + ) +)] + +#[cfg(feature = "std")] +#[macro_use] +extern crate std; +#[cfg(feature = "alloc")] +#[macro_use] +#[doc(hidden)] +pub extern crate alloc; + +pub mod unix_signals; + +#[cfg(all(windows, feature = "std"))] +#[expect(missing_docs, overflowing_literals)] +pub mod windows_exceptions; + +#[cfg(unix)] +pub use unix_signals::CTRL_C_EXIT; + diff --git a/crates/libafl_bolts/src/os/unix_signals.rs b/crates/exceptional/src/unix_signals.rs similarity index 100% rename from crates/libafl_bolts/src/os/unix_signals.rs rename to crates/exceptional/src/unix_signals.rs diff --git a/crates/libafl_bolts/src/os/windows_exceptions.rs b/crates/exceptional/src/windows_exceptions.rs similarity index 98% rename from crates/libafl_bolts/src/os/windows_exceptions.rs rename to crates/exceptional/src/windows_exceptions.rs index 68f1ee7865f..7be6e1102f6 100644 --- a/crates/libafl_bolts/src/os/windows_exceptions.rs +++ b/crates/exceptional/src/windows_exceptions.rs @@ -27,16 +27,15 @@ use crate::Error; /// The special exit code when the target exited through ctrl-c pub const CTRL_C_EXIT: i32 = -1073741510; -// For VEH +/// For VEH const EXCEPTION_CONTINUE_EXECUTION: c_long = -1; -// For VEH +/// For VEH const EXCEPTION_CONTINUE_SEARCH: c_long = 0; // For SEH // const EXCEPTION_EXECUTE_HANDLER: c_long = 1; -// From https://github.com/Alexpux/mingw-w64/blob/master/mingw-w64-headers/crt/signal.h pub const SIGINT: i32 = 2; pub const SIGILL: i32 = 4; pub const SIGABRT_COMPAT: i32 = 6; @@ -47,7 +46,6 @@ pub const SIGBREAK: i32 = 21; pub const SIGABRT: i32 = 22; pub const SIGABRT2: i32 = 22; -// From https://github.com/wine-mirror/wine/blob/master/include/winnt.h#L611 pub const STATUS_WAIT_0: i32 = 0x00000000; pub const STATUS_ABANDONED_WAIT_0: i32 = 0x00000080; pub const STATUS_USER_APC: i32 = 0x000000C0; @@ -96,7 +94,6 @@ pub const STATUS_SXS_EARLY_DEACTIVATION: i32 = 0xC015000F; pub const STATUS_SXS_INVALID_DEACTIVATION: i32 = 0xC0150010; pub const STATUS_NOT_IMPLEMENTED: i32 = 0xC0000002; -// from https://github.com/x64dbg/x64dbg/blob/4d631707b89d97e199844c08f5b65d8ea5d5d3f3/bin/exceptiondb.txt pub const STATUS_WX86_UNSIMULATE: i32 = 0x4000001C; pub const STATUS_WX86_CONTINUE: i32 = 0x4000001D; pub const STATUS_WX86_SINGLE_STEP: i32 = 0x4000001E; @@ -132,7 +129,6 @@ pub const VCPP_EXCEPTION_ERROR_PROC_NOT_FOUND: i32 = 0xC06D007F; #[derive(Debug, FromPrimitive, Copy, Clone)] #[repr(i32)] pub enum ExceptionCode { - // From https://github.com/wine-mirror/wine/blob/master/include/winnt.h#L611 WaitZero = STATUS_WAIT_0, AbandonedWaitZero = STATUS_ABANDONED_WAIT_0, UserApc = STATUS_USER_APC, @@ -180,7 +176,7 @@ pub enum ExceptionCode { SxsEarlyDeactivation = STATUS_SXS_EARLY_DEACTIVATION, SxsInvalidDeactivation = STATUS_SXS_INVALID_DEACTIVATION, NotImplemented = STATUS_NOT_IMPLEMENTED, - // from https://github.com/x64dbg/x64dbg/blob/4d631707b89d97e199844c08f5b65d8ea5d5d3f3/bin/exceptiondb.txt + Wx86Unsimulate = STATUS_WX86_UNSIMULATE, Wx86Continue = STATUS_WX86_CONTINUE, Wx86SingleStep = STATUS_WX86_SINGLE_STEP, @@ -534,6 +530,7 @@ unsafe extern "C" fn handle_signal(_signum: i32) { } /// Setup Win32 exception handlers in a somewhat rusty way. +/// /// # Safety /// Exception handlers are usually ugly, handle with care! #[cfg(feature = "alloc")] @@ -602,6 +599,7 @@ struct CtrlHandlerHolder { static mut CTRL_HANDLER: Option = None; /// Set `ConsoleCtrlHandler` to catch Ctrl-C +/// /// # Safety /// Same safety considerations as in `setup_exception_handler` pub(crate) unsafe fn setup_ctrl_handler( diff --git a/crates/libafl_bolts/examples/llmp_test/main.rs b/crates/libafl_bolts/examples/llmp_test/main.rs deleted file mode 100644 index 2ac4d09413b..00000000000 --- a/crates/libafl_bolts/examples/llmp_test/main.rs +++ /dev/null @@ -1,254 +0,0 @@ -/*! -This shows how llmp can be used directly, without libafl abstractions -*/ -extern crate alloc; - -use core::marker::PhantomData; -#[cfg(all(feature = "std", not(target_os = "haiku")))] -use core::num::NonZeroUsize; -#[cfg(not(target_os = "haiku"))] -use core::time::Duration; -#[cfg(all(feature = "std", not(target_os = "haiku")))] -use std::{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}, -}; -use tuple_list::tuple_list; - -#[cfg(all(feature = "std", not(target_os = "haiku")))] -const _TAG_SIMPLE_U32_V1: Tag = Tag(0x5130_0321); -#[cfg(all(feature = "std", not(target_os = "haiku")))] -const _TAG_MATH_RESULT_V1: Tag = Tag(0x7747_4331); -#[cfg(all(feature = "std", not(target_os = "haiku")))] -const _TAG_1MEG_V1: Tag = Tag(0xB111_1161); - -/// The time the broker will wait for things to happen before printing a message -#[cfg(all(feature = "std", not(target_os = "haiku")))] -const BROKER_TIMEOUT: Duration = Duration::from_secs(10); - -/// How long the broker may sleep between forwarding a new chunk of sent messages -#[cfg(all(feature = "std", not(target_os = "haiku")))] -const SLEEP_BETWEEN_FORWARDS: Duration = Duration::from_millis(5); - -#[cfg(all(feature = "std", not(target_os = "haiku")))] -static LOGGER: SimpleStderrLogger = SimpleStderrLogger::new(); - -#[cfg(all(feature = "std", not(target_os = "haiku")))] -fn adder_loop(port: u16) -> Result<(), Box> { - let shmem_provider = StdShMemProvider::new()?; - let mut client = llmp::LlmpClient::create_attach_to_tcp(shmem_provider, port)?; - let mut last_result: u32 = 0; - let mut current_result: u32 = 0; - loop { - let mut msg_counter = 0; - loop { - let Some((sender, tag, buf)) = client.recv_buf()? else { - break; - }; - msg_counter += 1; - match tag { - _TAG_SIMPLE_U32_V1 => { - current_result = - current_result.wrapping_add(u32::from_le_bytes(buf.try_into()?)); - } - _ => println!( - "Adder Client ignored unknown message {:?} from client {:?} with {} bytes", - tag, - sender, - buf.len() - ), - } - } - - if current_result != last_result { - println!("Adder handled {msg_counter} messages, reporting {current_result} to broker"); - - client.send_buf(_TAG_MATH_RESULT_V1, ¤t_result.to_le_bytes())?; - last_result = current_result; - } - - thread::sleep(time::Duration::from_millis(100)); - } -} - -#[cfg(all(feature = "std", not(target_os = "haiku")))] -fn large_msg_loop(port: u16) -> Result<(), Box> { - let mut client = llmp::LlmpClient::create_attach_to_tcp(StdShMemProvider::new()?, port)?; - - #[cfg(not(target_vendor = "apple"))] - let meg_buf = vec![1u8; 1 << 20]; - #[cfg(target_vendor = "apple")] - let meg_buf = vec![1u8; 1 << 19]; - - loop { - client.send_buf(_TAG_1MEG_V1, &meg_buf)?; - #[cfg(not(target_vendor = "apple"))] - println!("Sending the next megabyte"); - #[cfg(target_vendor = "apple")] - println!("Sending the next half megabyte (Apple had issues with >1 meg)"); - thread::sleep(time::Duration::from_millis(100)); - } -} - -pub struct LlmpExampleHook { - phantom: PhantomData, -} - -impl LlmpExampleHook { - #[must_use] - pub fn new() -> Self { - Self { - phantom: PhantomData, - } - } -} - -impl Default for LlmpExampleHook { - fn default() -> Self { - Self::new() - } -} - -#[cfg(all(feature = "std", not(target_os = "haiku")))] -impl LlmpHook for LlmpExampleHook -where - SP: ShMemProvider + 'static, -{ - fn on_new_message( - &mut self, - _broker_inner: &mut LlmpBrokerInner, - client_id: ClientId, - msg_tag: &mut Tag, - _msg_flags: &mut Flags, - msg: &mut [u8], - _new_msgs: &mut Vec<(Tag, Flags, Vec)>, - ) -> Result { - match *msg_tag { - _TAG_SIMPLE_U32_V1 => { - println!( - "Client {:?} sent message: {:?}", - client_id, - u32::from_le_bytes(msg.try_into()?) - ); - Ok(LlmpMsgHookResult::ForwardToClients) - } - _TAG_MATH_RESULT_V1 => { - println!( - "Adder Client has this current result: {:?}", - u32::from_le_bytes(msg.try_into()?) - ); - Ok(LlmpMsgHookResult::Handled) - } - _ => { - println!("Unknown message id received: {msg_tag:?}"); - Ok(LlmpMsgHookResult::ForwardToClients) - } - } - } - - fn on_timeout(&mut self) -> Result<(), Error> { - println!( - "No client did anything for {} seconds..", - BROKER_TIMEOUT.as_secs() - ); - - Ok(()) - } -} - -#[cfg(target_os = "haiku")] -fn main() { - eprintln!("LLMP example is currently not supported on no_std. Implement ShMem for no_std."); -} - -#[cfg(not(target_os = "haiku"))] -fn main() -> Result<(), Box> { - /* The main node has a broker, and a few worker threads */ - - use libafl_bolts::llmp::Broker; - - let mode = std::env::args() - .nth(1) - .expect("no mode specified, chose 'broker', 'b2b', 'ctr', 'adder', 'large', or 'exiting'"); - let port: u16 = std::env::args() - .nth(2) - .unwrap_or_else(|| "1337".into()) - .parse::()?; - // in the b2b use-case, this is our "own" port, we connect to the "normal" broker node on startup. - let b2b_port: u16 = std::env::args() - .nth(3) - .unwrap_or_else(|| "4242".into()) - .parse::()?; - - log::set_logger(&LOGGER).unwrap(); - log::set_max_level(log::LevelFilter::Trace); - println!("Launching in mode {mode} on port {port}"); - - match mode.as_str() { - "broker" => { - let mut broker = llmp::LlmpBroker::new( - StdShMemProvider::new()?, - tuple_list!(LlmpExampleHook::new()), - )?; - broker.inner_mut().launch_tcp_listener_on(port)?; - // Exit when we got at least _n_ nodes, and all of them quit. - broker.set_exit_after(NonZeroUsize::new(1_usize).unwrap()); - broker.loop_with_timeouts(BROKER_TIMEOUT, Some(SLEEP_BETWEEN_FORWARDS)); - } - "b2b" => { - let mut broker = llmp::LlmpBroker::new( - StdShMemProvider::new()?, - tuple_list!(LlmpExampleHook::new()), - )?; - broker.inner_mut().launch_tcp_listener_on(b2b_port)?; - // connect back to the main broker. - broker.inner_mut().connect_b2b(("127.0.0.1", port))?; - broker.loop_with_timeouts(BROKER_TIMEOUT, Some(SLEEP_BETWEEN_FORWARDS)); - } - "ctr" => { - let mut client = - llmp::LlmpClient::create_attach_to_tcp(StdShMemProvider::new()?, port)?; - let mut counter: u32 = 0; - loop { - counter = counter.wrapping_add(1); - client.send_buf(_TAG_SIMPLE_U32_V1, &counter.to_le_bytes())?; - println!("CTR Client writing {counter}"); - thread::sleep(Duration::from_secs(1)); - } - } - "adder" => { - adder_loop(port)?; - } - "large" => { - large_msg_loop(port)?; - } - "exiting" => { - let mut client = - llmp::LlmpClient::create_attach_to_tcp(StdShMemProvider::new()?, port)?; - for i in 0..10_u32 { - client.send_buf(_TAG_SIMPLE_U32_V1, &i.to_le_bytes())?; - println!("Exiting Client writing {i}"); - thread::sleep(Duration::from_millis(10)); - } - log::info!("Exiting Client exits"); - client.sender_mut().send_exiting()?; - - // there is another way to tell that this client wants to exit. - // one is to call client.sender_mut().send_exiting()?; - // you can disconnet the client in this way as long as this client in an unrecoverable state (like in a crash handler) - // another way to do this is through the detach_from_broker() call - // you can call detach_from_broker(port); to notify the broker that this broker wants to exit - // This one is usually for the event restarter to cut off the connection when the client has crashed. - // In that case we don't have access to the llmp client of the client anymore, but we can use detach_from_broker instead - } - _ => { - println!("No valid mode supplied"); - } - } - Ok(()) -} diff --git a/crates/libafl_bolts/src/lib.rs b/crates/libafl_bolts/src/lib.rs index 33460148bf5..296e268a1fc 100644 --- a/crates/libafl_bolts/src/lib.rs +++ b/crates/libafl_bolts/src/lib.rs @@ -246,56 +246,6 @@ pub mod prelude { pub use super::{bolts_prelude::*, *}; } - -#[cfg(all(any(doctest, test), not(feature = "std")))] -/// Provide custom time in `no_std` tests. -#[unsafe(no_mangle)] -pub unsafe extern "C" fn external_current_millis() -> u64 { - // TODO: use "real" time here - 1000 -} - -/// Current time -#[cfg(feature = "std")] -#[must_use] -#[inline] -pub fn current_time() -> time::Duration { - SystemTime::now().duration_since(UNIX_EPOCH).unwrap() -} - -// external defined function in case of `no_std` -// -// 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")))] -unsafe extern "C" { - //#[unsafe(no_mangle)] - fn external_current_millis() -> u64; -} - -/// Current time (fixed fallback for `no_std`) -#[cfg(not(feature = "std"))] -#[inline] -#[must_use] -pub fn current_time() -> time::Duration { - let millis = unsafe { external_current_millis() }; - time::Duration::from_millis(millis) -} - -/// Gets current nanoseconds since [`UNIX_EPOCH`] -#[must_use] -#[inline] -pub fn current_nanos() -> u64 { - current_time().as_nanos() as u64 -} - -/// Gets current milliseconds since [`UNIX_EPOCH`] -#[must_use] -#[inline] -pub fn current_milliseconds() -> u64 { - current_time().as_millis() as u64 -} - /// Trait to truncate slices and maps to a new size pub trait Truncate { /// Reduce the size of the slice @@ -319,38 +269,6 @@ impl Truncate for &mut [T] { } } -/// Format a `Duration` into a HMS string -#[cfg(feature = "alloc")] -#[must_use] -pub fn format_duration(duration: &time::Duration) -> String { - const MINS_PER_HOUR: u64 = 60; - const HOURS_PER_DAY: u64 = 24; - - const SECS_PER_MINUTE: u64 = 60; - const SECS_PER_HOUR: u64 = SECS_PER_MINUTE * MINS_PER_HOUR; - const SECS_PER_DAY: u64 = SECS_PER_HOUR * HOURS_PER_DAY; - - let total_secs = duration.as_secs(); - let secs = total_secs % SECS_PER_MINUTE; - - if total_secs < SECS_PER_MINUTE { - format!("{secs}s") - } else { - let mins = (total_secs / SECS_PER_MINUTE) % MINS_PER_HOUR; - if total_secs < SECS_PER_HOUR { - format!("{mins}m-{secs}s") - } else { - let hours = (total_secs / SECS_PER_HOUR) % HOURS_PER_DAY; - if total_secs < SECS_PER_DAY { - format!("{hours}h-{mins}m-{secs}s") - } else { - let days = total_secs / SECS_PER_DAY; - format!("{days}days {hours}h-{mins}m-{secs}s") - } - } - } -} - /// Format a number with thousands separators #[cfg(feature = "alloc")] #[must_use] diff --git a/crates/libafl_bolts/src/minibsod.rs b/crates/libafl_bolts/src/minibsod.rs deleted file mode 100644 index b837b70306c..00000000000 --- a/crates/libafl_bolts/src/minibsod.rs +++ /dev/null @@ -1,1258 +0,0 @@ -//! Implements a mini-bsod generator. -//! It dumps all important registers and prints a stacktrace. - -#[cfg(unix)] -use alloc::vec::Vec; -#[cfg(any(target_vendor = "apple", target_os = "openbsd"))] -use core::mem::size_of; -use std::io::{BufWriter, Write}; -#[cfg(any(target_os = "solaris", target_os = "illumos"))] -use std::process::Command; - -#[cfg(unix)] -use libc::siginfo_t; -#[cfg(target_vendor = "apple")] -use mach2::{ - message::mach_msg_type_number_t, - port::mach_port_t, - traps::mach_task_self, - vm::mach_vm_region_recurse, - vm_region::{vm_region_recurse_info_t, vm_region_submap_info_64}, - vm_types::{mach_vm_address_t, mach_vm_size_t, natural_t}, -}; -#[cfg(windows)] -use windows::Win32::System::Diagnostics::Debug::{CONTEXT, EXCEPTION_POINTERS}; - -#[cfg(unix)] -use crate::os::unix_signals::{Signal, ucontext_t}; - -/// Necessary info to print a mini-BSOD. -#[derive(Debug)] -#[cfg(unix)] -pub struct BsodInfo { - /// the signal - pub signal: Signal, - /// siginfo - pub siginfo: siginfo_t, - /// ucontext - pub ucontext: Option, -} - -/// Write the content of all important registers -#[cfg(all( - any(target_os = "linux", target_os = "android"), - target_arch = "x86_64" -))] -pub fn dump_registers( - writer: &mut BufWriter, - ucontext: &ucontext_t, -) -> Result<(), std::io::Error> { - use libc::{ - 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, - }; - - let mcontext = &ucontext.uc_mcontext; - - write!(writer, "r8 : {:#016x}, ", mcontext.gregs[REG_R8 as usize])?; - write!(writer, "r9 : {:#016x}, ", mcontext.gregs[REG_R9 as usize])?; - write!(writer, "r10: {:#016x}, ", mcontext.gregs[REG_R10 as usize])?; - writeln!(writer, "r11: {:#016x}, ", mcontext.gregs[REG_R11 as usize])?; - write!(writer, "r12: {:#016x}, ", mcontext.gregs[REG_R12 as usize])?; - write!(writer, "r13: {:#016x}, ", mcontext.gregs[REG_R13 as usize])?; - write!(writer, "r14: {:#016x}, ", mcontext.gregs[REG_R14 as usize])?; - writeln!(writer, "r15: {:#016x}, ", mcontext.gregs[REG_R15 as usize])?; - write!(writer, "rdi: {:#016x}, ", mcontext.gregs[REG_RDI as usize])?; - write!(writer, "rsi: {:#016x}, ", mcontext.gregs[REG_RSI as usize])?; - write!(writer, "rbp: {:#016x}, ", mcontext.gregs[REG_RBP as usize])?; - writeln!(writer, "rbx: {:#016x}, ", mcontext.gregs[REG_RBX as usize])?; - write!(writer, "rdx: {:#016x}, ", mcontext.gregs[REG_RDX as usize])?; - write!(writer, "rax: {:#016x}, ", mcontext.gregs[REG_RAX as usize])?; - write!(writer, "rcx: {:#016x}, ", mcontext.gregs[REG_RCX as usize])?; - writeln!(writer, "rsp: {:#016x}, ", mcontext.gregs[REG_RSP as usize])?; - write!(writer, "rip: {:#016x}, ", mcontext.gregs[REG_RIP as usize])?; - writeln!(writer, "efl: {:#016x}, ", mcontext.gregs[REG_EFL as usize])?; - - Ok(()) -} - -/// Write the content of all important registers -#[cfg(all(any(target_os = "linux", target_os = "android"), target_arch = "x86"))] -pub fn dump_registers( - writer: &mut BufWriter, - ucontext: &ucontext_t, -) -> Result<(), std::io::Error> { - use libc::{ - REG_EAX, REG_EBP, REG_EBX, REG_ECX, REG_EDI, REG_EDX, REG_EFL, REG_EIP, REG_ESI, REG_ESP, - }; - - let mcontext = &ucontext.uc_mcontext; - - write!(writer, "eax: {:#016x}, ", mcontext.gregs[REG_EAX as usize])?; - write!(writer, "ebx: {:#016x}, ", mcontext.gregs[REG_EBX as usize])?; - write!(writer, "ecx: {:#016x}, ", mcontext.gregs[REG_ECX as usize])?; - writeln!(writer, "edx: {:#016x}, ", mcontext.gregs[REG_EDX as usize])?; - write!(writer, "edi: {:#016x}, ", mcontext.gregs[REG_EDI as usize])?; - write!(writer, "esi: {:#016x}, ", mcontext.gregs[REG_ESI as usize])?; - write!(writer, "esp: {:#016x}, ", mcontext.gregs[REG_ESP as usize])?; - writeln!(writer, "ebp: {:#016x}, ", mcontext.gregs[REG_EBP as usize])?; - write!(writer, "eip: {:#016x}, ", mcontext.gregs[REG_EIP as usize])?; - writeln!(writer, "efl: {:#016x}, ", mcontext.gregs[REG_EFL as usize])?; - - Ok(()) -} - -/// Write the content of all important registers -#[cfg(all( - any(target_os = "linux", target_os = "android"), - target_arch = "aarch64" -))] -pub fn dump_registers( - writer: &mut BufWriter, - ucontext: &ucontext_t, -) -> Result<(), std::io::Error> { - for reg in 0..31_usize { - write!( - writer, - "x{:02}: 0x{:016x} ", - reg, ucontext.uc_mcontext.regs[reg] - )?; - if reg % 4 == 3 { - writeln!(writer)?; - } - } - writeln!(writer, "pc : 0x{:016x} ", ucontext.uc_mcontext.pc)?; - - Ok(()) -} - -/// Write the content of all important registers -#[cfg(all(target_os = "linux", target_arch = "arm"))] -pub fn dump_registers( - writer: &mut BufWriter, - ucontext: &ucontext_t, -) -> Result<(), std::io::Error> { - write!(writer, "r0 : {:#016x}, ", ucontext.uc_mcontext.arm_r0)?; - write!(writer, "r1 : {:#016x}, ", ucontext.uc_mcontext.arm_r1)?; - write!(writer, "r2: {:#016x}, ", ucontext.uc_mcontext.arm_r2)?; - writeln!(writer, "r3: {:#016x}, ", ucontext.uc_mcontext.arm_r3)?; - write!(writer, "r4: {:#016x}, ", ucontext.uc_mcontext.arm_r4)?; - write!(writer, "r5: {:#016x}, ", ucontext.uc_mcontext.arm_r5)?; - write!(writer, "r6: {:#016x}, ", ucontext.uc_mcontext.arm_r6)?; - writeln!(writer, "r7: {:#016x}, ", ucontext.uc_mcontext.arm_r7)?; - write!(writer, "r8: {:#016x}, ", ucontext.uc_mcontext.arm_r8)?; - write!(writer, "r9: {:#016x}, ", ucontext.uc_mcontext.arm_r9)?; - write!(writer, "r10: {:#016x}, ", ucontext.uc_mcontext.arm_r10)?; - writeln!(writer, "fp: {:#016x}, ", ucontext.uc_mcontext.arm_fp)?; - write!(writer, "ip: {:#016x}, ", ucontext.uc_mcontext.arm_ip)?; - write!(writer, "sp: {:#016x}, ", ucontext.uc_mcontext.arm_sp)?; - write!(writer, "lr: {:#016x}, ", ucontext.uc_mcontext.arm_lr)?; - writeln!(writer, "cpsr: {:#016x}, ", ucontext.uc_mcontext.arm_cpsr)?; - - writeln!(writer, "pc : 0x{:016x} ", ucontext.uc_mcontext.arm_pc)?; - - Ok(()) -} - -/// Write the content of all important registers -#[cfg(all(target_os = "freebsd", target_arch = "aarch64"))] -pub fn dump_registers( - writer: &mut BufWriter, - ucontext: &ucontext_t, -) -> Result<(), std::io::Error> { - let mcontext = unsafe { &*ucontext.uc_mcontext }; - for reg in 0..29_u8 { - writeln!( - writer, - "x{:02}: 0x{:016x} ", - reg, mcontext.mc_gpregs.gp_x[reg as usize] - )?; - if reg % 4 == 3 { - writeln!(writer)?; - } - } - write!(writer, "lr: 0x{:016x} ", mcontext.mc_gpregs.gp_lr)?; - write!(writer, "sp: 0x{:016x} ", mcontext.mc_gpregs.gp_sp)?; - - Ok(()) -} - -/// Write the content of all important registers -#[cfg(all(target_vendor = "apple", target_arch = "aarch64"))] -pub fn dump_registers( - writer: &mut BufWriter, - ucontext: &ucontext_t, -) -> Result<(), std::io::Error> { - let mcontext = unsafe { &*ucontext.uc_mcontext }; - for reg in 0..29_u8 { - writeln!( - writer, - "x{:02}: 0x{:016x} ", - reg, mcontext.__ss.__x[reg as usize] - )?; - if reg % 4 == 3 { - writeln!(writer)?; - } - } - write!(writer, "fp: 0x{:016x} ", mcontext.__ss.__fp)?; - write!(writer, "lr: 0x{:016x} ", mcontext.__ss.__lr)?; - write!(writer, "pc: 0x{:016x} ", mcontext.__ss.__pc)?; - - Ok(()) -} - -/// Write the content of all important registers -#[expect(clippy::unnecessary_wraps, clippy::similar_names)] -#[cfg(all(target_vendor = "apple", target_arch = "x86_64"))] -pub fn dump_registers( - writer: &mut BufWriter, - ucontext: &ucontext_t, -) -> Result<(), std::io::Error> { - let mcontext = unsafe { *ucontext.uc_mcontext }; - let ss = mcontext.__ss; - - write!(writer, "r8 : {:#016x}, ", ss.__r8)?; - write!(writer, "r9 : {:#016x}, ", ss.__r9)?; - write!(writer, "r10: {:#016x}, ", ss.__r10)?; - writeln!(writer, "r11: {:#016x}, ", ss.__r11)?; - write!(writer, "r12: {:#016x}, ", ss.__r12)?; - write!(writer, "r13: {:#016x}, ", ss.__r13)?; - write!(writer, "r14: {:#016x}, ", ss.__r14)?; - writeln!(writer, "r15: {:#016x}, ", ss.__r15)?; - write!(writer, "rdi: {:#016x}, ", ss.__rdi)?; - write!(writer, "rsi: {:#016x}, ", ss.__rsi)?; - write!(writer, "rbp: {:#016x}, ", ss.__rbp)?; - writeln!(writer, "rbx: {:#016x}, ", ss.__rbx)?; - write!(writer, "rdx: {:#016x}, ", ss.__rdx)?; - write!(writer, "rax: {:#016x}, ", ss.__rax)?; - write!(writer, "rcx: {:#016x}, ", ss.__rcx)?; - writeln!(writer, "rsp: {:#016x}, ", ss.__rsp)?; - write!(writer, "rip: {:#016x}, ", ss.__rip)?; - writeln!(writer, "efl: {:#016x}, ", ss.__rflags)?; - - Ok(()) -} - -/// Write the content of all important registers -#[cfg(all( - any(target_os = "freebsd", target_os = "dragonfly"), - target_arch = "x86_64" -))] -pub fn dump_registers( - writer: &mut BufWriter, - ucontext: &ucontext_t, -) -> Result<(), std::io::Error> { - let mcontext = &ucontext.uc_mcontext; - - write!(writer, "r8 : {:#016x}, ", mcontext.mc_r8)?; - write!(writer, "r9 : {:#016x}, ", mcontext.mc_r9)?; - write!(writer, "r10 : {:#016x}, ", mcontext.mc_r10)?; - write!(writer, "r11 : {:#016x}, ", mcontext.mc_r11)?; - write!(writer, "r12 : {:#016x}, ", mcontext.mc_r12)?; - write!(writer, "r13 : {:#016x}, ", mcontext.mc_r13)?; - write!(writer, "r14 : {:#016x}, ", mcontext.mc_r14)?; - write!(writer, "r15 : {:#016x}, ", mcontext.mc_r15)?; - write!(writer, "rdi : {:#016x}, ", mcontext.mc_rdi)?; - write!(writer, "rsi : {:#016x}, ", mcontext.mc_rsi)?; - write!(writer, "rbp : {:#016x}, ", mcontext.mc_rbp)?; - write!(writer, "rbx : {:#016x}, ", mcontext.mc_rbx)?; - write!(writer, "rdx : {:#016x}, ", mcontext.mc_rdx)?; - write!(writer, "rax : {:#016x}, ", mcontext.mc_rax)?; - write!(writer, "rcx : {:#016x}, ", mcontext.mc_rcx)?; - write!(writer, "rsp : {:#016x}, ", mcontext.mc_rsp)?; - write!(writer, "rflags : {:#016x}, ", mcontext.mc_rflags)?; - write!(writer, "cs : {:#016x}, ", mcontext.mc_cs)?; - Ok(()) -} - -/// Write the content of all important registers -#[cfg(all(target_os = "netbsd", target_arch = "x86_64"))] -pub fn dump_registers( - writer: &mut BufWriter, - ucontext: &ucontext_t, -) -> Result<(), std::io::Error> { - use libc::{ - _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, - }; - - let mcontext = &ucontext.uc_mcontext; - - write!( - writer, - "r8 : {:#016x}, ", - mcontext.__gregs[_REG_R8 as usize] - )?; - write!( - writer, - "r9 : {:#016x}, ", - mcontext.__gregs[_REG_R9 as usize] - )?; - write!( - writer, - "r10: {:#016x}, ", - mcontext.__gregs[_REG_R10 as usize] - )?; - writeln!( - writer, - "r11: {:#016x}, ", - mcontext.__gregs[_REG_R11 as usize] - )?; - write!( - writer, - "r12: {:#016x}, ", - mcontext.__gregs[_REG_R12 as usize] - )?; - write!( - writer, - "r13: {:#016x}, ", - mcontext.__gregs[_REG_R13 as usize] - )?; - write!( - writer, - "r14: {:#016x}, ", - mcontext.__gregs[_REG_R14 as usize] - )?; - writeln!( - writer, - "r15: {:#016x}, ", - mcontext.__gregs[_REG_R15 as usize] - )?; - write!( - writer, - "rdi: {:#016x}, ", - mcontext.__gregs[_REG_RDI as usize] - )?; - write!( - writer, - "rsi: {:#016x}, ", - mcontext.__gregs[_REG_RSI as usize] - )?; - write!( - writer, - "rbp: {:#016x}, ", - mcontext.__gregs[_REG_RBP as usize] - )?; - writeln!( - writer, - "rbx: {:#016x}, ", - mcontext.__gregs[_REG_RBX as usize] - )?; - write!( - writer, - "rdx: {:#016x}, ", - mcontext.__gregs[_REG_RDX as usize] - )?; - write!( - writer, - "rax: {:#016x}, ", - mcontext.__gregs[_REG_RAX as usize] - )?; - write!( - writer, - "rcx: {:#016x}, ", - mcontext.__gregs[_REG_RCX as usize] - )?; - writeln!( - writer, - "rsp: {:#016x}, ", - mcontext.__gregs[_REG_RSP as usize] - )?; - write!( - writer, - "rip: {:#016x}, ", - mcontext.__gregs[_REG_RIP as usize] - )?; - write!(writer, "cs: {:#016x}, ", mcontext.__gregs[_REG_CS as usize])?; - writeln!( - writer, - "rflags: {:#016x}, ", - mcontext.__gregs[_REG_RFLAGS as usize] - )?; - - Ok(()) -} - -/// Write the content of all important registers -#[cfg(all(target_os = "openbsd", target_arch = "x86_64"))] -pub fn dump_registers( - writer: &mut BufWriter, - ucontext: &ucontext_t, -) -> Result<(), std::io::Error> { - write!(writer, "r8 : {:#016x}, ", ucontext.sc_r8)?; - write!(writer, "r9 : {:#016x}, ", ucontext.sc_r9)?; - write!(writer, "r10 : {:#016x}, ", ucontext.sc_r10)?; - write!(writer, "r11 : {:#016x}, ", ucontext.sc_r11)?; - write!(writer, "r12 : {:#016x}, ", ucontext.sc_r12)?; - write!(writer, "r13 : {:#016x}, ", ucontext.sc_r13)?; - write!(writer, "r14 : {:#016x}, ", ucontext.sc_r14)?; - write!(writer, "r15 : {:#016x}, ", ucontext.sc_r15)?; - write!(writer, "rdi : {:#016x}, ", ucontext.sc_rdi)?; - write!(writer, "rsi : {:#016x}, ", ucontext.sc_rsi)?; - write!(writer, "rbp : {:#016x}, ", ucontext.sc_rbp)?; - write!(writer, "rbx : {:#016x}, ", ucontext.sc_rbx)?; - write!(writer, "rdx : {:#016x}, ", ucontext.sc_rdx)?; - write!(writer, "rax : {:#016x}, ", ucontext.sc_rax)?; - write!(writer, "rcx : {:#016x}, ", ucontext.sc_rcx)?; - write!(writer, "rsp : {:#016x}, ", ucontext.sc_rsp)?; - write!(writer, "rflags : {:#016x}, ", ucontext.sc_rflags)?; - write!(writer, "cs : {:#016x}, ", ucontext.sc_cs)?; - Ok(()) -} - -/// Write the content of all important registers -#[cfg(all(target_os = "openbsd", target_arch = "aarch64"))] -pub fn dump_registers( - writer: &mut BufWriter, - ucontext: &ucontext_t, -) -> Result<(), std::io::Error> { - for reg in 0..29_usize { - write!(writer, "x{:02}: 0x{:016x} ", reg, ucontext.sc_x[reg])?; - if reg % 4 == 3 { - writeln!(writer)?; - } - } - write!(writer, "lr : {:#016x}, ", ucontext.sc_lr)?; - write!(writer, "elr : {:#016x}, ", ucontext.sc_elr)?; - write!(writer, "sp : {:#016x}, ", ucontext.sc_sp)?; - write!(writer, "spsr : {:#016x}, ", ucontext.sc_spsr)?; -} - -/// -/// Write the content of all important registers -#[cfg(all( - any(target_os = "solaris", target_os = "illumos"), - target_arch = "x86_64" -))] -pub fn dump_registers( - writer: &mut BufWriter, - ucontext: &ucontext_t, -) -> Result<(), std::io::Error> { - use libc::{ - 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, - }; - - let mcontext = &ucontext.uc_mcontext; - - write!(writer, "r8 : {:#016x}, ", mcontext.gregs[REG_R8 as usize])?; - write!(writer, "r9 : {:#016x}, ", mcontext.gregs[REG_R9 as usize])?; - write!(writer, "r10: {:#016x}, ", mcontext.gregs[REG_R10 as usize])?; - writeln!(writer, "r11: {:#016x}, ", mcontext.gregs[REG_R11 as usize])?; - write!(writer, "r12: {:#016x}, ", mcontext.gregs[REG_R12 as usize])?; - write!(writer, "r13: {:#016x}, ", mcontext.gregs[REG_R13 as usize])?; - write!(writer, "r14: {:#016x}, ", mcontext.gregs[REG_R14 as usize])?; - writeln!(writer, "r15: {:#016x}, ", mcontext.gregs[REG_R15 as usize])?; - write!(writer, "rdi: {:#016x}, ", mcontext.gregs[REG_RDI as usize])?; - write!(writer, "rsi: {:#016x}, ", mcontext.gregs[REG_RSI as usize])?; - write!(writer, "rbp: {:#016x}, ", mcontext.gregs[REG_RBP as usize])?; - writeln!(writer, "rbx: {:#016x}, ", mcontext.gregs[REG_RBX as usize])?; - write!(writer, "rdx: {:#016x}, ", mcontext.gregs[REG_RDX as usize])?; - write!(writer, "rax: {:#016x}, ", mcontext.gregs[REG_RAX as usize])?; - write!(writer, "rcx: {:#016x}, ", mcontext.gregs[REG_RCX as usize])?; - writeln!(writer, "rsp: {:#016x}, ", mcontext.gregs[REG_RSP as usize])?; - write!(writer, "rip: {:#016x}, ", mcontext.gregs[REG_RIP as usize])?; - writeln!(writer, "efl: {:#016x}, ", mcontext.gregs[REG_RFL as usize])?; - - Ok(()) -} - -/// Write the content of all important registers -#[cfg(all(target_os = "windows", target_arch = "x86_64"))] -pub fn dump_registers( - writer: &mut BufWriter, - context: &CONTEXT, -) -> Result<(), std::io::Error> { - write!(writer, "r8 : {:#018x}, ", context.R8)?; - write!(writer, "r9 : {:#018x}, ", context.R9)?; - write!(writer, "r10: {:#018x}, ", context.R10)?; - writeln!(writer, "r11: {:#018x}, ", context.R11)?; - write!(writer, "r12: {:#018x}, ", context.R12)?; - write!(writer, "r13: {:#018x}, ", context.R13)?; - write!(writer, "r14: {:#018x}, ", context.R14)?; - writeln!(writer, "r15: {:#018x}, ", context.R15)?; - write!(writer, "rdi: {:#018x}, ", context.Rdi)?; - write!(writer, "rsi: {:#018x}, ", context.Rsi)?; - write!(writer, "rbp: {:#018x}, ", context.Rbp)?; - writeln!(writer, "rbx: {:#018x}, ", context.Rbx)?; - write!(writer, "rdx: {:#018x}, ", context.Rdx)?; - write!(writer, "rax: {:#018x}, ", context.Rax)?; - write!(writer, "rcx: {:#018x}, ", context.Rcx)?; - writeln!(writer, "rsp: {:#018x}, ", context.Rsp)?; - write!(writer, "rip: {:#018x}, ", context.Rip)?; - writeln!(writer, "efl: {:#018x}", context.EFlags)?; - - Ok(()) -} - -/// Write the content of all important registers -#[cfg(all(target_os = "windows", target_arch = "x86"))] -pub fn dump_registers( - writer: &mut BufWriter, - context: &CONTEXT, -) -> Result<(), std::io::Error> { - write!(writer, "eax: {:#010x}, ", context.Eax)?; - write!(writer, "ebx: {:#010x}, ", context.Ebx)?; - write!(writer, "ecx: {:#010x}, ", context.Ecx)?; - writeln!(writer, "edx: {:#010x}, ", context.Edx)?; - write!(writer, "edi: {:#010x}, ", context.Edi)?; - write!(writer, "esi: {:#010x}, ", context.Esi)?; - write!(writer, "esp: {:#010x}, ", context.Esp)?; - writeln!(writer, "ebp: {:#010x}, ", context.Ebp)?; - write!(writer, "eip: {:#010x}, ", context.Eip)?; - writeln!(writer, "efl: {:#010x} ", context.EFlags)?; - Ok(()) -} - -/// Write the content of all important registers -#[cfg(all(target_os = "windows", target_arch = "aarch64"))] -pub fn dump_registers( - writer: &mut BufWriter, - context: &CONTEXT, -) -> Result<(), std::io::Error> { - for reg in 0..29_usize { - write!(writer, "x{:02}: 0x{:016x} ", reg, unsafe { - context.Anonymous.X[reg] - })?; - if reg % 4 == 3 || reg == 28_usize { - writeln!(writer)?; - } - } - writeln!(writer, "pc : 0x{:016x} ", context.Pc)?; - writeln!(writer, "sp : 0x{:016x} ", context.Sp)?; - writeln!(writer, "fp : 0x{:016x} ", unsafe { - context.Anonymous.Anonymous.Fp - })?; - writeln!(writer, "lr : 0x{:016x} ", unsafe { - context.Anonymous.Anonymous.Lr - })?; - - Ok(()) -} - -/// Write the content of all important registers -#[cfg(all(target_os = "haiku", target_arch = "x86_64"))] -pub fn dump_registers( - writer: &mut BufWriter, - ucontext: &ucontext_t, -) -> Result<(), std::io::Error> { - let mcontext = &ucontext.uc_mcontext; - - write!(writer, "r8 : {:#016x}, ", mcontext.r8)?; - write!(writer, "r9 : {:#016x}, ", mcontext.r9)?; - write!(writer, "r10 : {:#016x}, ", mcontext.r10)?; - write!(writer, "r11 : {:#016x}, ", mcontext.r11)?; - write!(writer, "r12 : {:#016x}, ", mcontext.r12)?; - write!(writer, "r13 : {:#016x}, ", mcontext.r13)?; - write!(writer, "r14 : {:#016x}, ", mcontext.r14)?; - write!(writer, "r15 : {:#016x}, ", mcontext.r15)?; - write!(writer, "rdi : {:#016x}, ", mcontext.rdi)?; - write!(writer, "rsi : {:#016x}, ", mcontext.rsi)?; - write!(writer, "rbp : {:#016x}, ", mcontext.rbp)?; - write!(writer, "rbx : {:#016x}, ", mcontext.rbx)?; - write!(writer, "rdx : {:#016x}, ", mcontext.rdx)?; - write!(writer, "rax : {:#016x}, ", mcontext.rax)?; - write!(writer, "rcx : {:#016x}, ", mcontext.rcx)?; - write!(writer, "rsp : {:#016x}, ", mcontext.rsp)?; - write!(writer, "rflags : {:#016x}, ", mcontext.rflags)?; - Ok(()) -} - -#[expect(clippy::unnecessary_wraps)] -#[cfg(not(any( - target_vendor = "apple", - target_os = "linux", - target_os = "android", - target_os = "freebsd", - target_os = "dragonfly", - target_os = "netbsd", - target_os = "openbsd", - windows, - target_os = "haiku", - any(target_os = "solaris", target_os = "illumos"), -)))] -fn dump_registers( - writer: &mut BufWriter, - _ucontext: &ucontext_t, -) -> Result<(), std::io::Error> { - // TODO: Implement dump registers - writeln!( - writer, - "< Dumping registers is not yet supported on platform {:?}. Please add it to `minibsod.rs` >", - std::env::consts::OS - )?; - Ok(()) -} - -#[cfg(all( - any(target_os = "linux", target_os = "android"), - target_arch = "x86_64" -))] -fn write_crash( - writer: &mut BufWriter, - signal: Signal, - ucontext: &ucontext_t, -) -> Result<(), std::io::Error> { - writeln!( - writer, - "Received signal {} at {:#016x}, fault address: {:#016x}", - signal, - ucontext.uc_mcontext.gregs[libc::REG_RIP as usize], - ucontext.uc_mcontext.gregs[libc::REG_CR2 as usize] - )?; - - Ok(()) -} - -#[cfg(all(any(target_os = "linux", target_os = "android"), target_arch = "x86"))] -fn write_crash( - writer: &mut BufWriter, - signal: Signal, - ucontext: &ucontext_t, -) -> Result<(), std::io::Error> { - writeln!( - writer, - "Received signal {} at {:#08x}, fault address: {:#08x}", - signal, - ucontext.uc_mcontext.gregs[libc::REG_EIP as usize], - ucontext.uc_mcontext.cr2 - )?; - - Ok(()) -} - -#[cfg(all( - any(target_os = "linux", target_os = "android"), - target_arch = "aarch64" -))] -fn write_crash( - writer: &mut BufWriter, - signal: Signal, - ucontext: &ucontext_t, -) -> Result<(), std::io::Error> { - writeln!( - writer, - "Received signal {} at 0x{:016x}, fault address: 0x{:016x}", - signal, ucontext.uc_mcontext.pc, ucontext.uc_mcontext.fault_address - )?; - - Ok(()) -} - -#[cfg(all(target_os = "linux", target_arch = "arm"))] -fn write_crash( - writer: &mut BufWriter, - signal: Signal, - ucontext: &ucontext_t, -) -> Result<(), std::io::Error> { - writeln!( - writer, - "Received signal {} at 0x{:016x}, fault address: 0x{:016x}", - signal, ucontext.uc_mcontext.arm_pc, ucontext.uc_mcontext.fault_address - )?; - - Ok(()) -} - -#[cfg(all(target_os = "freebsd", target_arch = "aarch64"))] -fn write_crash( - writer: &mut BufWriter, - signal: Signal, - ucontext: &ucontext_t, -) -> Result<(), std::io::Error> { - writeln!( - writer, - "Received signal {} at 0x{:016x}", - signal, ucontext.uc_mcontext.mc_gpregs.gp_elr - )?; - - Ok(()) -} - -#[cfg(all(target_vendor = "apple", target_arch = "aarch64"))] -fn write_crash( - writer: &mut BufWriter, - signal: Signal, - ucontext: &ucontext_t, -) -> Result<(), std::io::Error> { - let mcontext = unsafe { &*ucontext.uc_mcontext }; - writeln!( - writer, - "Received signal {} at 0x{:016x}, fault address: 0x{:016x}", - signal, mcontext.__ss.__pc, mcontext.__es.__far - )?; - - Ok(()) -} - -#[cfg(all(target_vendor = "apple", target_arch = "x86_64"))] -fn write_crash( - writer: &mut BufWriter, - signal: Signal, - ucontext: &ucontext_t, -) -> Result<(), std::io::Error> { - let mcontext = unsafe { *ucontext.uc_mcontext }; - - writeln!( - writer, - "Received signal {} at 0x{:016x}, fault address: 0x{:016x}, trapno: 0x{:x}, err: 0x{:x}", - signal, - mcontext.__ss.__rip, - mcontext.__es.__faultvaddr, - mcontext.__es.__trapno, - mcontext.__es.__err - )?; - - Ok(()) -} - -#[cfg(all(target_os = "freebsd", target_arch = "x86_64"))] -fn write_crash( - writer: &mut BufWriter, - signal: Signal, - ucontext: &ucontext_t, -) -> Result<(), std::io::Error> { - writeln!( - writer, - "Received signal {} at{:016x}, fault address: 0x{:016x}", - signal, ucontext.uc_mcontext.mc_rip, ucontext.uc_mcontext.mc_fs - )?; - - Ok(()) -} - -#[cfg(all(target_os = "dragonfly", target_arch = "x86_64"))] -fn write_crash( - writer: &mut BufWriter, - signal: Signal, - ucontext: &ucontext_t, -) -> Result<(), std::io::Error> { - writeln!( - writer, - "Received signal {} at{:016x}, fault address: 0x{:016x}", - signal, ucontext.uc_mcontext.mc_rip, ucontext.uc_mcontext.mc_cs - )?; - - Ok(()) -} - -#[cfg(all(target_os = "openbsd", target_arch = "x86_64"))] -fn write_crash( - writer: &mut BufWriter, - signal: Signal, - ucontext: &ucontext_t, -) -> Result<(), std::io::Error> { - writeln!( - writer, - "Received signal {} at{:016x}, fault address: 0x{:016x}", - signal, ucontext.sc_rip, ucontext.sc_fs - )?; - - Ok(()) -} - -#[cfg(all(target_os = "openbsd", target_arch = "aarch64"))] -fn write_crash( - writer: &mut BufWriter, - signal: Signal, - ucontext: &ucontext_t, -) -> Result<(), std::io::Error> { - writeln!( - writer, - "Received signal {} at{:016x}", - signal, ucontext.sc_elr - )?; - - Ok(()) -} - -#[cfg(all(target_os = "netbsd", target_arch = "x86_64"))] -fn write_crash( - writer: &mut BufWriter, - signal: Signal, - ucontext: &ucontext_t, -) -> Result<(), std::io::Error> { - writeln!( - writer, - "Received signal {} at {:#016x}, fault address: {:#016x}", - signal, ucontext.uc_mcontext.__gregs[21], ucontext.uc_mcontext.__gregs[16] - )?; - - Ok(()) -} - -#[cfg(all( - any(target_os = "solaris", target_os = "illumos"), - target_arch = "x86_64" -))] -fn write_crash( - writer: &mut BufWriter, - signal: Signal, - ucontext: &ucontext_t, -) -> Result<(), std::io::Error> { - writeln!( - writer, - "Received signal {} at {:#016x}, fault address: {:#016x}", - signal, - ucontext.uc_mcontext.gregs[libc::REG_RIP as usize], - ucontext.uc_mcontext.gregs[libc::REG_FS as usize] - )?; - - Ok(()) -} - -#[cfg(all(target_os = "haiku", target_arch = "x86_64"))] -fn write_crash( - writer: &mut BufWriter, - signal: Signal, - ucontext: &ucontext_t, -) -> Result<(), std::io::Error> { - writeln!( - writer, - "Received signal {} at {:#016x}", - signal, ucontext.uc_mcontext.rip - )?; - - Ok(()) -} - -#[cfg(not(any( - target_vendor = "apple", - target_os = "linux", - target_os = "android", - target_os = "freebsd", - target_os = "dragonfly", - target_os = "openbsd", - target_os = "netbsd", - windows, - target_os = "haiku", - any(target_os = "solaris", target_os = "illumos"), -)))] -fn write_crash( - writer: &mut BufWriter, - signal: Signal, - _ucontext: &ucontext_t, -) -> Result<(), std::io::Error> { - // TODO add fault addr for other platforms. - writeln!(writer, "Received signal {signal}")?; - - Ok(()) -} - -#[cfg(windows)] -fn write_crash( - writer: &mut BufWriter, - exception_pointers: *mut EXCEPTION_POINTERS, -) -> Result<(), std::io::Error> { - // TODO add fault addr for other platforms. - unsafe { - writeln!( - writer, - "Received exception {:0x} at address {:x}", - (*exception_pointers) - .ExceptionRecord - .as_mut() - .unwrap() - .ExceptionCode - .0, - (*exception_pointers) - .ExceptionRecord - .as_mut() - .unwrap() - .ExceptionAddress as usize - ) - }?; - - Ok(()) -} - -#[cfg(any(target_os = "linux", target_os = "android"))] -fn write_minibsod(writer: &mut BufWriter) -> Result<(), std::io::Error> { - match std::fs::read_to_string("/proc/self/maps") { - Ok(maps) => writer.write_all(maps.as_bytes())?, - Err(e) => writeln!(writer, "Couldn't load mappings: {e:?}")?, - } - - Ok(()) -} - -#[cfg(any(target_os = "freebsd", target_os = "netbsd"))] -#[expect(clippy::cast_ptr_alignment)] -fn write_minibsod(writer: &mut BufWriter) -> Result<(), std::io::Error> { - let mut s: usize = 0; - #[cfg(target_os = "freebsd")] - let arr = &[libc::CTL_KERN, libc::KERN_PROC, libc::KERN_PROC_VMMAP, -1]; - #[cfg(target_os = "netbsd")] - let arr = &[ - libc::CTL_VM, - libc::VM_PROC, - libc::VM_PROC_MAP, - -1, - size_of::() - .try_into() - .expect("Invalid libc::kinfo_vmentry size"), - ]; - let mib = arr.as_ptr(); - let miblen = arr.len() as u32; - if unsafe { - libc::sysctl( - mib, - miblen, - std::ptr::null_mut(), - &mut s, - std::ptr::null_mut(), - 0, - ) - } == 0 - { - s = s * 4 / 3; - let mut buf: std::boxed::Box<[u8]> = vec![0; s].into_boxed_slice(); - let bufptr = buf.as_mut_ptr() as *mut libc::c_void; - if unsafe { libc::sysctl(mib, miblen, bufptr, &mut s, std::ptr::null_mut(), 0) } == 0 { - let mut start = bufptr as usize; - let end = start + s; - - unsafe { - while start < end { - let entry = start as *mut u8 as *mut libc::kinfo_vmentry; - #[cfg(target_os = "freebsd")] - let sz: usize = (*entry) - .kve_structsize - .try_into() - .expect("invalid kve_structsize value"); - #[cfg(target_os = "netbsd")] - let sz = size_of::(); - if sz == 0 { - break; - } - - let i = format!( - "{}-{} {:?}\n", - (*entry).kve_start, - (*entry).kve_end, - (*entry).kve_path - ); - writer.write_all(&i.into_bytes())?; - - start += sz; - } - } - } else { - return Err(std::io::Error::last_os_error()); - } - } else { - return Err(std::io::Error::last_os_error()); - } - - Ok(()) -} - -#[cfg(target_os = "openbsd")] -fn write_minibsod(writer: &mut BufWriter) -> Result<(), std::io::Error> { - let mut pentry = std::mem::MaybeUninit::::uninit(); - let mut s = size_of::(); - let arr = &[libc::CTL_KERN, libc::KERN_PROC_VMMAP, unsafe { - libc::getpid() - }]; - let mib = arr.as_ptr(); - let miblen = arr.len() as u32; - unsafe { (*pentry.as_mut_ptr()).kve_start = 0 }; - if unsafe { - libc::sysctl( - mib, - miblen, - pentry.as_mut_ptr() as *mut libc::c_void, - &mut s, - std::ptr::null_mut(), - 0, - ) - } == 0 - { - let end: u64 = s as u64; - unsafe { - let mut e = pentry.assume_init(); - while libc::sysctl( - mib, - miblen, - &mut e as *mut libc::kinfo_vmentry as *mut libc::c_void, - &mut s, - std::ptr::null_mut(), - 0, - ) == 0 - { - if e.kve_end == end { - break; - } - // OpenBSD's vm mappings have no knowledge of their paths on disk - let i = format!("{}-{}\n", e.kve_start, e.kve_end); - writer.write_all(&i.into_bytes())?; - e.kve_start += 1; - } - } - } else { - return Err(std::io::Error::last_os_error()); - } - - Ok(()) -} - -#[cfg(target_vendor = "apple")] -fn write_minibsod(writer: &mut BufWriter) -> Result<(), std::io::Error> { - let mut ptask = core::mem::MaybeUninit::::uninit(); - // We start by the lowest virtual address from the userland' standpoint - let mut addr: mach_vm_address_t = 0; - let mut _cnt: mach_msg_type_number_t = 0; - let mut sz: mach_vm_size_t = 0; - let mut reg: natural_t = 1; - - let mut r = unsafe { libc::task_for_pid(mach_task_self(), libc::getpid(), ptask.as_mut_ptr()) }; - if r != libc::KERN_SUCCESS { - return Err(std::io::Error::last_os_error()); - } - - let task = unsafe { ptask.assume_init() }; - - loop { - let mut pvminfo = core::mem::MaybeUninit::::uninit(); - _cnt = mach_msg_type_number_t::try_from( - size_of::() / size_of::(), - ) - .unwrap(); - r = unsafe { - mach_vm_region_recurse( - task, - &raw mut addr, - &raw mut sz, - &raw mut reg, - pvminfo.as_mut_ptr() as vm_region_recurse_info_t, - &raw mut _cnt, - ) - }; - if r != libc::KERN_SUCCESS { - break; - } - - let vminfo = unsafe { pvminfo.assume_init() }; - // We are only interested by the first level of the maps - if vminfo.is_submap == 0 { - let i = format!("{}-{}\n", addr, addr + sz); - writer.write_all(&i.into_bytes())?; - } - addr += sz; - } - - Ok(()) -} - -#[cfg(any(target_os = "solaris", target_os = "illumos"))] -fn write_minibsod(writer: &mut BufWriter) -> Result<(), std::io::Error> { - let pid = format!("{}", unsafe { libc::getpid() }); - let mut cmdname = Command::new("pmap"); - let cmd = cmdname.args(["-x", &pid]); - - match cmd.output() { - Ok(s) => writer.write_all(&s.stdout)?, - Err(e) => writeln!(writer, "Couldn't load mappings: {e:?}")?, - } - - Ok(()) -} - -#[cfg(target_os = "haiku")] -fn write_minibsod(writer: &mut BufWriter) -> Result<(), std::io::Error> { - let p = std::mem::MaybeUninit::::uninit(); - let mut info = unsafe { p.assume_init() }; - let mut c: i32 = 0; - - loop { - if unsafe { libc::get_next_image_info(0, &mut c, &mut info) } == libc::B_OK { - let i = format!( - "{}-{} {:?}\n", - info.text as i64, - info.text as i64 + i64::from(info.text_size), - info.name - ); - writer.write_all(&i.into_bytes())?; - } else { - break; - } - } - - Ok(()) -} - -#[cfg(not(any( - target_os = "freebsd", - target_os = "openbsd", - target_os = "netbsd", - target_os = "haiku", - target_vendor = "apple", - any(target_os = "linux", target_os = "android"), - any(target_os = "solaris", target_os = "illumos"), -)))] -fn write_minibsod(writer: &mut BufWriter) -> Result<(), std::io::Error> { - // TODO for other platforms - writeln!(writer, "{:━^100}", " / ")?; - Ok(()) -} - -/// Generates a mini-BSOD given a signal and context. -#[cfg(unix)] -#[expect(clippy::non_ascii_literal)] -pub fn generate_minibsod( - writer: &mut BufWriter, - signal: Signal, - _siginfo: &siginfo_t, - ucontext: Option<&ucontext_t>, -) -> Result<(), std::io::Error> { - writeln!(writer, "{:━^100}", " CRASH ")?; - if let Some(uctx) = ucontext { - write_crash(writer, signal, uctx)?; - - #[cfg(target_pointer_width = "64")] - { - writeln!(writer, "{:━^100}", " REGISTERS ")?; - dump_registers(writer, uctx)?; - } - } else { - writeln!(writer, "Received signal {signal}")?; - } - writeln!(writer, "{:━^100}", " BACKTRACE ")?; - writeln!(writer, "{:?}", backtrace::Backtrace::new())?; - writeln!(writer, "{:━^100}", " MAPS ")?; - write_minibsod(writer) -} - -/// Generates a mini-BSOD given a signal and context and dump it to a [`Vec`] -#[cfg(unix)] -pub fn generate_minibsod_to_vec( - signal: Signal, - siginfo: &siginfo_t, - ucontext: Option<&ucontext_t>, -) -> Result, std::io::Error> { - let mut bsod = Vec::new(); - { - let mut writer = BufWriter::new(&mut bsod); - - generate_minibsod(&mut writer, signal, siginfo, ucontext)?; - - writer.flush()?; - } - Ok(bsod) -} - -/// Generates a mini-BSOD given an `EXCEPTION_POINTERS` structure. -#[cfg(windows)] -#[expect(clippy::non_ascii_literal, clippy::not_unsafe_ptr_arg_deref)] -pub fn generate_minibsod( - writer: &mut BufWriter, - exception_pointers: *mut EXCEPTION_POINTERS, -) -> Result<(), std::io::Error> { - writeln!(writer, "{:━^100}", " CRASH ")?; - write_crash(writer, exception_pointers)?; - writeln!(writer, "{:━^100}", " REGISTERS ")?; - dump_registers(writer, unsafe { - (*exception_pointers).ContextRecord.as_mut().unwrap() - })?; - writeln!(writer, "{:━^100}", " BACKTRACE ")?; - writeln!(writer, "{:?}", backtrace::Backtrace::new())?; - writeln!(writer, "{:━^100}", " MAPS ")?; - write_minibsod(writer) -} - -#[cfg(unix)] -#[cfg(test)] -mod tests { - - use std::io::{BufWriter, stdout}; - - use crate::{minibsod::dump_registers, os::unix_signals::ucontext}; - - #[test] - #[cfg_attr(miri, ignore)] - fn test_dump_registers() { - let ucontext = ucontext().unwrap(); - let mut writer = BufWriter::new(stdout()); - dump_registers(&mut writer, &ucontext).unwrap(); - } -} - -#[cfg(windows)] -#[cfg(test)] -mod tests { - - use std::{ - io::{BufWriter, stdout}, - os::raw::c_void, - sync::mpsc, - }; - - use windows::Win32::{ - Foundation::{CloseHandle, DUPLICATE_SAME_ACCESS, DuplicateHandle, HANDLE}, - System::{ - Diagnostics::Debug::{ - CONTEXT, CONTEXT_FULL_AMD64, CONTEXT_FULL_ARM64, CONTEXT_FULL_X86, GetThreadContext, - }, - Threading::{GetCurrentProcess, GetCurrentThread, ResumeThread, SuspendThread}, - }, - }; - - use crate::minibsod::dump_registers; - - #[derive(Default)] - #[repr(align(16))] - struct Align16 { - pub ctx: CONTEXT, - } - - #[test] - #[cfg_attr(miri, ignore)] - fn test_dump_registers() { - let (tx, rx) = mpsc::channel(); - let (evt_tx, evt_rx) = mpsc::channel(); - let t = std::thread::spawn(move || { - let cur = unsafe { GetCurrentThread() }; - let proc = unsafe { GetCurrentProcess() }; - let mut out = HANDLE::default(); - unsafe { - DuplicateHandle( - proc, - cur, - proc, - &raw mut out, - 0, - true, - DUPLICATE_SAME_ACCESS, - ) - .unwrap(); - }; - tx.send(out.0 as i64).unwrap(); - evt_rx.recv().unwrap(); - }); - - let thread = rx.recv().unwrap(); - let thread = HANDLE(thread as *mut c_void); - eprintln!("thread: {thread:?}"); - unsafe { SuspendThread(thread) }; - - // https://stackoverflow.com/questions/56516445/getting-0x3e6-when-calling-getthreadcontext-for-debugged-thread - let mut c = Align16::default(); - if cfg!(target_arch = "x86") { - c.ctx.ContextFlags = CONTEXT_FULL_X86; - } else if cfg!(target_arch = "x86_64") { - c.ctx.ContextFlags = CONTEXT_FULL_AMD64; - } else if cfg!(target_arch = "aarch64") { - c.ctx.ContextFlags = CONTEXT_FULL_ARM64; - } - unsafe { GetThreadContext(thread, &raw mut (c.ctx)).unwrap() }; - - let mut writer = BufWriter::new(stdout()); - dump_registers(&mut writer, &c.ctx).unwrap(); - - unsafe { ResumeThread(thread) }; - unsafe { CloseHandle(thread).unwrap() }; - evt_tx.send(true).unwrap(); - t.join().unwrap(); - } -} diff --git a/crates/libafl_bolts/src/os/mod.rs b/crates/libafl_bolts/src/os.rs similarity index 96% rename from crates/libafl_bolts/src/os/mod.rs rename to crates/libafl_bolts/src/os.rs index 1b9d81b1c9f..c2aedf97640 100644 --- a/crates/libafl_bolts/src/os/mod.rs +++ b/crates/libafl_bolts/src/os.rs @@ -3,14 +3,6 @@ #[cfg(any(unix, all(windows, feature = "std")))] use crate::Error; -#[cfg(unix)] -pub mod unix_signals; -#[cfg(unix)] -pub use unix_signals::CTRL_C_EXIT; - -#[cfg(all(unix, feature = "alloc"))] -pub mod pipes; - #[cfg(all(unix, feature = "std"))] use alloc::{borrow::Cow, ffi::CString}; #[cfg(all(unix, feature = "std"))] @@ -27,9 +19,6 @@ use std::{ }; // Allow a few extra features we need for the whole module -#[cfg(all(windows, feature = "std"))] -#[expect(missing_docs, overflowing_literals)] -pub mod windows_exceptions; #[cfg(unix)] use libc::pid_t; #[cfg(all(windows, feature = "std"))] diff --git a/crates/libafl_bolts/src/simd.rs b/crates/libafl_bolts/src/simd.rs index 0be9430d765..e3944ea69d3 100644 --- a/crates/libafl_bolts/src/simd.rs +++ b/crates/libafl_bolts/src/simd.rs @@ -131,7 +131,7 @@ where } } -/// Unforunately we have to keep this type due to [`wide`] might not `PartialOrd` +/// Unfortunately we have to keep this type due to [`wide`] might not `PartialOrd` #[cfg(feature = "wide")] #[derive(Debug)] pub struct SimdMinReducer; diff --git a/crates/minibsod/Cargo.toml b/crates/minibsod/Cargo.toml index 98362da0702..d9a1b3a007e 100644 --- a/crates/minibsod/Cargo.toml +++ b/crates/minibsod/Cargo.toml @@ -1,11 +1,11 @@ [package] -name = "ownedref" +name = "minibsod" version.workspace = true authors = [ "Andrea Fioraldi ", "Dominik Maier ", ] -description = "Library to pass around references that will be owned types on deserialization" +description = "A library to dump current register states" documentation = "https://docs.rs/libafl" repository = "https://github.com/AFLplusplus/LibAFL/" readme = "./README.md" @@ -40,9 +40,6 @@ std = [ ## Enables all features that allocate in `no_std` alloc = [] -## Stores the backtraces of all generated `Error`s. Good for debugging, but may come with a slight performance hit. -errors_backtrace = ["backtrace"] - [build-dependencies] rustversion = { workspace = true } @@ -51,6 +48,11 @@ rustversion = { workspace = true } [dependencies] # Document all features of this crate (for `cargo doc`) document-features = { workspace = true, optional = true } +backtrace = { workspace = true } +libc = { workspace = true } + +[target.'cfg(target_vendor = "apple")'.dependencies] +mach2 = "0.4.2" [lints] workspace = true diff --git a/crates/minibsod/src/lib.rs b/crates/minibsod/src/lib.rs index e69de29bb2d..48d9ea29be9 100644 --- a/crates/minibsod/src/lib.rs +++ b/crates/minibsod/src/lib.rs @@ -0,0 +1,1308 @@ +//! Implements a mini-bsod generator. +//! It dumps all important registers and prints a stacktrace. +#![doc = include_str!("../../../README.md")] +/*! */ +#![cfg_attr(feature = "document-features", doc = document_features::document_features!())] +#![no_std] +#![cfg_attr(not(test), warn( + missing_debug_implementations, + missing_docs, + //trivial_casts, + trivial_numeric_casts, + unused_extern_crates, + unused_import_braces, + unused_qualifications, + //unused_results +))] +#![cfg_attr(test, deny( + missing_debug_implementations, + missing_docs, + //trivial_casts, + trivial_numeric_casts, + unused_extern_crates, + unused_import_braces, + unused_qualifications, + unused_must_use, + //unused_results +))] +#![cfg_attr( + test, + deny( + bad_style, + dead_code, + improper_ctypes, + non_shorthand_field_patterns, + no_mangle_generic_items, + overflowing_literals, + path_statements, + patterns_in_fns_without_body, + unconditional_recursion, + unused, + unused_allocation, + unused_comparisons, + unused_parens, + while_true + ) +)] + +#[cfg(feature = "std")] +#[macro_use] +extern crate std; +#[doc(hidden)] +pub extern crate alloc; + +#[cfg(unix)] +use alloc::vec::Vec; +#[cfg(any(target_vendor = "apple", target_os = "openbsd"))] +use core::mem::size_of; +use std::io::{BufWriter, Write}; +#[cfg(any(target_os = "solaris", target_os = "illumos"))] +use std::process::Command; + +#[cfg(unix)] +use libc::siginfo_t; +#[cfg(target_vendor = "apple")] +use mach2::{ + message::mach_msg_type_number_t, + port::mach_port_t, + traps::mach_task_self, + vm::mach_vm_region_recurse, + vm_region::{vm_region_recurse_info_t, vm_region_submap_info_64}, + vm_types::{mach_vm_address_t, mach_vm_size_t, natural_t}, +}; +#[cfg(windows)] +use windows::Win32::System::Diagnostics::Debug::{CONTEXT, EXCEPTION_POINTERS}; + +#[cfg(unix)] +use crate::os::unix_signals::{Signal, ucontext_t}; + +/// Necessary info to print a mini-BSOD. +#[derive(Debug)] +#[cfg(unix)] +pub struct BsodInfo { + /// the signal + pub signal: Signal, + /// siginfo + pub siginfo: siginfo_t, + /// ucontext + pub ucontext: Option, +} + +/// Write the content of all important registers +#[cfg(all( + any(target_os = "linux", target_os = "android"), + target_arch = "x86_64" +))] +pub fn dump_registers( + writer: &mut BufWriter, + ucontext: &ucontext_t, +) -> Result<(), std::io::Error> { + use libc::{ + 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, + }; + + let mcontext = &ucontext.uc_mcontext; + + write!(writer, "r8 : {:#016x}, ", mcontext.gregs[REG_R8 as usize])?; + write!(writer, "r9 : {:#016x}, ", mcontext.gregs[REG_R9 as usize])?; + write!(writer, "r10: {:#016x}, ", mcontext.gregs[REG_R10 as usize])?; + writeln!(writer, "r11: {:#016x}, ", mcontext.gregs[REG_R11 as usize])?; + write!(writer, "r12: {:#016x}, ", mcontext.gregs[REG_R12 as usize])?; + write!(writer, "r13: {:#016x}, ", mcontext.gregs[REG_R13 as usize])?; + write!(writer, "r14: {:#016x}, ", mcontext.gregs[REG_R14 as usize])?; + writeln!(writer, "r15: {:#016x}, ", mcontext.gregs[REG_R15 as usize])?; + write!(writer, "rdi: {:#016x}, ", mcontext.gregs[REG_RDI as usize])?; + write!(writer, "rsi: {:#016x}, ", mcontext.gregs[REG_RSI as usize])?; + write!(writer, "rbp: {:#016x}, ", mcontext.gregs[REG_RBP as usize])?; + writeln!(writer, "rbx: {:#016x}, ", mcontext.gregs[REG_RBX as usize])?; + write!(writer, "rdx: {:#016x}, ", mcontext.gregs[REG_RDX as usize])?; + write!(writer, "rax: {:#016x}, ", mcontext.gregs[REG_RAX as usize])?; + write!(writer, "rcx: {:#016x}, ", mcontext.gregs[REG_RCX as usize])?; + writeln!(writer, "rsp: {:#016x}, ", mcontext.gregs[REG_RSP as usize])?; + write!(writer, "rip: {:#016x}, ", mcontext.gregs[REG_RIP as usize])?; + writeln!(writer, "efl: {:#016x}, ", mcontext.gregs[REG_EFL as usize])?; + + Ok(()) +} + +/// Write the content of all important registers +#[cfg(all(any(target_os = "linux", target_os = "android"), target_arch = "x86"))] +pub fn dump_registers( + writer: &mut BufWriter, + ucontext: &ucontext_t, +) -> Result<(), std::io::Error> { + use libc::{ + REG_EAX, REG_EBP, REG_EBX, REG_ECX, REG_EDI, REG_EDX, REG_EFL, REG_EIP, REG_ESI, REG_ESP, + }; + + let mcontext = &ucontext.uc_mcontext; + + write!(writer, "eax: {:#016x}, ", mcontext.gregs[REG_EAX as usize])?; + write!(writer, "ebx: {:#016x}, ", mcontext.gregs[REG_EBX as usize])?; + write!(writer, "ecx: {:#016x}, ", mcontext.gregs[REG_ECX as usize])?; + writeln!(writer, "edx: {:#016x}, ", mcontext.gregs[REG_EDX as usize])?; + write!(writer, "edi: {:#016x}, ", mcontext.gregs[REG_EDI as usize])?; + write!(writer, "esi: {:#016x}, ", mcontext.gregs[REG_ESI as usize])?; + write!(writer, "esp: {:#016x}, ", mcontext.gregs[REG_ESP as usize])?; + writeln!(writer, "ebp: {:#016x}, ", mcontext.gregs[REG_EBP as usize])?; + write!(writer, "eip: {:#016x}, ", mcontext.gregs[REG_EIP as usize])?; + writeln!(writer, "efl: {:#016x}, ", mcontext.gregs[REG_EFL as usize])?; + + Ok(()) +} + +/// Write the content of all important registers +#[cfg(all( + any(target_os = "linux", target_os = "android"), + target_arch = "aarch64" +))] +pub fn dump_registers( + writer: &mut BufWriter, + ucontext: &ucontext_t, +) -> Result<(), std::io::Error> { + for reg in 0..31_usize { + write!( + writer, + "x{:02}: 0x{:016x} ", + reg, ucontext.uc_mcontext.regs[reg] + )?; + if reg % 4 == 3 { + writeln!(writer)?; + } + } + writeln!(writer, "pc : 0x{:016x} ", ucontext.uc_mcontext.pc)?; + + Ok(()) +} + +/// Write the content of all important registers +#[cfg(all(target_os = "linux", target_arch = "arm"))] +pub fn dump_registers( + writer: &mut BufWriter, + ucontext: &ucontext_t, +) -> Result<(), std::io::Error> { + write!(writer, "r0 : {:#016x}, ", ucontext.uc_mcontext.arm_r0)?; + write!(writer, "r1 : {:#016x}, ", ucontext.uc_mcontext.arm_r1)?; + write!(writer, "r2: {:#016x}, ", ucontext.uc_mcontext.arm_r2)?; + writeln!(writer, "r3: {:#016x}, ", ucontext.uc_mcontext.arm_r3)?; + write!(writer, "r4: {:#016x}, ", ucontext.uc_mcontext.arm_r4)?; + write!(writer, "r5: {:#016x}, ", ucontext.uc_mcontext.arm_r5)?; + write!(writer, "r6: {:#016x}, ", ucontext.uc_mcontext.arm_r6)?; + writeln!(writer, "r7: {:#016x}, ", ucontext.uc_mcontext.arm_r7)?; + write!(writer, "r8: {:#016x}, ", ucontext.uc_mcontext.arm_r8)?; + write!(writer, "r9: {:#016x}, ", ucontext.uc_mcontext.arm_r9)?; + write!(writer, "r10: {:#016x}, ", ucontext.uc_mcontext.arm_r10)?; + writeln!(writer, "fp: {:#016x}, ", ucontext.uc_mcontext.arm_fp)?; + write!(writer, "ip: {:#016x}, ", ucontext.uc_mcontext.arm_ip)?; + write!(writer, "sp: {:#016x}, ", ucontext.uc_mcontext.arm_sp)?; + write!(writer, "lr: {:#016x}, ", ucontext.uc_mcontext.arm_lr)?; + writeln!(writer, "cpsr: {:#016x}, ", ucontext.uc_mcontext.arm_cpsr)?; + + writeln!(writer, "pc : 0x{:016x} ", ucontext.uc_mcontext.arm_pc)?; + + Ok(()) +} + +/// Write the content of all important registers +#[cfg(all(target_os = "freebsd", target_arch = "aarch64"))] +pub fn dump_registers( + writer: &mut BufWriter, + ucontext: &ucontext_t, +) -> Result<(), std::io::Error> { + let mcontext = unsafe { &*ucontext.uc_mcontext }; + for reg in 0..29_u8 { + writeln!( + writer, + "x{:02}: 0x{:016x} ", + reg, mcontext.mc_gpregs.gp_x[reg as usize] + )?; + if reg % 4 == 3 { + writeln!(writer)?; + } + } + write!(writer, "lr: 0x{:016x} ", mcontext.mc_gpregs.gp_lr)?; + write!(writer, "sp: 0x{:016x} ", mcontext.mc_gpregs.gp_sp)?; + + Ok(()) +} + +/// Write the content of all important registers +#[cfg(all(target_vendor = "apple", target_arch = "aarch64"))] +pub fn dump_registers( + writer: &mut BufWriter, + ucontext: &ucontext_t, +) -> Result<(), std::io::Error> { + let mcontext = unsafe { &*ucontext.uc_mcontext }; + for reg in 0..29_u8 { + writeln!( + writer, + "x{:02}: 0x{:016x} ", + reg, mcontext.__ss.__x[reg as usize] + )?; + if reg % 4 == 3 { + writeln!(writer)?; + } + } + write!(writer, "fp: 0x{:016x} ", mcontext.__ss.__fp)?; + write!(writer, "lr: 0x{:016x} ", mcontext.__ss.__lr)?; + write!(writer, "pc: 0x{:016x} ", mcontext.__ss.__pc)?; + + Ok(()) +} + +/// Write the content of all important registers +#[expect(clippy::unnecessary_wraps, clippy::similar_names)] +#[cfg(all(target_vendor = "apple", target_arch = "x86_64"))] +pub fn dump_registers( + writer: &mut BufWriter, + ucontext: &ucontext_t, +) -> Result<(), std::io::Error> { + let mcontext = unsafe { *ucontext.uc_mcontext }; + let ss = mcontext.__ss; + + write!(writer, "r8 : {:#016x}, ", ss.__r8)?; + write!(writer, "r9 : {:#016x}, ", ss.__r9)?; + write!(writer, "r10: {:#016x}, ", ss.__r10)?; + writeln!(writer, "r11: {:#016x}, ", ss.__r11)?; + write!(writer, "r12: {:#016x}, ", ss.__r12)?; + write!(writer, "r13: {:#016x}, ", ss.__r13)?; + write!(writer, "r14: {:#016x}, ", ss.__r14)?; + writeln!(writer, "r15: {:#016x}, ", ss.__r15)?; + write!(writer, "rdi: {:#016x}, ", ss.__rdi)?; + write!(writer, "rsi: {:#016x}, ", ss.__rsi)?; + write!(writer, "rbp: {:#016x}, ", ss.__rbp)?; + writeln!(writer, "rbx: {:#016x}, ", ss.__rbx)?; + write!(writer, "rdx: {:#016x}, ", ss.__rdx)?; + write!(writer, "rax: {:#016x}, ", ss.__rax)?; + write!(writer, "rcx: {:#016x}, ", ss.__rcx)?; + writeln!(writer, "rsp: {:#016x}, ", ss.__rsp)?; + write!(writer, "rip: {:#016x}, ", ss.__rip)?; + writeln!(writer, "efl: {:#016x}, ", ss.__rflags)?; + + Ok(()) +} + +/// Write the content of all important registers +#[cfg(all( + any(target_os = "freebsd", target_os = "dragonfly"), + target_arch = "x86_64" +))] +pub fn dump_registers( + writer: &mut BufWriter, + ucontext: &ucontext_t, +) -> Result<(), std::io::Error> { + let mcontext = &ucontext.uc_mcontext; + + write!(writer, "r8 : {:#016x}, ", mcontext.mc_r8)?; + write!(writer, "r9 : {:#016x}, ", mcontext.mc_r9)?; + write!(writer, "r10 : {:#016x}, ", mcontext.mc_r10)?; + write!(writer, "r11 : {:#016x}, ", mcontext.mc_r11)?; + write!(writer, "r12 : {:#016x}, ", mcontext.mc_r12)?; + write!(writer, "r13 : {:#016x}, ", mcontext.mc_r13)?; + write!(writer, "r14 : {:#016x}, ", mcontext.mc_r14)?; + write!(writer, "r15 : {:#016x}, ", mcontext.mc_r15)?; + write!(writer, "rdi : {:#016x}, ", mcontext.mc_rdi)?; + write!(writer, "rsi : {:#016x}, ", mcontext.mc_rsi)?; + write!(writer, "rbp : {:#016x}, ", mcontext.mc_rbp)?; + write!(writer, "rbx : {:#016x}, ", mcontext.mc_rbx)?; + write!(writer, "rdx : {:#016x}, ", mcontext.mc_rdx)?; + write!(writer, "rax : {:#016x}, ", mcontext.mc_rax)?; + write!(writer, "rcx : {:#016x}, ", mcontext.mc_rcx)?; + write!(writer, "rsp : {:#016x}, ", mcontext.mc_rsp)?; + write!(writer, "rflags : {:#016x}, ", mcontext.mc_rflags)?; + write!(writer, "cs : {:#016x}, ", mcontext.mc_cs)?; + Ok(()) +} + +/// Write the content of all important registers +#[cfg(all(target_os = "netbsd", target_arch = "x86_64"))] +pub fn dump_registers( + writer: &mut BufWriter, + ucontext: &ucontext_t, +) -> Result<(), std::io::Error> { + use libc::{ + _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, + }; + + let mcontext = &ucontext.uc_mcontext; + + write!( + writer, + "r8 : {:#016x}, ", + mcontext.__gregs[_REG_R8 as usize] + )?; + write!( + writer, + "r9 : {:#016x}, ", + mcontext.__gregs[_REG_R9 as usize] + )?; + write!( + writer, + "r10: {:#016x}, ", + mcontext.__gregs[_REG_R10 as usize] + )?; + writeln!( + writer, + "r11: {:#016x}, ", + mcontext.__gregs[_REG_R11 as usize] + )?; + write!( + writer, + "r12: {:#016x}, ", + mcontext.__gregs[_REG_R12 as usize] + )?; + write!( + writer, + "r13: {:#016x}, ", + mcontext.__gregs[_REG_R13 as usize] + )?; + write!( + writer, + "r14: {:#016x}, ", + mcontext.__gregs[_REG_R14 as usize] + )?; + writeln!( + writer, + "r15: {:#016x}, ", + mcontext.__gregs[_REG_R15 as usize] + )?; + write!( + writer, + "rdi: {:#016x}, ", + mcontext.__gregs[_REG_RDI as usize] + )?; + write!( + writer, + "rsi: {:#016x}, ", + mcontext.__gregs[_REG_RSI as usize] + )?; + write!( + writer, + "rbp: {:#016x}, ", + mcontext.__gregs[_REG_RBP as usize] + )?; + writeln!( + writer, + "rbx: {:#016x}, ", + mcontext.__gregs[_REG_RBX as usize] + )?; + write!( + writer, + "rdx: {:#016x}, ", + mcontext.__gregs[_REG_RDX as usize] + )?; + write!( + writer, + "rax: {:#016x}, ", + mcontext.__gregs[_REG_RAX as usize] + )?; + write!( + writer, + "rcx: {:#016x}, ", + mcontext.__gregs[_REG_RCX as usize] + )?; + writeln!( + writer, + "rsp: {:#016x}, ", + mcontext.__gregs[_REG_RSP as usize] + )?; + write!( + writer, + "rip: {:#016x}, ", + mcontext.__gregs[_REG_RIP as usize] + )?; + write!(writer, "cs: {:#016x}, ", mcontext.__gregs[_REG_CS as usize])?; + writeln!( + writer, + "rflags: {:#016x}, ", + mcontext.__gregs[_REG_RFLAGS as usize] + )?; + + Ok(()) +} + +/// Write the content of all important registers +#[cfg(all(target_os = "openbsd", target_arch = "x86_64"))] +pub fn dump_registers( + writer: &mut BufWriter, + ucontext: &ucontext_t, +) -> Result<(), std::io::Error> { + write!(writer, "r8 : {:#016x}, ", ucontext.sc_r8)?; + write!(writer, "r9 : {:#016x}, ", ucontext.sc_r9)?; + write!(writer, "r10 : {:#016x}, ", ucontext.sc_r10)?; + write!(writer, "r11 : {:#016x}, ", ucontext.sc_r11)?; + write!(writer, "r12 : {:#016x}, ", ucontext.sc_r12)?; + write!(writer, "r13 : {:#016x}, ", ucontext.sc_r13)?; + write!(writer, "r14 : {:#016x}, ", ucontext.sc_r14)?; + write!(writer, "r15 : {:#016x}, ", ucontext.sc_r15)?; + write!(writer, "rdi : {:#016x}, ", ucontext.sc_rdi)?; + write!(writer, "rsi : {:#016x}, ", ucontext.sc_rsi)?; + write!(writer, "rbp : {:#016x}, ", ucontext.sc_rbp)?; + write!(writer, "rbx : {:#016x}, ", ucontext.sc_rbx)?; + write!(writer, "rdx : {:#016x}, ", ucontext.sc_rdx)?; + write!(writer, "rax : {:#016x}, ", ucontext.sc_rax)?; + write!(writer, "rcx : {:#016x}, ", ucontext.sc_rcx)?; + write!(writer, "rsp : {:#016x}, ", ucontext.sc_rsp)?; + write!(writer, "rflags : {:#016x}, ", ucontext.sc_rflags)?; + write!(writer, "cs : {:#016x}, ", ucontext.sc_cs)?; + Ok(()) +} + +/// Write the content of all important registers +#[cfg(all(target_os = "openbsd", target_arch = "aarch64"))] +pub fn dump_registers( + writer: &mut BufWriter, + ucontext: &ucontext_t, +) -> Result<(), std::io::Error> { + for reg in 0..29_usize { + write!(writer, "x{:02}: 0x{:016x} ", reg, ucontext.sc_x[reg])?; + if reg % 4 == 3 { + writeln!(writer)?; + } + } + write!(writer, "lr : {:#016x}, ", ucontext.sc_lr)?; + write!(writer, "elr : {:#016x}, ", ucontext.sc_elr)?; + write!(writer, "sp : {:#016x}, ", ucontext.sc_sp)?; + write!(writer, "spsr : {:#016x}, ", ucontext.sc_spsr)?; +} + +/// +/// Write the content of all important registers +#[cfg(all( + any(target_os = "solaris", target_os = "illumos"), + target_arch = "x86_64" +))] +pub fn dump_registers( + writer: &mut BufWriter, + ucontext: &ucontext_t, +) -> Result<(), std::io::Error> { + use libc::{ + 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, + }; + + let mcontext = &ucontext.uc_mcontext; + + write!(writer, "r8 : {:#016x}, ", mcontext.gregs[REG_R8 as usize])?; + write!(writer, "r9 : {:#016x}, ", mcontext.gregs[REG_R9 as usize])?; + write!(writer, "r10: {:#016x}, ", mcontext.gregs[REG_R10 as usize])?; + writeln!(writer, "r11: {:#016x}, ", mcontext.gregs[REG_R11 as usize])?; + write!(writer, "r12: {:#016x}, ", mcontext.gregs[REG_R12 as usize])?; + write!(writer, "r13: {:#016x}, ", mcontext.gregs[REG_R13 as usize])?; + write!(writer, "r14: {:#016x}, ", mcontext.gregs[REG_R14 as usize])?; + writeln!(writer, "r15: {:#016x}, ", mcontext.gregs[REG_R15 as usize])?; + write!(writer, "rdi: {:#016x}, ", mcontext.gregs[REG_RDI as usize])?; + write!(writer, "rsi: {:#016x}, ", mcontext.gregs[REG_RSI as usize])?; + write!(writer, "rbp: {:#016x}, ", mcontext.gregs[REG_RBP as usize])?; + writeln!(writer, "rbx: {:#016x}, ", mcontext.gregs[REG_RBX as usize])?; + write!(writer, "rdx: {:#016x}, ", mcontext.gregs[REG_RDX as usize])?; + write!(writer, "rax: {:#016x}, ", mcontext.gregs[REG_RAX as usize])?; + write!(writer, "rcx: {:#016x}, ", mcontext.gregs[REG_RCX as usize])?; + writeln!(writer, "rsp: {:#016x}, ", mcontext.gregs[REG_RSP as usize])?; + write!(writer, "rip: {:#016x}, ", mcontext.gregs[REG_RIP as usize])?; + writeln!(writer, "efl: {:#016x}, ", mcontext.gregs[REG_RFL as usize])?; + + Ok(()) +} + +/// Write the content of all important registers +#[cfg(all(target_os = "windows", target_arch = "x86_64"))] +pub fn dump_registers( + writer: &mut BufWriter, + context: &CONTEXT, +) -> Result<(), std::io::Error> { + write!(writer, "r8 : {:#018x}, ", context.R8)?; + write!(writer, "r9 : {:#018x}, ", context.R9)?; + write!(writer, "r10: {:#018x}, ", context.R10)?; + writeln!(writer, "r11: {:#018x}, ", context.R11)?; + write!(writer, "r12: {:#018x}, ", context.R12)?; + write!(writer, "r13: {:#018x}, ", context.R13)?; + write!(writer, "r14: {:#018x}, ", context.R14)?; + writeln!(writer, "r15: {:#018x}, ", context.R15)?; + write!(writer, "rdi: {:#018x}, ", context.Rdi)?; + write!(writer, "rsi: {:#018x}, ", context.Rsi)?; + write!(writer, "rbp: {:#018x}, ", context.Rbp)?; + writeln!(writer, "rbx: {:#018x}, ", context.Rbx)?; + write!(writer, "rdx: {:#018x}, ", context.Rdx)?; + write!(writer, "rax: {:#018x}, ", context.Rax)?; + write!(writer, "rcx: {:#018x}, ", context.Rcx)?; + writeln!(writer, "rsp: {:#018x}, ", context.Rsp)?; + write!(writer, "rip: {:#018x}, ", context.Rip)?; + writeln!(writer, "efl: {:#018x}", context.EFlags)?; + + Ok(()) +} + +/// Write the content of all important registers +#[cfg(all(target_os = "windows", target_arch = "x86"))] +pub fn dump_registers( + writer: &mut BufWriter, + context: &CONTEXT, +) -> Result<(), std::io::Error> { + write!(writer, "eax: {:#010x}, ", context.Eax)?; + write!(writer, "ebx: {:#010x}, ", context.Ebx)?; + write!(writer, "ecx: {:#010x}, ", context.Ecx)?; + writeln!(writer, "edx: {:#010x}, ", context.Edx)?; + write!(writer, "edi: {:#010x}, ", context.Edi)?; + write!(writer, "esi: {:#010x}, ", context.Esi)?; + write!(writer, "esp: {:#010x}, ", context.Esp)?; + writeln!(writer, "ebp: {:#010x}, ", context.Ebp)?; + write!(writer, "eip: {:#010x}, ", context.Eip)?; + writeln!(writer, "efl: {:#010x} ", context.EFlags)?; + Ok(()) +} + +/// Write the content of all important registers +#[cfg(all(target_os = "windows", target_arch = "aarch64"))] +pub fn dump_registers( + writer: &mut BufWriter, + context: &CONTEXT, +) -> Result<(), std::io::Error> { + for reg in 0..29_usize { + write!(writer, "x{:02}: 0x{:016x} ", reg, unsafe { + context.Anonymous.X[reg] + })?; + if reg % 4 == 3 || reg == 28_usize { + writeln!(writer)?; + } + } + writeln!(writer, "pc : 0x{:016x} ", context.Pc)?; + writeln!(writer, "sp : 0x{:016x} ", context.Sp)?; + writeln!(writer, "fp : 0x{:016x} ", unsafe { + context.Anonymous.Anonymous.Fp + })?; + writeln!(writer, "lr : 0x{:016x} ", unsafe { + context.Anonymous.Anonymous.Lr + })?; + + Ok(()) +} + +/// Write the content of all important registers +#[cfg(all(target_os = "haiku", target_arch = "x86_64"))] +pub fn dump_registers( + writer: &mut BufWriter, + ucontext: &ucontext_t, +) -> Result<(), std::io::Error> { + let mcontext = &ucontext.uc_mcontext; + + write!(writer, "r8 : {:#016x}, ", mcontext.r8)?; + write!(writer, "r9 : {:#016x}, ", mcontext.r9)?; + write!(writer, "r10 : {:#016x}, ", mcontext.r10)?; + write!(writer, "r11 : {:#016x}, ", mcontext.r11)?; + write!(writer, "r12 : {:#016x}, ", mcontext.r12)?; + write!(writer, "r13 : {:#016x}, ", mcontext.r13)?; + write!(writer, "r14 : {:#016x}, ", mcontext.r14)?; + write!(writer, "r15 : {:#016x}, ", mcontext.r15)?; + write!(writer, "rdi : {:#016x}, ", mcontext.rdi)?; + write!(writer, "rsi : {:#016x}, ", mcontext.rsi)?; + write!(writer, "rbp : {:#016x}, ", mcontext.rbp)?; + write!(writer, "rbx : {:#016x}, ", mcontext.rbx)?; + write!(writer, "rdx : {:#016x}, ", mcontext.rdx)?; + write!(writer, "rax : {:#016x}, ", mcontext.rax)?; + write!(writer, "rcx : {:#016x}, ", mcontext.rcx)?; + write!(writer, "rsp : {:#016x}, ", mcontext.rsp)?; + write!(writer, "rflags : {:#016x}, ", mcontext.rflags)?; + Ok(()) +} + +#[expect(clippy::unnecessary_wraps)] +#[cfg(not(any( + target_vendor = "apple", + target_os = "linux", + target_os = "android", + target_os = "freebsd", + target_os = "dragonfly", + target_os = "netbsd", + target_os = "openbsd", + windows, + target_os = "haiku", + any(target_os = "solaris", target_os = "illumos"), +)))] +fn dump_registers( + writer: &mut BufWriter, + _ucontext: &ucontext_t, +) -> Result<(), std::io::Error> { + // TODO: Implement dump registers + writeln!( + writer, + "< Dumping registers is not yet supported on platform {:?}. Please add it to `minibsod.rs` >", + std::env::consts::OS + )?; + Ok(()) +} + +#[cfg(all( + any(target_os = "linux", target_os = "android"), + target_arch = "x86_64" +))] +fn write_crash( + writer: &mut BufWriter, + signal: Signal, + ucontext: &ucontext_t, +) -> Result<(), std::io::Error> { + writeln!( + writer, + "Received signal {} at {:#016x}, fault address: {:#016x}", + signal, + ucontext.uc_mcontext.gregs[libc::REG_RIP as usize], + ucontext.uc_mcontext.gregs[libc::REG_CR2 as usize] + )?; + + Ok(()) +} + +#[cfg(all(any(target_os = "linux", target_os = "android"), target_arch = "x86"))] +fn write_crash( + writer: &mut BufWriter, + signal: Signal, + ucontext: &ucontext_t, +) -> Result<(), std::io::Error> { + writeln!( + writer, + "Received signal {} at {:#08x}, fault address: {:#08x}", + signal, + ucontext.uc_mcontext.gregs[libc::REG_EIP as usize], + ucontext.uc_mcontext.cr2 + )?; + + Ok(()) +} + +#[cfg(all( + any(target_os = "linux", target_os = "android"), + target_arch = "aarch64" +))] +fn write_crash( + writer: &mut BufWriter, + signal: Signal, + ucontext: &ucontext_t, +) -> Result<(), std::io::Error> { + writeln!( + writer, + "Received signal {} at 0x{:016x}, fault address: 0x{:016x}", + signal, ucontext.uc_mcontext.pc, ucontext.uc_mcontext.fault_address + )?; + + Ok(()) +} + +#[cfg(all(target_os = "linux", target_arch = "arm"))] +fn write_crash( + writer: &mut BufWriter, + signal: Signal, + ucontext: &ucontext_t, +) -> Result<(), std::io::Error> { + writeln!( + writer, + "Received signal {} at 0x{:016x}, fault address: 0x{:016x}", + signal, ucontext.uc_mcontext.arm_pc, ucontext.uc_mcontext.fault_address + )?; + + Ok(()) +} + +#[cfg(all(target_os = "freebsd", target_arch = "aarch64"))] +fn write_crash( + writer: &mut BufWriter, + signal: Signal, + ucontext: &ucontext_t, +) -> Result<(), std::io::Error> { + writeln!( + writer, + "Received signal {} at 0x{:016x}", + signal, ucontext.uc_mcontext.mc_gpregs.gp_elr + )?; + + Ok(()) +} + +#[cfg(all(target_vendor = "apple", target_arch = "aarch64"))] +fn write_crash( + writer: &mut BufWriter, + signal: Signal, + ucontext: &ucontext_t, +) -> Result<(), std::io::Error> { + let mcontext = unsafe { &*ucontext.uc_mcontext }; + writeln!( + writer, + "Received signal {} at 0x{:016x}, fault address: 0x{:016x}", + signal, mcontext.__ss.__pc, mcontext.__es.__far + )?; + + Ok(()) +} + +#[cfg(all(target_vendor = "apple", target_arch = "x86_64"))] +fn write_crash( + writer: &mut BufWriter, + signal: Signal, + ucontext: &ucontext_t, +) -> Result<(), std::io::Error> { + let mcontext = unsafe { *ucontext.uc_mcontext }; + + writeln!( + writer, + "Received signal {} at 0x{:016x}, fault address: 0x{:016x}, trapno: 0x{:x}, err: 0x{:x}", + signal, + mcontext.__ss.__rip, + mcontext.__es.__faultvaddr, + mcontext.__es.__trapno, + mcontext.__es.__err + )?; + + Ok(()) +} + +#[cfg(all(target_os = "freebsd", target_arch = "x86_64"))] +fn write_crash( + writer: &mut BufWriter, + signal: Signal, + ucontext: &ucontext_t, +) -> Result<(), std::io::Error> { + writeln!( + writer, + "Received signal {} at{:016x}, fault address: 0x{:016x}", + signal, ucontext.uc_mcontext.mc_rip, ucontext.uc_mcontext.mc_fs + )?; + + Ok(()) +} + +#[cfg(all(target_os = "dragonfly", target_arch = "x86_64"))] +fn write_crash( + writer: &mut BufWriter, + signal: Signal, + ucontext: &ucontext_t, +) -> Result<(), std::io::Error> { + writeln!( + writer, + "Received signal {} at{:016x}, fault address: 0x{:016x}", + signal, ucontext.uc_mcontext.mc_rip, ucontext.uc_mcontext.mc_cs + )?; + + Ok(()) +} + +#[cfg(all(target_os = "openbsd", target_arch = "x86_64"))] +fn write_crash( + writer: &mut BufWriter, + signal: Signal, + ucontext: &ucontext_t, +) -> Result<(), std::io::Error> { + writeln!( + writer, + "Received signal {} at{:016x}, fault address: 0x{:016x}", + signal, ucontext.sc_rip, ucontext.sc_fs + )?; + + Ok(()) +} + +#[cfg(all(target_os = "openbsd", target_arch = "aarch64"))] +fn write_crash( + writer: &mut BufWriter, + signal: Signal, + ucontext: &ucontext_t, +) -> Result<(), std::io::Error> { + writeln!( + writer, + "Received signal {} at{:016x}", + signal, ucontext.sc_elr + )?; + + Ok(()) +} + +#[cfg(all(target_os = "netbsd", target_arch = "x86_64"))] +fn write_crash( + writer: &mut BufWriter, + signal: Signal, + ucontext: &ucontext_t, +) -> Result<(), std::io::Error> { + writeln!( + writer, + "Received signal {} at {:#016x}, fault address: {:#016x}", + signal, ucontext.uc_mcontext.__gregs[21], ucontext.uc_mcontext.__gregs[16] + )?; + + Ok(()) +} + +#[cfg(all( + any(target_os = "solaris", target_os = "illumos"), + target_arch = "x86_64" +))] +fn write_crash( + writer: &mut BufWriter, + signal: Signal, + ucontext: &ucontext_t, +) -> Result<(), std::io::Error> { + writeln!( + writer, + "Received signal {} at {:#016x}, fault address: {:#016x}", + signal, + ucontext.uc_mcontext.gregs[libc::REG_RIP as usize], + ucontext.uc_mcontext.gregs[libc::REG_FS as usize] + )?; + + Ok(()) +} + +#[cfg(all(target_os = "haiku", target_arch = "x86_64"))] +fn write_crash( + writer: &mut BufWriter, + signal: Signal, + ucontext: &ucontext_t, +) -> Result<(), std::io::Error> { + writeln!( + writer, + "Received signal {} at {:#016x}", + signal, ucontext.uc_mcontext.rip + )?; + + Ok(()) +} + +#[cfg(not(any( + target_vendor = "apple", + target_os = "linux", + target_os = "android", + target_os = "freebsd", + target_os = "dragonfly", + target_os = "openbsd", + target_os = "netbsd", + windows, + target_os = "haiku", + any(target_os = "solaris", target_os = "illumos"), +)))] +fn write_crash( + writer: &mut BufWriter, + signal: Signal, + _ucontext: &ucontext_t, +) -> Result<(), std::io::Error> { + // TODO add fault addr for other platforms. + writeln!(writer, "Received signal {signal}")?; + + Ok(()) +} + +#[cfg(windows)] +fn write_crash( + writer: &mut BufWriter, + exception_pointers: *mut EXCEPTION_POINTERS, +) -> Result<(), std::io::Error> { + // TODO add fault addr for other platforms. + unsafe { + writeln!( + writer, + "Received exception {:0x} at address {:x}", + (*exception_pointers) + .ExceptionRecord + .as_mut() + .unwrap() + .ExceptionCode + .0, + (*exception_pointers) + .ExceptionRecord + .as_mut() + .unwrap() + .ExceptionAddress as usize + ) + }?; + + Ok(()) +} + +#[cfg(any(target_os = "linux", target_os = "android"))] +fn write_minibsod(writer: &mut BufWriter) -> Result<(), std::io::Error> { + match std::fs::read_to_string("/proc/self/maps") { + Ok(maps) => writer.write_all(maps.as_bytes())?, + Err(e) => writeln!(writer, "Couldn't load mappings: {e:?}")?, + } + + Ok(()) +} + +#[cfg(any(target_os = "freebsd", target_os = "netbsd"))] +#[expect(clippy::cast_ptr_alignment)] +fn write_minibsod(writer: &mut BufWriter) -> Result<(), std::io::Error> { + let mut s: usize = 0; + #[cfg(target_os = "freebsd")] + let arr = &[libc::CTL_KERN, libc::KERN_PROC, libc::KERN_PROC_VMMAP, -1]; + #[cfg(target_os = "netbsd")] + let arr = &[ + libc::CTL_VM, + libc::VM_PROC, + libc::VM_PROC_MAP, + -1, + size_of::() + .try_into() + .expect("Invalid libc::kinfo_vmentry size"), + ]; + let mib = arr.as_ptr(); + let miblen = arr.len() as u32; + if unsafe { + libc::sysctl( + mib, + miblen, + std::ptr::null_mut(), + &mut s, + std::ptr::null_mut(), + 0, + ) + } == 0 + { + s = s * 4 / 3; + let mut buf: std::boxed::Box<[u8]> = vec![0; s].into_boxed_slice(); + let bufptr = buf.as_mut_ptr() as *mut libc::c_void; + if unsafe { libc::sysctl(mib, miblen, bufptr, &mut s, std::ptr::null_mut(), 0) } == 0 { + let mut start = bufptr as usize; + let end = start + s; + + unsafe { + while start < end { + let entry = start as *mut u8 as *mut libc::kinfo_vmentry; + #[cfg(target_os = "freebsd")] + let sz: usize = (*entry) + .kve_structsize + .try_into() + .expect("invalid kve_structsize value"); + #[cfg(target_os = "netbsd")] + let sz = size_of::(); + if sz == 0 { + break; + } + + let i = format!( + "{}-{} {:?}\n", + (*entry).kve_start, + (*entry).kve_end, + (*entry).kve_path + ); + writer.write_all(&i.into_bytes())?; + + start += sz; + } + } + } else { + return Err(std::io::Error::last_os_error()); + } + } else { + return Err(std::io::Error::last_os_error()); + } + + Ok(()) +} + +#[cfg(target_os = "openbsd")] +fn write_minibsod(writer: &mut BufWriter) -> Result<(), std::io::Error> { + let mut pentry = std::mem::MaybeUninit::::uninit(); + let mut s = size_of::(); + let arr = &[libc::CTL_KERN, libc::KERN_PROC_VMMAP, unsafe { + libc::getpid() + }]; + let mib = arr.as_ptr(); + let miblen = arr.len() as u32; + unsafe { (*pentry.as_mut_ptr()).kve_start = 0 }; + if unsafe { + libc::sysctl( + mib, + miblen, + pentry.as_mut_ptr() as *mut libc::c_void, + &mut s, + std::ptr::null_mut(), + 0, + ) + } == 0 + { + let end: u64 = s as u64; + unsafe { + let mut e = pentry.assume_init(); + while libc::sysctl( + mib, + miblen, + &mut e as *mut libc::kinfo_vmentry as *mut libc::c_void, + &mut s, + std::ptr::null_mut(), + 0, + ) == 0 + { + if e.kve_end == end { + break; + } + // OpenBSD's vm mappings have no knowledge of their paths on disk + let i = format!("{}-{}\n", e.kve_start, e.kve_end); + writer.write_all(&i.into_bytes())?; + e.kve_start += 1; + } + } + } else { + return Err(std::io::Error::last_os_error()); + } + + Ok(()) +} + +#[cfg(target_vendor = "apple")] +fn write_minibsod(writer: &mut BufWriter) -> Result<(), std::io::Error> { + let mut ptask = core::mem::MaybeUninit::::uninit(); + // We start by the lowest virtual address from the userland' standpoint + let mut addr: mach_vm_address_t = 0; + let mut _cnt: mach_msg_type_number_t = 0; + let mut sz: mach_vm_size_t = 0; + let mut reg: natural_t = 1; + + let mut r = unsafe { libc::task_for_pid(mach_task_self(), libc::getpid(), ptask.as_mut_ptr()) }; + if r != libc::KERN_SUCCESS { + return Err(std::io::Error::last_os_error()); + } + + let task = unsafe { ptask.assume_init() }; + + loop { + let mut pvminfo = core::mem::MaybeUninit::::uninit(); + _cnt = mach_msg_type_number_t::try_from( + size_of::() / size_of::(), + ) + .unwrap(); + r = unsafe { + mach_vm_region_recurse( + task, + &raw mut addr, + &raw mut sz, + &raw mut reg, + pvminfo.as_mut_ptr() as vm_region_recurse_info_t, + &raw mut _cnt, + ) + }; + if r != libc::KERN_SUCCESS { + break; + } + + let vminfo = unsafe { pvminfo.assume_init() }; + // We are only interested by the first level of the maps + if vminfo.is_submap == 0 { + let i = format!("{}-{}\n", addr, addr + sz); + writer.write_all(&i.into_bytes())?; + } + addr += sz; + } + + Ok(()) +} + +#[cfg(any(target_os = "solaris", target_os = "illumos"))] +fn write_minibsod(writer: &mut BufWriter) -> Result<(), std::io::Error> { + let pid = format!("{}", unsafe { libc::getpid() }); + let mut cmdname = Command::new("pmap"); + let cmd = cmdname.args(["-x", &pid]); + + match cmd.output() { + Ok(s) => writer.write_all(&s.stdout)?, + Err(e) => writeln!(writer, "Couldn't load mappings: {e:?}")?, + } + + Ok(()) +} + +#[cfg(target_os = "haiku")] +fn write_minibsod(writer: &mut BufWriter) -> Result<(), std::io::Error> { + let p = std::mem::MaybeUninit::::uninit(); + let mut info = unsafe { p.assume_init() }; + let mut c: i32 = 0; + + loop { + if unsafe { libc::get_next_image_info(0, &mut c, &mut info) } == libc::B_OK { + let i = format!( + "{}-{} {:?}\n", + info.text as i64, + info.text as i64 + i64::from(info.text_size), + info.name + ); + writer.write_all(&i.into_bytes())?; + } else { + break; + } + } + + Ok(()) +} + +#[cfg(not(any( + target_os = "freebsd", + target_os = "openbsd", + target_os = "netbsd", + target_os = "haiku", + target_vendor = "apple", + any(target_os = "linux", target_os = "android"), + any(target_os = "solaris", target_os = "illumos"), +)))] +fn write_minibsod(writer: &mut BufWriter) -> Result<(), std::io::Error> { + // TODO for other platforms + writeln!(writer, "{:━^100}", " / ")?; + Ok(()) +} + +/// Generates a mini-BSOD given a signal and context. +#[cfg(unix)] +#[expect(clippy::non_ascii_literal)] +pub fn generate_minibsod( + writer: &mut BufWriter, + signal: Signal, + _siginfo: &siginfo_t, + ucontext: Option<&ucontext_t>, +) -> Result<(), std::io::Error> { + writeln!(writer, "{:━^100}", " CRASH ")?; + if let Some(uctx) = ucontext { + write_crash(writer, signal, uctx)?; + + #[cfg(target_pointer_width = "64")] + { + writeln!(writer, "{:━^100}", " REGISTERS ")?; + dump_registers(writer, uctx)?; + } + } else { + writeln!(writer, "Received signal {signal}")?; + } + writeln!(writer, "{:━^100}", " BACKTRACE ")?; + writeln!(writer, "{:?}", backtrace::Backtrace::new())?; + writeln!(writer, "{:━^100}", " MAPS ")?; + write_minibsod(writer) +} + +/// Generates a mini-BSOD given a signal and context and dump it to a [`Vec`] +#[cfg(unix)] +pub fn generate_minibsod_to_vec( + signal: Signal, + siginfo: &siginfo_t, + ucontext: Option<&ucontext_t>, +) -> Result, std::io::Error> { + let mut bsod = Vec::new(); + { + let mut writer = BufWriter::new(&mut bsod); + + generate_minibsod(&mut writer, signal, siginfo, ucontext)?; + + writer.flush()?; + } + Ok(bsod) +} + +/// Generates a mini-BSOD given an `EXCEPTION_POINTERS` structure. +#[cfg(windows)] +#[expect(clippy::non_ascii_literal, clippy::not_unsafe_ptr_arg_deref)] +pub fn generate_minibsod( + writer: &mut BufWriter, + exception_pointers: *mut EXCEPTION_POINTERS, +) -> Result<(), std::io::Error> { + writeln!(writer, "{:━^100}", " CRASH ")?; + write_crash(writer, exception_pointers)?; + writeln!(writer, "{:━^100}", " REGISTERS ")?; + dump_registers(writer, unsafe { + (*exception_pointers).ContextRecord.as_mut().unwrap() + })?; + writeln!(writer, "{:━^100}", " BACKTRACE ")?; + writeln!(writer, "{:?}", backtrace::Backtrace::new())?; + writeln!(writer, "{:━^100}", " MAPS ")?; + write_minibsod(writer) +} + +#[cfg(unix)] +#[cfg(test)] +mod tests { + + use std::io::{BufWriter, stdout}; + + use crate::{minibsod::dump_registers, os::unix_signals::ucontext}; + + #[test] + #[cfg_attr(miri, ignore)] + fn test_dump_registers() { + let ucontext = ucontext().unwrap(); + let mut writer = BufWriter::new(stdout()); + dump_registers(&mut writer, &ucontext).unwrap(); + } +} + +#[cfg(windows)] +#[cfg(test)] +mod tests { + + use std::{ + io::{BufWriter, stdout}, + os::raw::c_void, + sync::mpsc, + }; + + use windows::Win32::{ + Foundation::{CloseHandle, DUPLICATE_SAME_ACCESS, DuplicateHandle, HANDLE}, + System::{ + Diagnostics::Debug::{ + CONTEXT, CONTEXT_FULL_AMD64, CONTEXT_FULL_ARM64, CONTEXT_FULL_X86, GetThreadContext, + }, + Threading::{GetCurrentProcess, GetCurrentThread, ResumeThread, SuspendThread}, + }, + }; + + use crate::minibsod::dump_registers; + + #[derive(Default)] + #[repr(align(16))] + struct Align16 { + pub ctx: CONTEXT, + } + + #[test] + #[cfg_attr(miri, ignore)] + fn test_dump_registers() { + let (tx, rx) = mpsc::channel(); + let (evt_tx, evt_rx) = mpsc::channel(); + let t = std::thread::spawn(move || { + let cur = unsafe { GetCurrentThread() }; + let proc = unsafe { GetCurrentProcess() }; + let mut out = HANDLE::default(); + unsafe { + DuplicateHandle( + proc, + cur, + proc, + &raw mut out, + 0, + true, + DUPLICATE_SAME_ACCESS, + ) + .unwrap(); + }; + tx.send(out.0 as i64).unwrap(); + evt_rx.recv().unwrap(); + }); + + let thread = rx.recv().unwrap(); + let thread = HANDLE(thread as *mut c_void); + eprintln!("thread: {thread:?}"); + unsafe { SuspendThread(thread) }; + + // https://stackoverflow.com/questions/56516445/getting-0x3e6-when-calling-getthreadcontext-for-debugged-thread + let mut c = Align16::default(); + if cfg!(target_arch = "x86") { + c.ctx.ContextFlags = CONTEXT_FULL_X86; + } else if cfg!(target_arch = "x86_64") { + c.ctx.ContextFlags = CONTEXT_FULL_AMD64; + } else if cfg!(target_arch = "aarch64") { + c.ctx.ContextFlags = CONTEXT_FULL_ARM64; + } + unsafe { GetThreadContext(thread, &raw mut (c.ctx)).unwrap() }; + + let mut writer = BufWriter::new(stdout()); + dump_registers(&mut writer, &c.ctx).unwrap(); + + unsafe { ResumeThread(thread) }; + unsafe { CloseHandle(thread).unwrap() }; + evt_tx.send(true).unwrap(); + t.join().unwrap(); + } +} diff --git a/crates/tuplelist_ex/Cargo.toml b/crates/no_std_time/Cargo.toml similarity index 79% rename from crates/tuplelist_ex/Cargo.toml rename to crates/no_std_time/Cargo.toml index 98362da0702..fdce58b6bd8 100644 --- a/crates/tuplelist_ex/Cargo.toml +++ b/crates/no_std_time/Cargo.toml @@ -1,11 +1,11 @@ [package] -name = "ownedref" +name = "no_std_time" version.workspace = true authors = [ "Andrea Fioraldi ", "Dominik Maier ", ] -description = "Library to pass around references that will be owned types on deserialization" +description = "Time measurments that work in no_std environments" documentation = "https://docs.rs/libafl" repository = "https://github.com/AFLplusplus/LibAFL/" readme = "./README.md" @@ -40,9 +40,6 @@ std = [ ## Enables all features that allocate in `no_std` alloc = [] -## Stores the backtraces of all generated `Error`s. Good for debugging, but may come with a slight performance hit. -errors_backtrace = ["backtrace"] - [build-dependencies] rustversion = { workspace = true } diff --git a/crates/no_std_time/LICENSE-APACHE b/crates/no_std_time/LICENSE-APACHE new file mode 120000 index 00000000000..965b606f331 --- /dev/null +++ b/crates/no_std_time/LICENSE-APACHE @@ -0,0 +1 @@ +../LICENSE-APACHE \ No newline at end of file diff --git a/crates/no_std_time/LICENSE-MIT b/crates/no_std_time/LICENSE-MIT new file mode 120000 index 00000000000..76219eb72e8 --- /dev/null +++ b/crates/no_std_time/LICENSE-MIT @@ -0,0 +1 @@ +../LICENSE-MIT \ No newline at end of file diff --git a/crates/tuplelist_ex/README.md b/crates/no_std_time/README.md similarity index 100% rename from crates/tuplelist_ex/README.md rename to crates/no_std_time/README.md diff --git a/crates/no_std_time/src/lib.rs b/crates/no_std_time/src/lib.rs new file mode 100644 index 00000000000..b16173c5b79 --- /dev/null +++ b/crates/no_std_time/src/lib.rs @@ -0,0 +1,137 @@ +//! Time functions that can be used on no_std +#![doc = include_str!("../../../README.md")] +/*! */ +#![cfg_attr(feature = "document-features", doc = document_features::document_features!())] +#![no_std] +#![cfg_attr(not(test), warn( + missing_debug_implementations, + missing_docs, + //trivial_casts, + trivial_numeric_casts, + unused_extern_crates, + unused_import_braces, + unused_qualifications, + //unused_results +))] +#![cfg_attr(test, deny( + missing_debug_implementations, + missing_docs, + //trivial_casts, + trivial_numeric_casts, + unused_extern_crates, + unused_import_braces, + unused_qualifications, + unused_must_use, + //unused_results +))] +#![cfg_attr( + test, + deny( + bad_style, + dead_code, + improper_ctypes, + non_shorthand_field_patterns, + no_mangle_generic_items, + overflowing_literals, + path_statements, + patterns_in_fns_without_body, + unconditional_recursion, + unused, + unused_allocation, + unused_comparisons, + unused_parens, + while_true + ) +)] + +#[cfg(feature = "std")] +#[macro_use] +extern crate std; +#[cfg(feature = "alloc")] +#[macro_use] +#[doc(hidden)] +pub extern crate alloc; + +pub mod time_counters; + +/// Format a `Duration` into a HMS string +#[cfg(feature = "alloc")] +#[must_use] +pub fn format_duration(duration: &time::Duration) -> String { + const MINS_PER_HOUR: u64 = 60; + const HOURS_PER_DAY: u64 = 24; + + const SECS_PER_MINUTE: u64 = 60; + const SECS_PER_HOUR: u64 = SECS_PER_MINUTE * MINS_PER_HOUR; + const SECS_PER_DAY: u64 = SECS_PER_HOUR * HOURS_PER_DAY; + + let total_secs = duration.as_secs(); + let secs = total_secs % SECS_PER_MINUTE; + + if total_secs < SECS_PER_MINUTE { + format!("{secs}s") + } else { + let mins = (total_secs / SECS_PER_MINUTE) % MINS_PER_HOUR; + if total_secs < SECS_PER_HOUR { + format!("{mins}m-{secs}s") + } else { + let hours = (total_secs / SECS_PER_HOUR) % HOURS_PER_DAY; + if total_secs < SECS_PER_DAY { + format!("{hours}h-{mins}m-{secs}s") + } else { + let days = total_secs / SECS_PER_DAY; + format!("{days}days {hours}h-{mins}m-{secs}s") + } + } + } +} + +#[cfg(all(any(doctest, test), not(feature = "std")))] +/// Provide custom time in `no_std` tests. +#[unsafe(no_mangle)] +pub unsafe extern "C" fn external_current_millis() -> u64 { + // TODO: use "real" time here + 1000 +} + +/// Current time +#[cfg(feature = "std")] +#[must_use] +#[inline] +pub fn current_time() -> time::Duration { + SystemTime::now().duration_since(UNIX_EPOCH).unwrap() +} + +// external defined function in case of `no_std` +// +// 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")))] +unsafe extern "C" { + //#[unsafe(no_mangle)] + fn external_current_millis() -> u64; +} + +/// Current time (fixed fallback for `no_std`) +#[cfg(not(feature = "std"))] +#[inline] +#[must_use] +pub fn current_time() -> time::Duration { + let millis = unsafe { external_current_millis() }; + time::Duration::from_millis(millis) +} + +/// Gets current nanoseconds since [`UNIX_EPOCH`] +#[must_use] +#[inline] +pub fn current_nanos() -> u64 { + current_time().as_nanos() as u64 +} + +/// Gets current milliseconds since [`UNIX_EPOCH`] +#[must_use] +#[inline] +pub fn current_milliseconds() -> u64 { + current_time().as_millis() as u64 +} + diff --git a/crates/libafl_bolts/src/cpu.rs b/crates/no_std_time/src/time_counters.rs similarity index 100% rename from crates/libafl_bolts/src/cpu.rs rename to crates/no_std_time/src/time_counters.rs diff --git a/crates/ownedref/Cargo.toml b/crates/ownedref/Cargo.toml index 98362da0702..f6b24456ce2 100644 --- a/crates/ownedref/Cargo.toml +++ b/crates/ownedref/Cargo.toml @@ -40,9 +40,6 @@ std = [ ## Enables all features that allocate in `no_std` alloc = [] -## Stores the backtraces of all generated `Error`s. Good for debugging, but may come with a slight performance hit. -errors_backtrace = ["backtrace"] - [build-dependencies] rustversion = { workspace = true } diff --git a/crates/ownedref/src/lib.rs b/crates/ownedref/src/lib.rs index b29cfa29462..e89f232c450 100644 --- a/crates/ownedref/src/lib.rs +++ b/crates/ownedref/src/lib.rs @@ -51,8 +51,6 @@ extern crate std; #[doc(hidden)] pub extern crate alloc; - - pub mod subrange; use alloc::{boxed::Box, vec::Vec}; diff --git a/crates/serde_anymap/Cargo.toml b/crates/serde_anymap/Cargo.toml index 98362da0702..39a38334269 100644 --- a/crates/serde_anymap/Cargo.toml +++ b/crates/serde_anymap/Cargo.toml @@ -1,11 +1,11 @@ [package] -name = "ownedref" +name = "serde_anymap" +description = "A map that can retrieve values by type - and is SerDe serializable" version.workspace = true authors = [ "Andrea Fioraldi ", "Dominik Maier ", ] -description = "Library to pass around references that will be owned types on deserialization" documentation = "https://docs.rs/libafl" repository = "https://github.com/AFLplusplus/LibAFL/" readme = "./README.md" @@ -40,9 +40,6 @@ std = [ ## Enables all features that allocate in `no_std` alloc = [] -## Stores the backtraces of all generated `Error`s. Good for debugging, but may come with a slight performance hit. -errors_backtrace = ["backtrace"] - [build-dependencies] rustversion = { workspace = true } diff --git a/crates/libafl_bolts/src/anymap.rs b/crates/serde_anymap/src/anymap.rs similarity index 100% rename from crates/libafl_bolts/src/anymap.rs rename to crates/serde_anymap/src/anymap.rs diff --git a/crates/serde_anymap/src/lib.rs b/crates/serde_anymap/src/lib.rs index e69de29bb2d..7dff1e6180f 100644 --- a/crates/serde_anymap/src/lib.rs +++ b/crates/serde_anymap/src/lib.rs @@ -0,0 +1,54 @@ +//! A map that can retrieve values by type - and is SerDe serializable. +#![doc = include_str!("../../../README.md")] +/*! */ +#![cfg_attr(feature = "document-features", doc = document_features::document_features!())] +#![no_std] +#![cfg_attr(not(test), warn( + missing_debug_implementations, + missing_docs, + //trivial_casts, + trivial_numeric_casts, + unused_extern_crates, + unused_import_braces, + unused_qualifications, + //unused_results +))] +#![cfg_attr(test, deny( + missing_debug_implementations, + missing_docs, + //trivial_casts, + trivial_numeric_casts, + unused_extern_crates, + unused_import_braces, + unused_qualifications, + unused_must_use, + //unused_results +))] +#![cfg_attr( + test, + deny( + bad_style, + dead_code, + improper_ctypes, + non_shorthand_field_patterns, + no_mangle_generic_items, + overflowing_literals, + path_statements, + patterns_in_fns_without_body, + unconditional_recursion, + unused, + unused_allocation, + unused_comparisons, + unused_parens, + while_true + ) +)] + +#[cfg(feature = "std")] +#[macro_use] +extern crate std; +#[doc(hidden)] +pub extern crate alloc; + +pub mod serdeany; +pub mod anymap; \ No newline at end of file diff --git a/crates/libafl_bolts/src/serdeany.rs b/crates/serde_anymap/src/serdeany.rs similarity index 100% rename from crates/libafl_bolts/src/serdeany.rs rename to crates/serde_anymap/src/serdeany.rs diff --git a/crates/signal_handler/src/lib.rs b/crates/signal_handler/src/lib.rs deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/crates/tuple_list_ex/Cargo.toml b/crates/tuple_list_ex/Cargo.toml new file mode 100644 index 00000000000..af2442efd47 --- /dev/null +++ b/crates/tuple_list_ex/Cargo.toml @@ -0,0 +1,53 @@ +[package] +name = "tuple_list_ex" +version.workspace = true +authors = [ + "Andrea Fioraldi ", + "Dominik Maier ", +] +description = "Useful Haskel-like extensions for the tuple_list crate" +documentation = "https://docs.rs/libafl" +repository = "https://github.com/AFLplusplus/LibAFL/" +readme = "./README.md" +license = "MIT OR Apache-2.0" +keywords = ["os", "no-std"] +edition = "2024" +rust-version = "1.87" +categories = [ + "embedded", + "os", + "no-std", +] + +[package.metadata.docs.rs] +features = ["document-features"] +all-features = true + +[features] +default = [ + "std", + "alloc", +] +document-features = ["dep:document-features"] + +#! # Feature Flags +#! ### General Features + +## Enables features that need rust's `std` lib to work, like print, env, ... support +std = [ +] + +## Enables all features that allocate in `no_std` +alloc = [] + +[build-dependencies] +rustversion = { workspace = true } + +[dev-dependencies] + +[dependencies] +# Document all features of this crate (for `cargo doc`) +document-features = { workspace = true, optional = true } + +[lints] +workspace = true diff --git a/crates/tuple_list_ex/LICENSE-APACHE b/crates/tuple_list_ex/LICENSE-APACHE new file mode 120000 index 00000000000..965b606f331 --- /dev/null +++ b/crates/tuple_list_ex/LICENSE-APACHE @@ -0,0 +1 @@ +../LICENSE-APACHE \ No newline at end of file diff --git a/crates/tuple_list_ex/LICENSE-MIT b/crates/tuple_list_ex/LICENSE-MIT new file mode 120000 index 00000000000..76219eb72e8 --- /dev/null +++ b/crates/tuple_list_ex/LICENSE-MIT @@ -0,0 +1 @@ +../LICENSE-MIT \ No newline at end of file diff --git a/crates/tuple_list_ex/README.md b/crates/tuple_list_ex/README.md new file mode 100644 index 00000000000..0a638ac1244 --- /dev/null +++ b/crates/tuple_list_ex/README.md @@ -0,0 +1,58 @@ +# LibAFL_bolts: OS and Fuzzer Dev's Libary Collection. + + LibAFL logo + +The `libafl_bolts` crate exposes a lot of low-level features of LibAFL for projects that are unrelated to fuzzing, or just fuzzers completely different to LibAFL. +Some cross-platform things in bolts include (but are not limited to): + +* SerdeAnyMap: a map that stores and retrieves elements by type and is serializable and deserializable +* ShMem: A cross-platform (Windows, Linux, Android, MacOS) shared memory implementation +* LLMP: A fast, lock-free IPC mechanism via SharedMap +* Core_affinity: A maintained version of `core_affinity` that can be used to get core information and bind processes to cores +* Rands: Fast random number generators for fuzzing (like [RomuRand](https://www.romu-random.org/)) +* MiniBSOD: get and print information about the current process state including important registers. +* Tuples: Haskel-like compile-time tuple lists +* Os: OS specific stuff like signal handling, windows exception handling, pipes, and helpers for `fork` + +LibAFL_bolts is written and maintained by + +* [Andrea Fioraldi](https://twitter.com/andreafioraldi) +* [Dominik Maier](https://twitter.com/domenuk) +* [s1341](https://twitter.com/srubenst1341) +* [Dongjia Zhang](https://github.com/tokatoka) +* [Addison Crump](https://github.com/addisoncrump) + +## Contributing + +For bugs, feel free to open issues or contact us directly. Thank you for your support. <3 + +Even though we will gladly assist you in finishing up your PR, try to +- keep all the crates compiling with *stable* rust (hide the eventual non-stable code under [`cfg`s](https://github.com/AFLplusplus/LibAFL/blob/main/libafl/build.rs#L26)) +- run `cargo nightly fmt` on your code before pushing +- check the output of `cargo clippy --all` or `./clippy.sh` +- run `cargo build --no-default-features` to check for `no_std` compatibility (and possibly add `#[cfg(feature = "std")]`) to hide parts of your code. + +Some of the parts in this list may be hard, don't be afraid to open a PR if you cannot fix them by yourself, so we can help. + +#### License + + +Licensed under either of Apache License, Version +2.0 or MIT license at your option. + + +
+ + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in this crate by you, as defined in the Apache-2.0 license, shall +be dual licensed as above, without any additional terms or conditions. + + +
+ + +Dependencies under more restrictive licenses, such as GPL or AGPL, can be enabled +using the respective feature in each crate when it is present, such as the +'agpl' feature of the libafl crate. + diff --git a/crates/libafl_bolts/src/tuples.rs b/crates/tuple_list_ex/src/lib.rs similarity index 95% rename from crates/libafl_bolts/src/tuples.rs rename to crates/tuple_list_ex/src/lib.rs index 6ce73ccc115..18fc066187c 100644 --- a/crates/libafl_bolts/src/tuples.rs +++ b/crates/tuple_list_ex/src/lib.rs @@ -1,4 +1,56 @@ //! Compiletime lists/tuples used throughout the `LibAFL` universe +#![doc = include_str!("../../../README.md")] +/*! */ +#![cfg_attr(feature = "document-features", doc = document_features::document_features!())] +#![no_std] +#![cfg_attr(not(test), warn( + missing_debug_implementations, + missing_docs, + //trivial_casts, + trivial_numeric_casts, + unused_extern_crates, + unused_import_braces, + unused_qualifications, + //unused_results +))] +#![cfg_attr(test, deny( + missing_debug_implementations, + missing_docs, + //trivial_casts, + trivial_numeric_casts, + unused_extern_crates, + unused_import_braces, + unused_qualifications, + unused_must_use, + //unused_results +))] +#![cfg_attr( + test, + deny( + bad_style, + dead_code, + improper_ctypes, + non_shorthand_field_patterns, + no_mangle_generic_items, + overflowing_literals, + path_statements, + patterns_in_fns_without_body, + unconditional_recursion, + unused, + unused_allocation, + unused_comparisons, + unused_parens, + while_true + ) +)] + +#[cfg(feature = "std")] +#[macro_use] +extern crate std; +#[cfg(feature = "alloc")] +#[macro_use] +#[doc(hidden)] +pub extern crate alloc; #[cfg(feature = "alloc")] use alloc::{borrow::Cow, vec::Vec}; diff --git a/crates/tuplelist_ex/src/lib.rs b/crates/tuplelist_ex/src/lib.rs deleted file mode 100644 index e69de29bb2d..00000000000 From 329182d6a104473991428be3cbb467bcd4a87bd1 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Fri, 11 Jul 2025 13:44:53 +0200 Subject: [PATCH 03/18] More more --- Cargo.toml | 2 ++ crates/build_id2/Cargo.toml | 7 ++--- crates/core_affinity2/Cargo.toml | 14 +++------- crates/exceptional/Cargo.toml | 26 ++++++++++--------- crates/exceptional/src/lib.rs | 2 -- crates/exceptional/src/unix_signals.rs | 5 ++-- crates/fast_rands/Cargo.toml | 13 +++------- crates/fast_rands/src/loaded_dice.rs | 4 +-- crates/libafl/Cargo.toml | 4 +-- crates/libafl_bolts/Cargo.toml | 3 +-- crates/libafl_bolts/src/lib.rs | 13 ---------- crates/libafl_bolts/src/math.rs | 4 ++- crates/libafl_bolts/src/os.rs | 2 ++ crates/libafl_core/Cargo.toml | 4 +++ crates/libafl_core/src/lib.rs | 17 +++++++++++- crates/ll_mp/Cargo.toml | 36 ++++++++++++++------------ crates/ll_mp/src/lib.rs | 25 +++++++++--------- crates/minibsod/Cargo.toml | 14 +++------- crates/no_std_time/Cargo.toml | 14 +++------- crates/no_std_time/src/lib.rs | 2 ++ crates/ownedref/Cargo.toml | 14 +++------- crates/serde_anymap/Cargo.toml | 14 +++------- crates/shmem_providers/src/lib.rs | 3 +++ crates/tuple_list_ex/Cargo.toml | 14 +++------- 24 files changed, 108 insertions(+), 148 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index dd0274a9ab2..22460fa96b0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -76,6 +76,7 @@ readme = "./README.md" [workspace.dependencies] # Internal deps +exceptional = { path = "./crates/exceptional", version = "0.15.3", default-features = false } fast_rands = { path = "./crates/fast_rands", version = "0.15.3", default-features = false } libafl = { path = "./crates/libafl", version = "0.15.3", default-features = false } libafl_bolts = { path = "./crates/libafl_bolts", version = "0.15.3", default-features = false } @@ -95,6 +96,7 @@ libafl_qemu_build = { path = "./crates/libafl_qemu/libafl_qemu_build", version = libafl_qemu_sys = { path = "./crates/libafl_qemu/libafl_qemu_sys", version = "0.15.3", default-features = false } libafl_sugar = { path = "./crates/libafl_sugar", version = "0.15.3", default-features = false } ll_mp = { path = "./crates/ll_mp", version = "0.15.3", default-features = false } +no_std_time = { path = "./crates/no_std_time", version = "0.15.3", default-features = false } shmem_providers = { path = "./crates/shmem_providers", version = "0.15.3", default-features = false } dump_constraints = { path = "./crates/libafl_concolic/test/dump_constraints", version = "0.15.2", default-features = false } runtime_test = { path = "./crates/libafl_concolic/test/runtime_test", version = "0.15.2", default-features = false } diff --git a/crates/build_id2/Cargo.toml b/crates/build_id2/Cargo.toml index 9e9526fcf7d..5acfa2c2582 100644 --- a/crates/build_id2/Cargo.toml +++ b/crates/build_id2/Cargo.toml @@ -13,17 +13,14 @@ license = "MIT OR Apache-2.0" keywords = ["os", "build-id"] edition = "2024" rust-version = "1.87" -categories = [ - "os", -] +categories = ["os"] [package.metadata.docs.rs] features = ["document-features"] all-features = true [features] -default = [ -] +default = [] [build-dependencies] rustversion = { workspace = true } diff --git a/crates/core_affinity2/Cargo.toml b/crates/core_affinity2/Cargo.toml index 9d9fff5c447..02a09161855 100644 --- a/crates/core_affinity2/Cargo.toml +++ b/crates/core_affinity2/Cargo.toml @@ -13,29 +13,21 @@ license = "MIT OR Apache-2.0" keywords = ["os", "core-affinity", "no-std"] edition = "2024" rust-version = "1.87" -categories = [ - "embedded", - "os", - "no-std", -] +categories = ["embedded", "os", "no-std"] [package.metadata.docs.rs] features = ["document-features"] all-features = true [features] -default = [ - "std", -] +default = ["std"] document-features = ["dep:document-features"] #! # Feature Flags #! ### General Features ## Enables features that need rust's `std` lib to work, like print, env, ... support -std = [ - "libafl_core/std" -] +std = ["libafl_core/std"] [build-dependencies] rustversion = { workspace = true } diff --git a/crates/exceptional/Cargo.toml b/crates/exceptional/Cargo.toml index 14a2aa67834..74ff78b3b20 100644 --- a/crates/exceptional/Cargo.toml +++ b/crates/exceptional/Cargo.toml @@ -13,32 +13,24 @@ license = "MIT OR Apache-2.0" keywords = ["os", "shmem", "no-std"] edition = "2024" rust-version = "1.87" -categories = [ - "embedded", - "os", - "no-std", -] +categories = ["embedded", "os", "no-std"] [package.metadata.docs.rs] features = ["document-features"] all-features = true [features] -default = [ - "std", - "alloc", -] +default = ["std", "alloc"] document-features = ["dep:document-features"] #! # Feature Flags #! ### General Features ## Enables features that need rust's `std` lib to work, like print, env, ... support -std = [ -] +std = ["nix", "libafl_core/std"] ## Enables all features that allocate in `no_std` -alloc = [] +alloc = ["libafl_core/alloc"] [build-dependencies] rustversion = { workspace = true } @@ -48,6 +40,16 @@ rustversion = { workspace = true } [dependencies] # Document all features of this crate (for `cargo doc`) document-features = { workspace = true, optional = true } +libafl_core = { workspace = true } +nix = { workspace = true, optional = true, default-features = false, features = [ + "fs", + "signal", + "socket", + "poll", +] } +num_enum = { workspace = true, default-features = false } +[target.'cfg(unix)'.dependencies] +libc = { workspace = true } [lints] workspace = true diff --git a/crates/exceptional/src/lib.rs b/crates/exceptional/src/lib.rs index 8e07f958e30..5f3cfb2933d 100644 --- a/crates/exceptional/src/lib.rs +++ b/crates/exceptional/src/lib.rs @@ -50,7 +50,6 @@ #[macro_use] extern crate std; #[cfg(feature = "alloc")] -#[macro_use] #[doc(hidden)] pub extern crate alloc; @@ -62,4 +61,3 @@ pub mod windows_exceptions; #[cfg(unix)] pub use unix_signals::CTRL_C_EXIT; - diff --git a/crates/exceptional/src/unix_signals.rs b/crates/exceptional/src/unix_signals.rs index a2ed3ee2ba4..ad240b993d1 100644 --- a/crates/exceptional/src/unix_signals.rs +++ b/crates/exceptional/src/unix_signals.rs @@ -16,6 +16,8 @@ use core::{ mem, }; +use libafl_core::format; + /// armv7 `libc` does not feature a `uncontext_t` implementation #[cfg(target_arch = "arm")] pub use libc::c_ulong; @@ -246,6 +248,7 @@ pub struct ucontext_t { pub mcontext_data: mcontext64, } +use libafl_core::Error; #[cfg(all(target_vendor = "apple", target_arch = "aarch64"))] use libc::ssize_t; #[cfg(not(any( @@ -265,8 +268,6 @@ use libc::{ pub use libc::{c_void, siginfo_t}; use num_enum::{IntoPrimitive, TryFromPrimitive}; -use crate::Error; - unsafe extern "C" { /// The `libc` `getcontext` /// For some reason, it's not available on `MacOS`. diff --git a/crates/fast_rands/Cargo.toml b/crates/fast_rands/Cargo.toml index d4f1ae5e32b..36abc98cae0 100644 --- a/crates/fast_rands/Cargo.toml +++ b/crates/fast_rands/Cargo.toml @@ -13,21 +13,14 @@ license = "MIT OR Apache-2.0" keywords = ["os", "shmem", "no-std"] edition = "2024" rust-version = "1.87" -categories = [ - "embedded", - "os", - "no-std", -] +categories = ["embedded", "os", "no-std"] [package.metadata.docs.rs] features = ["document-features"] all-features = true [features] -default = [ - "std", - "alloc", -] +default = ["std", "alloc"] document-features = ["dep:document-features"] #! # Feature Flags @@ -57,7 +50,7 @@ serde = { workspace = true, default-features = false, features = [ ] } # serialization lib # Document all features of this crate (for `cargo doc`) document-features = { workspace = true, optional = true } -rand_core ={ version = "0.9.0", optional = true } +rand_core = { version = "0.9.0", optional = true } pyo3 = { workspace = true, optional = true, features = ["serde", "macros"] } [lints] diff --git a/crates/fast_rands/src/loaded_dice.rs b/crates/fast_rands/src/loaded_dice.rs index 75660f88549..713fa43fe20 100644 --- a/crates/fast_rands/src/loaded_dice.rs +++ b/crates/fast_rands/src/loaded_dice.rs @@ -7,8 +7,8 @@ A simple module that implements a random sampler implementing the [alias method] Assume we want to sample from the following distribution: `p(0)=0.5, p(1)=0.3, p(2)=0.1, p(3)=0.1`: ```rust -# extern crate libafl_rand; -use libafl_rand::{StdRand, loaded_dice::LoadedDiceSampler}; +# extern crate fast_rands; +use fast_rands::{StdRand, loaded_dice::LoadedDiceSampler}; fn main() { let mut rand = StdRand::new(); let mut sampler = LoadedDiceSampler::new(&[0.5, 0.3, 0.1, 0.1]).unwrap(); diff --git a/crates/libafl/Cargo.toml b/crates/libafl/Cargo.toml index c89d8b66f95..19206be9b16 100644 --- a/crates/libafl/Cargo.toml +++ b/crates/libafl/Cargo.toml @@ -186,9 +186,7 @@ llmp_compression = ["ll_mp/llmp_compression"] llmp_debug = ["std", "ll_mp/llmp_debug"] ## Reduces the initial map size for llmp -llmp_small_maps = [ - "ll_mp/llmp_small_maps", -] # reduces initial map size for llmp +llmp_small_maps = ["ll_mp/llmp_small_maps"] # reduces initial map size for llmp ## Grammar mutator. nautilus = ["std", "serde_json/std", "rand_trait", "regex-syntax", "regex"] diff --git a/crates/libafl_bolts/Cargo.toml b/crates/libafl_bolts/Cargo.toml index 2197a22829b..653c42a2391 100644 --- a/crates/libafl_bolts/Cargo.toml +++ b/crates/libafl_bolts/Cargo.toml @@ -125,7 +125,7 @@ chrono = "0.4.40" itertools = "0.14.0" [dependencies] -libafl_core = { workspace = true, features=["postcard"] } +libafl_core = { workspace = true, features = ["postcard"] } libafl_derive = { workspace = true, default-features = true, optional = true } static_assertions = { workspace = true } typeid = { workspace = true } @@ -226,4 +226,3 @@ required-features = ["std", "simd"] [lints] workspace = true - diff --git a/crates/libafl_bolts/src/lib.rs b/crates/libafl_bolts/src/lib.rs index 296e268a1fc..ac26acb121d 100644 --- a/crates/libafl_bolts/src/lib.rs +++ b/crates/libafl_bolts/src/lib.rs @@ -70,7 +70,6 @@ pub mod cli; pub mod compress; #[cfg(feature = "std")] pub mod core_affinity; -pub mod cpu; #[cfg(feature = "std")] pub mod fs; #[cfg(feature = "alloc")] @@ -156,29 +155,17 @@ use std::{ // TODO: re-enable once is resolved. #[cfg(all(not(feature = "xxh3"), feature = "alloc"))] use ahash::RandomState; -use serde::{Deserialize, Serialize}; #[cfg(feature = "xxh3")] use xxhash_rust::xxh3::xxh3_64; -/// The client ID == the sender id. -#[repr(transparent)] -#[derive( - Debug, Default, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize, -)] -pub struct ClientId(pub u32); - #[cfg(feature = "alloc")] use alloc::string::String; -use core::time; #[cfg(feature = "libafl_derive")] pub use libafl_derive::SerdeAny; #[cfg(feature = "std")] use log::{Metadata, Record}; -/// Localhost addr, this is used, for example, for LLMP Client, which connects to this address -pub const IP_LOCALHOST: &str = "127.0.0.1"; - /// Returns the standard input [`Hasher`] /// /// Returns the hasher for the input with a given hash, depending on features: diff --git a/crates/libafl_bolts/src/math.rs b/crates/libafl_bolts/src/math.rs index f9ac732a132..d4b879c3c4d 100644 --- a/crates/libafl_bolts/src/math.rs +++ b/crates/libafl_bolts/src/math.rs @@ -2,7 +2,9 @@ use core::ops::AddAssign; -use crate::Error; +use libafl_core::Error; + +use libafl_core::format; /// Returns the cumulative distribution function for a discrete distribution. pub fn calculate_cumulative_distribution_in_place(probabilities: &mut [f32]) -> Result<(), Error> { diff --git a/crates/libafl_bolts/src/os.rs b/crates/libafl_bolts/src/os.rs index c2aedf97640..a35f77cb6a9 100644 --- a/crates/libafl_bolts/src/os.rs +++ b/crates/libafl_bolts/src/os.rs @@ -18,6 +18,8 @@ use std::{ sync::OnceLock, }; +use libafl_core::format; + // Allow a few extra features we need for the whole module #[cfg(unix)] use libc::pid_t; diff --git a/crates/libafl_core/Cargo.toml b/crates/libafl_core/Cargo.toml index ceb7f0e93a2..44e45049052 100644 --- a/crates/libafl_core/Cargo.toml +++ b/crates/libafl_core/Cargo.toml @@ -43,6 +43,9 @@ nix = ["dep:nix"] ## Enables postcard error conversion postcard = ["dep:postcard"] +## Enables Serde support for some types +serde = ["dep:serde", "alloc"] + [build-dependencies] rustversion = { workspace = true } @@ -54,6 +57,7 @@ backtrace = { workspace = true, default-features = true, optional = true } postcard = { workspace = true, optional = true } nix = { workspace = true, optional = true } pyo3 = { workspace = true, optional = true } +serde = { workspace = true, features = ["derive", "alloc"], optional = true } [lints] workspace = true diff --git a/crates/libafl_core/src/lib.rs b/crates/libafl_core/src/lib.rs index 4867e3a8c5b..4852a6164a7 100644 --- a/crates/libafl_core/src/lib.rs +++ b/crates/libafl_core/src/lib.rs @@ -56,16 +56,19 @@ type String = &'static str; /// Problem is that we really need a non-allocating format... /// This one simply returns the `fmt` string. /// Good enough for simple errors, for anything else, use the `alloc` feature. +#[macro_export] #[cfg(not(feature = "alloc"))] macro_rules! format { ($fmt:literal) => {{ $fmt }}; } +/// Re-export of the "format" macro +#[cfg(feature = "alloc")] +pub use alloc::format; #[cfg(feature = "std")] #[macro_use] extern crate std; #[cfg(feature = "alloc")] -#[macro_use] #[doc(hidden)] pub extern crate alloc; @@ -87,7 +90,19 @@ use { core::str::Utf8Error, }; +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; +/// Localhost addr, this is used, for example, for LLMP Client, which connects to this address +pub const IP_LOCALHOST: &str = "127.0.0.1"; + +/// The client ID for various use cases across LibAFL +#[repr(transparent)] +#[derive( + Debug, Default, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord +)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub struct ClientId(pub u32); #[cfg(feature = "errors_backtrace")] /// Error Backtrace type when `errors_backtrace` feature is enabled (== [`backtrace::Backtrace`]) diff --git a/crates/ll_mp/Cargo.toml b/crates/ll_mp/Cargo.toml index 70e57ecfb4c..651a5291060 100644 --- a/crates/ll_mp/Cargo.toml +++ b/crates/ll_mp/Cargo.toml @@ -13,34 +13,31 @@ license = "MIT OR Apache-2.0" keywords = ["os", "ipc", "no-std"] edition = "2024" rust-version = "1.87" -categories = [ - "os", - "no-std", -] +categories = ["os", "no-std"] [package.metadata.docs.rs] features = ["document-features"] all-features = true [features] -default = [ - "std", - "alloc", - "gzip", - "llmp_compression", - "llmp_small_maps", -] +default = ["std", "alloc", "gzip", "llmp_compression", "llmp_small_maps"] document-features = ["dep:document-features"] #! # Feature Flags #! ### General Features ## Enables features that need rust's `std` lib to work, like print, env, ... support -std = [ -] +std = ["libafl_core/std", "shmem_providers/std"] ## Enables all features that allocate in `no_std` -alloc = [] +alloc = [ + "hostname", + "postcard", + "libafl_core/alloc", + "libafl_core/serde", + "exceptional/alloc", + "shmem_providers/alloc", +] ## Enables gzip compression in certain parts of the lib gzip = ["miniz_oxide", "alloc"] @@ -69,12 +66,17 @@ rustversion = { workspace = true } # Document all features of this crate (for `cargo doc`) document-features = { workspace = true, optional = true } miniz_oxide = { version = "0.8.0", optional = true } -hostname = { version = "0.4.0", optional = true } # Is there really no gethostname in the stdlib? -postcard = { workspace = true, optional = true } # no_std compatible serde serialization format +hostname = { version = "0.4.0", optional = true } # Is there really no gethostname in the stdlib? +postcard = { workspace = true, optional = true } # no_std compatible serde serialization format log = { workspace = true } tuple_list = { version = "0.1.3" } -libafl_bolts = { workspace = true } +libafl_core = { workspace = true } +nix = { workspace = true, features = ["socket"] } +no_std_time = { workspace = true } +serde = { workspace = true, features = ["alloc", "derive"] } shmem_providers = { workspace = true } +exceptional = { workspace = true } +serial_test = { workspace = true } [[example]] name = "llmp_test" diff --git a/crates/ll_mp/src/lib.rs b/crates/ll_mp/src/lib.rs index 21361fd5608..c9324d642a8 100644 --- a/crates/ll_mp/src/lib.rs +++ b/crates/ll_mp/src/lib.rs @@ -140,24 +140,25 @@ use std::{ #[cfg(all(debug_assertions, feature = "llmp_debug", feature = "std"))] use backtrace::Backtrace; -use libafl_bolts::{ClientId, Error}; +#[cfg(all(unix, not(miri)))] +use exceptional::unix_signals::setup_signal_handler; +#[cfg(unix)] +use exceptional::unix_signals::{Signal, SignalHandler, siginfo_t, ucontext_t}; +#[cfg(all(windows, feature = "std"))] +use exceptional::windows_exceptions::{CtrlHandler, setup_ctrl_handler}; #[cfg(feature = "std")] -use libafl_bolts::{IP_LOCALHOST, current_time}; +use libafl_core::IP_LOCALHOST; +use libafl_core::{ClientId, Error}; #[cfg(all(unix, feature = "std"))] #[cfg(not(any(target_os = "solaris", target_os = "illumos")))] use nix::sys::socket::{self, sockopt::ReusePort}; +#[cfg(feature = "std")] +use no_std_time::current_time; use serde::{Deserialize, Serialize}; use shmem_providers::{ShMem, ShMemDescription, ShMemId, ShMemProvider}; #[cfg(feature = "std")] 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::{Signal, SignalHandler, siginfo_t, ucontext_t}; -#[cfg(all(windows, feature = "std"))] -use crate::os::windows_exceptions::{CtrlHandler, setup_ctrl_handler}; - /// 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. /// Instead of increasing this value, you may consider sending new messages at a lower rate, else your Sender will eventually `OOM`. @@ -2485,7 +2486,7 @@ impl Brokers { /// 5 millis of sleep can't hurt to keep busywait not at 100% #[cfg(feature = "std")] pub fn loop_with_timeouts(&mut self, timeout: Duration, sleep_time: Option) { - use super::current_milliseconds; + use no_std_time::current_milliseconds; #[cfg(any(all(unix, not(miri)), all(windows, feature = "std")))] Self::setup_handlers(); @@ -2661,7 +2662,7 @@ where /// 5 millis of sleep can't hurt to keep busywait not at 100% #[cfg(feature = "std")] pub fn loop_with_timeouts(&mut self, timeout: Duration, sleep_time: Option) { - use super::current_milliseconds; + use no_std_time::current_milliseconds; #[cfg(any(all(unix, not(miri)), all(windows, feature = "std")))] Self::setup_handlers(); @@ -3922,13 +3923,13 @@ mod tests { use std::thread::sleep; use serial_test::serial; + use shmem_providers::{ShMemProvider, StdShMemProvider}; use super::{ LlmpClient, LlmpConnection::{self, IsBroker, IsClient}, Tag, }; - use crate::shmem::{ShMemProvider, StdShMemProvider}; #[test] #[serial] diff --git a/crates/minibsod/Cargo.toml b/crates/minibsod/Cargo.toml index d9a1b3a007e..231b9ae11aa 100644 --- a/crates/minibsod/Cargo.toml +++ b/crates/minibsod/Cargo.toml @@ -13,29 +13,21 @@ license = "MIT OR Apache-2.0" keywords = ["os", "shmem", "no-std"] edition = "2024" rust-version = "1.87" -categories = [ - "embedded", - "os", - "no-std", -] +categories = ["embedded", "os", "no-std"] [package.metadata.docs.rs] features = ["document-features"] all-features = true [features] -default = [ - "std", - "alloc", -] +default = ["std", "alloc"] document-features = ["dep:document-features"] #! # Feature Flags #! ### General Features ## Enables features that need rust's `std` lib to work, like print, env, ... support -std = [ -] +std = [] ## Enables all features that allocate in `no_std` alloc = [] diff --git a/crates/no_std_time/Cargo.toml b/crates/no_std_time/Cargo.toml index fdce58b6bd8..605680c0b14 100644 --- a/crates/no_std_time/Cargo.toml +++ b/crates/no_std_time/Cargo.toml @@ -13,29 +13,21 @@ license = "MIT OR Apache-2.0" keywords = ["os", "shmem", "no-std"] edition = "2024" rust-version = "1.87" -categories = [ - "embedded", - "os", - "no-std", -] +categories = ["embedded", "os", "no-std"] [package.metadata.docs.rs] features = ["document-features"] all-features = true [features] -default = [ - "std", - "alloc", -] +default = ["std", "alloc"] document-features = ["dep:document-features"] #! # Feature Flags #! ### General Features ## Enables features that need rust's `std` lib to work, like print, env, ... support -std = [ -] +std = [] ## Enables all features that allocate in `no_std` alloc = [] diff --git a/crates/no_std_time/src/lib.rs b/crates/no_std_time/src/lib.rs index b16173c5b79..086564ac05e 100644 --- a/crates/no_std_time/src/lib.rs +++ b/crates/no_std_time/src/lib.rs @@ -52,6 +52,8 @@ extern crate std; #[doc(hidden)] pub extern crate alloc; +use core::time; + pub mod time_counters; /// Format a `Duration` into a HMS string diff --git a/crates/ownedref/Cargo.toml b/crates/ownedref/Cargo.toml index f6b24456ce2..33ef0a54df4 100644 --- a/crates/ownedref/Cargo.toml +++ b/crates/ownedref/Cargo.toml @@ -13,29 +13,21 @@ license = "MIT OR Apache-2.0" keywords = ["os", "shmem", "no-std"] edition = "2024" rust-version = "1.87" -categories = [ - "embedded", - "os", - "no-std", -] +categories = ["embedded", "os", "no-std"] [package.metadata.docs.rs] features = ["document-features"] all-features = true [features] -default = [ - "std", - "alloc", -] +default = ["std", "alloc"] document-features = ["dep:document-features"] #! # Feature Flags #! ### General Features ## Enables features that need rust's `std` lib to work, like print, env, ... support -std = [ -] +std = [] ## Enables all features that allocate in `no_std` alloc = [] diff --git a/crates/serde_anymap/Cargo.toml b/crates/serde_anymap/Cargo.toml index 39a38334269..ce110337d86 100644 --- a/crates/serde_anymap/Cargo.toml +++ b/crates/serde_anymap/Cargo.toml @@ -13,29 +13,21 @@ license = "MIT OR Apache-2.0" keywords = ["os", "shmem", "no-std"] edition = "2024" rust-version = "1.87" -categories = [ - "embedded", - "os", - "no-std", -] +categories = ["embedded", "os", "no-std"] [package.metadata.docs.rs] features = ["document-features"] all-features = true [features] -default = [ - "std", - "alloc", -] +default = ["std", "alloc"] document-features = ["dep:document-features"] #! # Feature Flags #! ### General Features ## Enables features that need rust's `std` lib to work, like print, env, ... support -std = [ -] +std = [] ## Enables all features that allocate in `no_std` alloc = [] diff --git a/crates/shmem_providers/src/lib.rs b/crates/shmem_providers/src/lib.rs index 6cc718de9bc..b036f8c2f77 100644 --- a/crates/shmem_providers/src/lib.rs +++ b/crates/shmem_providers/src/lib.rs @@ -51,6 +51,9 @@ extern crate std; #[doc(hidden)] pub extern crate alloc; +#[cfg(feature = "alloc")] +use alloc::vec; + pub use libafl_core::Error; #[cfg(all(unix, feature = "std"))] diff --git a/crates/tuple_list_ex/Cargo.toml b/crates/tuple_list_ex/Cargo.toml index af2442efd47..fa19442c1e3 100644 --- a/crates/tuple_list_ex/Cargo.toml +++ b/crates/tuple_list_ex/Cargo.toml @@ -13,29 +13,21 @@ license = "MIT OR Apache-2.0" keywords = ["os", "no-std"] edition = "2024" rust-version = "1.87" -categories = [ - "embedded", - "os", - "no-std", -] +categories = ["embedded", "os", "no-std"] [package.metadata.docs.rs] features = ["document-features"] all-features = true [features] -default = [ - "std", - "alloc", -] +default = ["std", "alloc"] document-features = ["dep:document-features"] #! # Feature Flags #! ### General Features ## Enables features that need rust's `std` lib to work, like print, env, ... support -std = [ -] +std = [] ## Enables all features that allocate in `no_std` alloc = [] From 936c286abe353aedf2bb7d0821be42f19ae04263 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sat, 12 Jul 2025 01:46:15 +0200 Subject: [PATCH 04/18] mas --- crates/exceptional/src/unix_signals.rs | 1 - crates/libafl_core/src/lib.rs | 10 +++----- crates/ll_mp/examples/llmp_test/main.rs | 31 +++++++++++-------------- crates/minibsod/Cargo.toml | 1 + crates/minibsod/src/lib.rs | 5 ++-- crates/no_std_time/src/lib.rs | 6 ++++- crates/serde_anymap/src/lib.rs | 2 +- 7 files changed, 26 insertions(+), 30 deletions(-) diff --git a/crates/exceptional/src/unix_signals.rs b/crates/exceptional/src/unix_signals.rs index ad240b993d1..855f8471afb 100644 --- a/crates/exceptional/src/unix_signals.rs +++ b/crates/exceptional/src/unix_signals.rs @@ -17,7 +17,6 @@ use core::{ }; use libafl_core::format; - /// armv7 `libc` does not feature a `uncontext_t` implementation #[cfg(target_arch = "arm")] pub use libc::c_ulong; diff --git a/crates/libafl_core/src/lib.rs b/crates/libafl_core/src/lib.rs index 4852a6164a7..38a18e79d90 100644 --- a/crates/libafl_core/src/lib.rs +++ b/crates/libafl_core/src/lib.rs @@ -83,6 +83,8 @@ use core::{ #[cfg(feature = "std")] use std::{env::VarError, io}; +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; #[cfg(feature = "alloc")] use { alloc::string::{FromUtf8Error, String}, @@ -90,17 +92,12 @@ use { core::str::Utf8Error, }; -#[cfg(feature = "serde")] -use serde::{Deserialize, Serialize}; - /// Localhost addr, this is used, for example, for LLMP Client, which connects to this address pub const IP_LOCALHOST: &str = "127.0.0.1"; /// The client ID for various use cases across LibAFL #[repr(transparent)] -#[derive( - Debug, Default, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord -)] +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct ClientId(pub u32); @@ -674,7 +671,6 @@ where } } - /// Has a ref count pub trait HasRefCnt { /// The ref count diff --git a/crates/ll_mp/examples/llmp_test/main.rs b/crates/ll_mp/examples/llmp_test/main.rs index 2ac4d09413b..8cdf3e3aaf2 100644 --- a/crates/ll_mp/examples/llmp_test/main.rs +++ b/crates/ll_mp/examples/llmp_test/main.rs @@ -11,13 +11,13 @@ use core::time::Duration; #[cfg(all(feature = "std", not(target_os = "haiku")))] use std::{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}, -}; +use libafl_core::{ClientId, Error}; +#[cfg(all(feature = "std", not(target_os = "haiku")))] +use ll_mp::{self, Flags, LlmpHook, Tag}; +use ll_mp::{LlmpBrokerInner, LlmpMsgHookResult}; +#[cfg(all(feature = "std", not(target_os = "haiku")))] +use shmem_providers::{ShMemProvider, StdShMemProvider}; use tuple_list::tuple_list; #[cfg(all(feature = "std", not(target_os = "haiku")))] @@ -35,13 +35,10 @@ const BROKER_TIMEOUT: Duration = Duration::from_secs(10); #[cfg(all(feature = "std", not(target_os = "haiku")))] const SLEEP_BETWEEN_FORWARDS: Duration = Duration::from_millis(5); -#[cfg(all(feature = "std", not(target_os = "haiku")))] -static LOGGER: SimpleStderrLogger = SimpleStderrLogger::new(); - #[cfg(all(feature = "std", not(target_os = "haiku")))] fn adder_loop(port: u16) -> Result<(), Box> { let shmem_provider = StdShMemProvider::new()?; - let mut client = llmp::LlmpClient::create_attach_to_tcp(shmem_provider, port)?; + let mut client = ll_mp::LlmpClient::create_attach_to_tcp(shmem_provider, port)?; let mut last_result: u32 = 0; let mut current_result: u32 = 0; loop { @@ -78,7 +75,7 @@ fn adder_loop(port: u16) -> Result<(), Box> { #[cfg(all(feature = "std", not(target_os = "haiku")))] fn large_msg_loop(port: u16) -> Result<(), Box> { - let mut client = llmp::LlmpClient::create_attach_to_tcp(StdShMemProvider::new()?, port)?; + let mut client = ll_mp::LlmpClient::create_attach_to_tcp(StdShMemProvider::new()?, port)?; #[cfg(not(target_vendor = "apple"))] let meg_buf = vec![1u8; 1 << 20]; @@ -170,7 +167,7 @@ fn main() { fn main() -> Result<(), Box> { /* The main node has a broker, and a few worker threads */ - use libafl_bolts::llmp::Broker; + use ll_mp::Broker; let mode = std::env::args() .nth(1) @@ -185,13 +182,13 @@ fn main() -> Result<(), Box> { .unwrap_or_else(|| "4242".into()) .parse::()?; - log::set_logger(&LOGGER).unwrap(); + // log::set_logger(..) log::set_max_level(log::LevelFilter::Trace); println!("Launching in mode {mode} on port {port}"); match mode.as_str() { "broker" => { - let mut broker = llmp::LlmpBroker::new( + let mut broker = ll_mp::LlmpBroker::new( StdShMemProvider::new()?, tuple_list!(LlmpExampleHook::new()), )?; @@ -201,7 +198,7 @@ fn main() -> Result<(), Box> { broker.loop_with_timeouts(BROKER_TIMEOUT, Some(SLEEP_BETWEEN_FORWARDS)); } "b2b" => { - let mut broker = llmp::LlmpBroker::new( + let mut broker = ll_mp::LlmpBroker::new( StdShMemProvider::new()?, tuple_list!(LlmpExampleHook::new()), )?; @@ -212,7 +209,7 @@ fn main() -> Result<(), Box> { } "ctr" => { let mut client = - llmp::LlmpClient::create_attach_to_tcp(StdShMemProvider::new()?, port)?; + ll_mp::LlmpClient::create_attach_to_tcp(StdShMemProvider::new()?, port)?; let mut counter: u32 = 0; loop { counter = counter.wrapping_add(1); @@ -229,7 +226,7 @@ fn main() -> Result<(), Box> { } "exiting" => { let mut client = - llmp::LlmpClient::create_attach_to_tcp(StdShMemProvider::new()?, port)?; + ll_mp::LlmpClient::create_attach_to_tcp(StdShMemProvider::new()?, port)?; for i in 0..10_u32 { client.send_buf(_TAG_SIMPLE_U32_V1, &i.to_le_bytes())?; println!("Exiting Client writing {i}"); diff --git a/crates/minibsod/Cargo.toml b/crates/minibsod/Cargo.toml index 231b9ae11aa..e9cd11a93c1 100644 --- a/crates/minibsod/Cargo.toml +++ b/crates/minibsod/Cargo.toml @@ -42,6 +42,7 @@ rustversion = { workspace = true } document-features = { workspace = true, optional = true } backtrace = { workspace = true } libc = { workspace = true } +exceptional = { workspace = true } [target.'cfg(target_vendor = "apple")'.dependencies] mach2 = "0.4.2" diff --git a/crates/minibsod/src/lib.rs b/crates/minibsod/src/lib.rs index 48d9ea29be9..4a404951351 100644 --- a/crates/minibsod/src/lib.rs +++ b/crates/minibsod/src/lib.rs @@ -59,6 +59,8 @@ use std::io::{BufWriter, Write}; #[cfg(any(target_os = "solaris", target_os = "illumos"))] use std::process::Command; +#[cfg(unix)] +use exceptional::unix_signals::{Signal, ucontext_t}; #[cfg(unix)] use libc::siginfo_t; #[cfg(target_vendor = "apple")] @@ -73,9 +75,6 @@ use mach2::{ #[cfg(windows)] use windows::Win32::System::Diagnostics::Debug::{CONTEXT, EXCEPTION_POINTERS}; -#[cfg(unix)] -use crate::os::unix_signals::{Signal, ucontext_t}; - /// Necessary info to print a mini-BSOD. #[derive(Debug)] #[cfg(unix)] diff --git a/crates/no_std_time/src/lib.rs b/crates/no_std_time/src/lib.rs index 086564ac05e..a486a44d237 100644 --- a/crates/no_std_time/src/lib.rs +++ b/crates/no_std_time/src/lib.rs @@ -56,6 +56,11 @@ use core::time; pub mod time_counters; +#[cfg(feature = "alloc")] +use alloc::string::String; +#[cfg(feature = "std")] +use std::time::{SystemTime, UNIX_EPOCH}; + /// Format a `Duration` into a HMS string #[cfg(feature = "alloc")] #[must_use] @@ -136,4 +141,3 @@ pub fn current_nanos() -> u64 { pub fn current_milliseconds() -> u64 { current_time().as_millis() as u64 } - diff --git a/crates/serde_anymap/src/lib.rs b/crates/serde_anymap/src/lib.rs index 7dff1e6180f..a671429e28e 100644 --- a/crates/serde_anymap/src/lib.rs +++ b/crates/serde_anymap/src/lib.rs @@ -50,5 +50,5 @@ extern crate std; #[doc(hidden)] pub extern crate alloc; +pub mod anymap; pub mod serdeany; -pub mod anymap; \ No newline at end of file From eade0cd7c239a357eba36726d74e0e6638e29f89 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sat, 12 Jul 2025 02:00:29 +0200 Subject: [PATCH 05/18] mas --- crates/libafl_bolts/Cargo.toml | 2 ++ crates/libafl_bolts/src/lib.rs | 39 +++++++------------------------ crates/ll_mp/src/lib.rs | 4 +++- crates/shmem_providers/src/lib.rs | 10 ++------ 4 files changed, 16 insertions(+), 39 deletions(-) diff --git a/crates/libafl_bolts/Cargo.toml b/crates/libafl_bolts/Cargo.toml index 653c42a2391..26031f4783b 100644 --- a/crates/libafl_bolts/Cargo.toml +++ b/crates/libafl_bolts/Cargo.toml @@ -47,6 +47,7 @@ std = [ "serde/std", "libafl_core/std", "libafl_core/nix", + "shmem_providers/std", "uuid", "backtrace", "uds", @@ -131,6 +132,7 @@ static_assertions = { workspace = true } typeid = { workspace = true } shmem_providers = { workspace = true } fast_rands = { workspace = true } +no_std_time = { workspace = true } tuple_list = { version = "0.1.3" } hashbrown = { workspace = true, features = [ diff --git a/crates/libafl_bolts/src/lib.rs b/crates/libafl_bolts/src/lib.rs index ac26acb121d..d6519273ed7 100644 --- a/crates/libafl_bolts/src/lib.rs +++ b/crates/libafl_bolts/src/lib.rs @@ -57,10 +57,6 @@ pub extern crate alloc; #[cfg(feature = "ctor")] #[doc(hidden)] pub use ctor; -#[cfg(feature = "alloc")] -pub mod anymap; -#[cfg(feature = "std")] -pub mod build_id; #[cfg(all( any(feature = "cli", feature = "frida_cli", feature = "qemu_cli"), feature = "std" @@ -69,26 +65,13 @@ pub mod cli; #[cfg(feature = "gzip")] pub mod compress; #[cfg(feature = "std")] -pub mod core_affinity; -#[cfg(feature = "std")] pub mod fs; -#[cfg(feature = "alloc")] -pub mod llmp; pub mod math; -#[cfg(feature = "std")] -pub mod minibsod; pub mod os; -#[cfg(feature = "alloc")] -pub mod ownedref; -#[cfg(feature = "alloc")] -pub mod serdeany; #[cfg(feature = "std")] pub mod staterestore; -#[cfg(feature = "alloc")] -pub mod subrange; -// TODO: reenable once ahash works in no-alloc -#[cfg(any(feature = "xxh3", feature = "alloc"))] -pub mod tuples; + +use no_std_time::current_time; #[cfg(all(feature = "std", unix))] pub mod argparse; @@ -102,8 +85,8 @@ pub use target_args::*; pub mod simd; -pub use libafl_core::Error; pub use fast_rands as rands; +pub use libafl_core::Error; pub use shmem_providers as shmem; /// The purpose of this module is to alleviate imports of the bolts by adding a glob import. @@ -134,6 +117,8 @@ pub mod bolts_prelude { #[cfg(all(unix, feature = "std"))] use alloc::boxed::Box; #[cfg(feature = "alloc")] +use alloc::string::String; +#[cfg(feature = "alloc")] use alloc::string::ToString; #[cfg(all(not(feature = "xxh3"), feature = "alloc"))] use core::hash::BuildHasher; @@ -141,8 +126,6 @@ use core::hash::BuildHasher; use core::hash::{Hash, Hasher}; #[cfg(all(unix, feature = "std"))] use core::mem; -#[cfg(feature = "std")] -use std::time::{SystemTime, UNIX_EPOCH}; #[cfg(all(unix, feature = "std"))] use std::{ fs::File, @@ -155,16 +138,12 @@ use std::{ // TODO: re-enable once is resolved. #[cfg(all(not(feature = "xxh3"), feature = "alloc"))] use ahash::RandomState; -#[cfg(feature = "xxh3")] -use xxhash_rust::xxh3::xxh3_64; - -#[cfg(feature = "alloc")] -use alloc::string::String; - #[cfg(feature = "libafl_derive")] pub use libafl_derive::SerdeAny; #[cfg(feature = "std")] use log::{Metadata, Record}; +#[cfg(feature = "xxh3")] +use xxhash_rust::xxh3::xxh3_64; /// Returns the standard input [`Hasher`] /// @@ -247,12 +226,12 @@ impl Truncate for &[T] { impl Truncate for &mut [T] { fn truncate(&mut self, len: usize) { - let value = core::mem::take(self); + let value = mem::take(self); let len = value.len().min(len); let truncated = value .get_mut(..len) .expect("Truncate with len <= len() should always work"); - let _: &mut [T] = core::mem::replace(self, truncated); + let _: &mut [T] = mem::replace(self, truncated); } } diff --git a/crates/ll_mp/src/lib.rs b/crates/ll_mp/src/lib.rs index c9324d642a8..99e167363f6 100644 --- a/crates/ll_mp/src/lib.rs +++ b/crates/ll_mp/src/lib.rs @@ -111,6 +111,8 @@ pub extern crate alloc; use alloc::boxed::Box; #[cfg(feature = "std")] use alloc::string::ToString; +#[cfg(feature = "alloc")] +use alloc::vec; use alloc::{string::String, vec::Vec}; #[cfg(feature = "std")] use core::net::SocketAddr; @@ -148,7 +150,7 @@ use exceptional::unix_signals::{Signal, SignalHandler, siginfo_t, ucontext_t}; use exceptional::windows_exceptions::{CtrlHandler, setup_ctrl_handler}; #[cfg(feature = "std")] use libafl_core::IP_LOCALHOST; -use libafl_core::{ClientId, Error}; +use libafl_core::{ClientId, Error, format}; #[cfg(all(unix, feature = "std"))] #[cfg(not(any(target_os = "solaris", target_os = "illumos")))] use nix::sys::socket::{self, sockopt::ReusePort}; diff --git a/crates/shmem_providers/src/lib.rs b/crates/shmem_providers/src/lib.rs index b036f8c2f77..5eff4766362 100644 --- a/crates/shmem_providers/src/lib.rs +++ b/crates/shmem_providers/src/lib.rs @@ -1237,10 +1237,7 @@ pub mod unix_shmem { open, }; - use crate::{ - Error, - shmem::{ShMem, ShMemId, ShMemProvider}, - }; + use crate::{Error, ShMem, ShMemId, ShMemProvider}; /// An ashmem based impl for linux/android #[derive(Debug, Clone)] @@ -1458,10 +1455,7 @@ pub mod unix_shmem { use libc::{MAP_SHARED, PROT_READ, PROT_WRITE, close, fstat, ftruncate, mmap, munmap}; use nix::sys::memfd::{MFdFlags, memfd_create}; - use crate::{ - Error, - shmem::{ShMem, ShMemId, ShMemProvider}, - }; + use crate::{Error, ShMem, ShMemId, ShMemProvider}; /// An memfd based impl for linux/android #[cfg(unix)] From 14be25c927b7d87ba8d473fcf52b6709876e71b5 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Tue, 15 Jul 2025 01:52:59 +0200 Subject: [PATCH 06/18] Still more --- Cargo.toml | 74 +++++----- crates/core_affinity2/src/lib.rs | 3 - crates/libafl/Cargo.toml | 2 +- crates/libafl_bolts/Cargo.toml | 88 +++++++----- crates/libafl_bolts/src/lib.rs | 60 +++----- crates/libafl_bolts/src/math.rs | 4 +- crates/libafl_bolts/src/os.rs | 7 +- crates/libafl_core/Cargo.toml | 2 +- crates/libafl_core/src/lib.rs | 93 ++++++++++++- crates/libafl_targets/Cargo.toml | 3 + crates/libafl_targets/src/cmps/mod.rs | 21 ++- crates/libafl_targets/src/coverage.rs | 4 +- crates/libafl_targets/src/drcov.rs | 2 +- crates/libafl_targets/src/forkserver.rs | 18 +-- .../libafl_targets/src/libfuzzer/mutators.rs | 4 +- .../src/libfuzzer/observers/oom.rs | 3 +- crates/libafl_targets/src/sancov_8bit.rs | 3 +- crates/ll_mp/Cargo.toml | 2 +- crates/ll_mp/src/lib.rs | 1 + crates/minibsod/Cargo.toml | 6 +- crates/minibsod/src/lib.rs | 2 - crates/ownedref/Cargo.toml | 3 + crates/ownedref/src/lib.rs | 29 +--- crates/ownedref/src/subrange.rs | 35 +++-- crates/serde_anymap/Cargo.toml | 18 ++- crates/serde_anymap/src/serdeany.rs | 10 +- crates/tuple_list_ex/Cargo.toml | 12 ++ crates/tuple_list_ex/src/lib.rs | 131 +----------------- 28 files changed, 305 insertions(+), 335 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 22460fa96b0..a5ec71af09c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,30 +5,30 @@ members = [ "crates/core_affinity2", "crates/exceptional", "crates/fast_rands", - "crates/libafl", "crates/libafl_asan", "crates/libafl_asan/libafl_asan_fuzz", "crates/libafl_asan/libafl_asan_libc", "crates/libafl_bolts", "crates/libafl_cc", - "crates/libafl_concolic/symcc_runtime", "crates/libafl_concolic/symcc_libafl", + "crates/libafl_concolic/symcc_runtime", + "crates/libafl_concolic/test/dump_constraints", + "crates/libafl_concolic/test/runtime_test", "crates/libafl_core", "crates/libafl_derive", "crates/libafl_frida", "crates/libafl_intelpt", "crates/libafl_libfuzzer", "crates/libafl_nyx", - "crates/libafl_unicorn", - "crates/libafl_targets", - "crates/libafl_tinyinst", "crates/libafl_qemu", "crates/libafl_qemu/libafl_qemu_build", "crates/libafl_qemu/libafl_qemu_runner", "crates/libafl_qemu/libafl_qemu_sys", "crates/libafl_sugar", - "crates/libafl_concolic/test/dump_constraints", - "crates/libafl_concolic/test/runtime_test", + "crates/libafl_targets", + "crates/libafl_tinyinst", + "crates/libafl_unicorn", + "crates/libafl", "crates/ll_mp", "crates/minibsod", "crates/no_std_time", @@ -37,33 +37,33 @@ members = [ "crates/shmem_providers", "crates/tuple_list_ex", "utils/build_and_test_fuzzers", + "utils/ci_runner", + "utils/ci_splitter", "utils/deexit", "utils/drcov_utils", "utils/gramatron/construct_automata", "utils/libafl_benches", "utils/libafl_jumper", - "utils/ci_runner", - "utils/ci_splitter", ] default-members = [ - "crates/libafl", "crates/libafl_bolts", "crates/libafl_cc", "crates/libafl_derive", "crates/libafl_targets", + "crates/libafl", ] exclude = [ "bindings/pylibafl", + "crates/libafl_libfuzzer_runtime", "docs", "fuzzers", - "crates/libafl_libfuzzer_runtime", - "utils/noaslr", + "scripts", "utils/gdb_qemu", "utils/libafl_repo_tools", "utils/multi_machine_generator", - "scripts", + "utils/noaslr", # additional crates "crates/libafl_concolic/test/symcc/util/symcc_fuzzing_helper", ] @@ -76,34 +76,44 @@ readme = "./README.md" [workspace.dependencies] # Internal deps +build_id2 = { path = "./crates/build_id2", version = "0.15.3", default-features = false } +core_affinity2 = { path = "./crates/core_affinity2", version = "0.15.3", default-features = false } exceptional = { path = "./crates/exceptional", version = "0.15.3", default-features = false } fast_rands = { path = "./crates/fast_rands", version = "0.15.3", default-features = false } libafl = { path = "./crates/libafl", version = "0.15.3", default-features = false } libafl_bolts = { path = "./crates/libafl_bolts", version = "0.15.3", default-features = false } libafl_cc = { path = "./crates/libafl_cc", version = "0.15.3", default-features = false } libafl_core = { path = "./crates/libafl_core", version = "0.15.3", default-features = false } -symcc_runtime = { path = "./crates/libafl_concolic/symcc_runtime", version = "0.15.2", default-features = false } -symcc_libafl = { path = "./crates/libafl_concolic/symcc_libafl", version = "0.15.3", default-features = false } libafl_derive = { path = "./crates/libafl_derive", version = "0.15.3", default-features = false } libafl_frida = { path = "./crates/libafl_frida", version = "0.15.3", default-features = false } libafl_intelpt = { path = "./crates/libafl_intelpt", version = "0.15.3", default-features = false } libafl_libfuzzer = { path = "./crates/libafl_libfuzzer", version = "0.15.3", default-features = false } libafl_nyx = { path = "./crates/libafl_nyx", version = "0.15.3", default-features = false } -libafl_targets = { path = "./crates/libafl_targets", version = "0.15.3", default-features = false } -libafl_tinyinst = { path = "./crates/libafl_tinyinst", version = "0.15.3", default-features = false } libafl_qemu = { path = "./crates/libafl_qemu", version = "0.15.3", default-features = false } libafl_qemu_build = { path = "./crates/libafl_qemu/libafl_qemu_build", version = "0.15.3", default-features = false } libafl_qemu_sys = { path = "./crates/libafl_qemu/libafl_qemu_sys", version = "0.15.3", default-features = false } libafl_sugar = { path = "./crates/libafl_sugar", version = "0.15.3", default-features = false } +libafl_targets = { path = "./crates/libafl_targets", version = "0.15.3", default-features = false } +libafl_tinyinst = { path = "./crates/libafl_tinyinst", version = "0.15.3", default-features = false } ll_mp = { path = "./crates/ll_mp", version = "0.15.3", default-features = false } +minibsod = { path = "./crates/minibsod", version = "0.15.3", default-features = false } no_std_time = { path = "./crates/no_std_time", version = "0.15.3", default-features = false } +ownedref = { path = "./crates/ownedref", version = "0.15.3", default-features = false } +serde_anymap = { path = "./crates/serde_anymap", version = "0.15.3", default-features = false } shmem_providers = { path = "./crates/shmem_providers", version = "0.15.3", default-features = false } +tuple_list_ex = { path = "./crates/tuple_list_ex", version = "0.15.2", default-features = false } + +# Concolic fuzzing crates dump_constraints = { path = "./crates/libafl_concolic/test/dump_constraints", version = "0.15.2", default-features = false } runtime_test = { path = "./crates/libafl_concolic/test/runtime_test", version = "0.15.2", default-features = false } +symcc_libafl = { path = "./crates/libafl_concolic/symcc_libafl", version = "0.15.3", default-features = false } +symcc_runtime = { path = "./crates/libafl_concolic/symcc_runtime", version = "0.15.2", default-features = false } + +# Utils build_and_test_fuzzers = { path = "./utils/build_and_test_fuzzers", version = "0.15.2", default-features = false } +construct_automata = { path = "./utils/gramatron/construct_automata", version = "0.15.2", default-features = false } deexit = { path = "./utils/deexit", version = "0.15.2", default-features = false } drcov_utils = { path = "./utils/drcov_utils", version = "0.15.2", default-features = false } -construct_automata = { path = "./utils/gramatron/construct_automata", version = "0.15.2", default-features = false } libafl_benches = { path = "./utils/libafl_benches", version = "0.15.3", default-features = false } libafl_jumper = { path = "./utils/libafl_jumper", version = "0.15.3", default-features = false } @@ -116,11 +126,13 @@ bindgen = "0.72.0" # fixme: Change this to 1.3.3 when the issue https://github.com/danlehmann/bitfield/issues/66 is resolved. bitbybit = "=1.3.2" # bitfields, use this for bit fields and bit enums capstone = "0.13.0" # Disassembler used in libafl_unicorn to provide disassembly on crash -clap = "4.5.18" cc = "1.1.21" +clap = "4.5.18" cmake = "0.1.51" document-features = "0.2.10" +erased-serde = { version = "0.4.5", default-features = false } # erased serde fastbloom = { version = "0.12.0", default-features = false } +fs2 = "0.4.3" # Used by OnDisk Corpus for file locking hashbrown = { version = "0.14.5", default-features = false } # A faster hashmap, nostd compatible just = "=1.40.0" libc = "0.2.159" # For (*nix) libc @@ -141,13 +153,14 @@ rangemap = "1.5.1" regex = "1.10.6" rustversion = "1.0.17" serde = { version = "1.0.210", default-features = false } # serialization lib -serial_test = { version = "3.2.0", default-features = false } serde_json = { version = "1.0.128", default-features = false } serde_yaml = { version = "0.9.34" } # For parsing the injections yaml file +serial_test = { version = "3.2.0", default-features = false } static_assertions = "1.1.0" strum = "0.27.0" strum_macros = "0.27.0" toml = "0.9.0" # For parsing the injections toml file +tuple_list = { version = "0.1.3" } typed-builder = "0.21.0" # Implement the builder pattern at compiletime typeid = "1.0.0" # Safe type_eq that doesn't rely on std specialization unicorn-engine = "2.0.1" # Used in libafl_unicorn @@ -155,7 +168,6 @@ uuid = { version = "1.10.0", features = ["serde", "v4"] } which = "8.0.0" windows = "0.59.0" z3 = "0.12.1" -fs2 = "0.4.3" # Used by OnDisk Corpus for file locking [workspace.lints.rust] # Deny @@ -183,21 +195,21 @@ std_instead_of_core = "deny" cargo = { level = "warn", priority = -1 } # Allow -negative_feature_names = "allow" # TODO: turn into 'warn' when working -multiple_crate_versions = "allow" # TODO: turn into `warn` when working -unreadable_literal = "allow" -type_repetition_in_bounds = "allow" -missing_errors_doc = "allow" cast_possible_truncation = "allow" -used_underscore_binding = "allow" -ptr_as_ptr = "allow" +comparison_chain = "allow" # This lint makes **ZERO** sense +missing_errors_doc = "allow" missing_panics_doc = "allow" module_name_repetitions = "allow" -unsafe_derive_deserialize = "allow" +multiple_crate_versions = "allow" # TODO: turn into `warn` when working +negative_feature_names = "allow" # TODO: turn into 'warn' when working +ptr_as_ptr = "allow" similar_names = "allow" -too_many_lines = "allow" -comparison_chain = "allow" # This lint makes **ZERO** sense struct_field_names = "allow" # ???? +too_many_lines = "allow" +type_repetition_in_bounds = "allow" +unreadable_literal = "allow" +unsafe_derive_deserialize = "allow" +used_underscore_binding = "allow" [workspace.lints.rustdoc] # Deny diff --git a/crates/core_affinity2/src/lib.rs b/crates/core_affinity2/src/lib.rs index 13edd67cda7..4b5109fa8f8 100644 --- a/crates/core_affinity2/src/lib.rs +++ b/crates/core_affinity2/src/lib.rs @@ -77,7 +77,6 @@ ) )] -#[cfg(feature = "std")] #[macro_use] extern crate std; #[doc(hidden)] @@ -146,7 +145,6 @@ pub struct Cores { pub ids: Vec, } -#[cfg(feature = "std")] impl Cores { /// Pick all cores pub fn all() -> Result { @@ -245,7 +243,6 @@ impl From> for Cores { } } -#[cfg(feature = "std")] impl TryFrom<&str> for Cores { type Error = Error; fn try_from(cores: &str) -> Result { diff --git a/crates/libafl/Cargo.toml b/crates/libafl/Cargo.toml index 19206be9b16..1863fcdc909 100644 --- a/crates/libafl/Cargo.toml +++ b/crates/libafl/Cargo.toml @@ -223,7 +223,7 @@ libafl_intelpt = { workspace = true, default-features = true, optional = true } ll_mp = { workspace = true } rustversion = { workspace = true } -tuple_list = { version = "0.1.3" } +tuple_list = { workspace = true } hashbrown = { workspace = true, features = [ "serde", "ahash", diff --git a/crates/libafl_bolts/Cargo.toml b/crates/libafl_bolts/Cargo.toml index 653c42a2391..19cadc306f9 100644 --- a/crates/libafl_bolts/Cargo.toml +++ b/crates/libafl_bolts/Cargo.toml @@ -42,27 +42,32 @@ document-features = ["dep:document-features"] ## Enables features that need rust's `std` lib to work, like print, env, ... support std = [ + "alloc", + "backtrace", "hostname", + "libafl_core/nix", + "libafl_core/std", "nix", + "no_std_time/std", "serde/std", - "libafl_core/std", - "libafl_core/nix", - "uuid", - "backtrace", - "uds", "serial_test", - "alloc", + "shmem_providers/std", "simd", + "uds", + "uuid", ] ## Enables all features that allocate in `no_std` alloc = [ - "serde/alloc", - "hashbrown", - "postcard", - "erased-serde/alloc", "ahash", + "erased-serde/alloc", + "hashbrown", "libafl_core/alloc", + "no_std_time/alloc", + "postcard", + "serde/alloc", + "shmem_providers/alloc", + "tuple_list_ex/alloc", ] ## Provide the `#[derive(SerdeAny)]` macro. @@ -125,56 +130,63 @@ chrono = "0.4.40" itertools = "0.14.0" [dependencies] +build_id2 = { workspace = true } +core_affinity2 = { workspace = true } +fast_rands = { workspace = true } libafl_core = { workspace = true, features = ["postcard"] } libafl_derive = { workspace = true, default-features = true, optional = true } +ll_mp = { workspace = true } +minibsod = { workspace = true } +no_std_time = { workspace = true } +ownedref = { workspace = true } +serde_anymap = { workspace = true } +shmem_providers = { workspace = true } static_assertions = { workspace = true } +tuple_list_ex = { workspace = true } typeid = { workspace = true } -shmem_providers = { workspace = true } -fast_rands = { workspace = true } -tuple_list = { version = "0.1.3" } +ahash = { workspace = true, optional = true } # The hash function already used in hashbrown +backtrace = { workspace = true, default-features = true, optional = true } # Used to get the stacktrace in StacktraceObserver +clap = { workspace = true, features = [ + "derive", + "wrap_help", +], optional = true } # CLI parsing, for libafl_bolts::cli / the `cli` feature +ctor = { optional = true, version = "0.4.0" } +erased-serde = { version = "0.4.5", default-features = false, optional = true } # erased serde hashbrown = { workspace = true, features = [ "serde", "ahash", ], default-features = false, optional = true } # A faster hashmap, nostd compatible -xxhash-rust = { version = "0.8.12", features = [ - "xxh3", -], optional = true } # xxh3 hashing for rust -serde = { workspace = true, default-features = false, features = [ - "derive", -] } # serialization lib -erased-serde = { version = "0.4.5", default-features = false, optional = true } # erased serde -postcard = { workspace = true, optional = true } # no_std compatible serde serialization format -num_enum = { workspace = true, default-features = false } -ahash = { workspace = true, optional = true } # The hash function already used in hashbrown -backtrace = { workspace = true, default-features = true, optional = true } # Used to get the stacktrace in StacktraceObserver - -ctor = { optional = true, version = "0.4.0" } -miniz_oxide = { version = "0.8.0", optional = true } hostname = { version = "0.4.0", optional = true } # Is there really no gethostname in the stdlib? -rand_core = { version = "0.9.0", optional = true } +log = { workspace = true } +miniz_oxide = { version = "0.8.0", optional = true } nix = { workspace = true, optional = true, default-features = false, features = [ "fs", "signal", "socket", "poll", ] } -uuid = { workspace = true, optional = true, features = ["serde", "v4"] } -clap = { workspace = true, features = [ - "derive", - "wrap_help", -], optional = true } # CLI parsing, for libafl_bolts::cli / the `cli` feature -log = { workspace = true } +num_enum = { workspace = true, default-features = false } +postcard = { workspace = true, optional = true } # no_std compatible serde serialization format pyo3 = { workspace = true, optional = true, features = ["serde", "macros"] } +rand_core = { version = "0.9.0", optional = true } +serde = { workspace = true, default-features = false, features = [ + "derive", +] } # serialization lib +tuple_list = { workspace = true } +uuid = { workspace = true, optional = true, features = ["serde", "v4"] } +xxhash-rust = { version = "0.8.12", features = [ + "xxh3", +], optional = true } # xxh3 hashing for rust # optional-dev deps (change when target.'cfg(accessible(::std))'.test-dependencies will be stable) serial_test = { workspace = true, optional = true, default-features = false, features = [ "logging", ] } +rustversion = { workspace = true } # optional stable simd, pin to a commit due to `u8x32` not released yet. Switch to `wide` as long as next release is out! wide = { version = "0.7.33", optional = true, package = "libafl_wide" } -rustversion = { workspace = true } # Document all features of this crate (for `cargo doc`) document-features = { workspace = true, optional = true } @@ -186,13 +198,13 @@ uds = { version = "0.4.2", optional = true, default-features = false } [target.'cfg(windows)'.dependencies] windows = { workspace = true, features = [ "Win32_Foundation", - "Win32_System_Threading", + "Win32_Security", + "Win32_System_Console", "Win32_System_Diagnostics_Debug", "Win32_System_Kernel", "Win32_System_Memory", - "Win32_Security", "Win32_System_SystemInformation", - "Win32_System_Console", + "Win32_System_Threading", ] } once_cell = "1.10.0" winapi = { version = "0.3", features = [ diff --git a/crates/libafl_bolts/src/lib.rs b/crates/libafl_bolts/src/lib.rs index ac26acb121d..4ea5c080093 100644 --- a/crates/libafl_bolts/src/lib.rs +++ b/crates/libafl_bolts/src/lib.rs @@ -54,13 +54,13 @@ extern crate std; #[doc(hidden)] pub extern crate alloc; +#[cfg(feature = "std")] +pub use build_id2 as build_id; #[cfg(feature = "ctor")] #[doc(hidden)] pub use ctor; #[cfg(feature = "alloc")] -pub mod anymap; -#[cfg(feature = "std")] -pub mod build_id; +pub use serde_anymap::anymap; #[cfg(all( any(feature = "cli", feature = "frida_cli", feature = "qemu_cli"), feature = "std" @@ -69,26 +69,22 @@ pub mod cli; #[cfg(feature = "gzip")] pub mod compress; #[cfg(feature = "std")] -pub mod core_affinity; +pub use core_affinity2 as core_affinity; #[cfg(feature = "std")] pub mod fs; #[cfg(feature = "alloc")] -pub mod llmp; +pub use ll_mp as llmp; pub mod math; #[cfg(feature = "std")] -pub mod minibsod; +pub use minibsod; pub mod os; #[cfg(feature = "alloc")] -pub mod ownedref; -#[cfg(feature = "alloc")] -pub mod serdeany; +pub use serde_anymap::serdeany; #[cfg(feature = "std")] pub mod staterestore; -#[cfg(feature = "alloc")] -pub mod subrange; // TODO: reenable once ahash works in no-alloc #[cfg(any(feature = "xxh3", feature = "alloc"))] -pub mod tuples; +pub use tuple_list_ex as tuples; #[cfg(all(feature = "std", unix))] pub mod argparse; @@ -102,8 +98,12 @@ pub use target_args::*; pub mod simd; -pub use libafl_core::Error; pub use fast_rands as rands; +pub use libafl_core::{ + AsIter, AsIterMut, AsSlice, AsSliceMut, ClientId, Error, HasLen, HasRefCnt, Named, Truncate, +}; +pub use no_std_time::current_time; +pub use ownedref; pub use shmem_providers as shmem; /// The purpose of this module is to alleviate imports of the bolts by adding a glob import. @@ -134,6 +134,8 @@ pub mod bolts_prelude { #[cfg(all(unix, feature = "std"))] use alloc::boxed::Box; #[cfg(feature = "alloc")] +use alloc::string::String; +#[cfg(feature = "alloc")] use alloc::string::ToString; #[cfg(all(not(feature = "xxh3"), feature = "alloc"))] use core::hash::BuildHasher; @@ -141,8 +143,6 @@ use core::hash::BuildHasher; use core::hash::{Hash, Hasher}; #[cfg(all(unix, feature = "std"))] use core::mem; -#[cfg(feature = "std")] -use std::time::{SystemTime, UNIX_EPOCH}; #[cfg(all(unix, feature = "std"))] use std::{ fs::File, @@ -155,16 +155,12 @@ use std::{ // TODO: re-enable once is resolved. #[cfg(all(not(feature = "xxh3"), feature = "alloc"))] use ahash::RandomState; -#[cfg(feature = "xxh3")] -use xxhash_rust::xxh3::xxh3_64; - -#[cfg(feature = "alloc")] -use alloc::string::String; - #[cfg(feature = "libafl_derive")] pub use libafl_derive::SerdeAny; #[cfg(feature = "std")] use log::{Metadata, Record}; +#[cfg(feature = "xxh3")] +use xxhash_rust::xxh3::xxh3_64; /// Returns the standard input [`Hasher`] /// @@ -233,28 +229,6 @@ pub mod prelude { pub use super::{bolts_prelude::*, *}; } -/// Trait to truncate slices and maps to a new size -pub trait Truncate { - /// Reduce the size of the slice - fn truncate(&mut self, len: usize); -} - -impl Truncate for &[T] { - fn truncate(&mut self, len: usize) { - *self = &self[..len]; - } -} - -impl Truncate for &mut [T] { - fn truncate(&mut self, len: usize) { - let value = core::mem::take(self); - let len = value.len().min(len); - let truncated = value - .get_mut(..len) - .expect("Truncate with len <= len() should always work"); - let _: &mut [T] = core::mem::replace(self, truncated); - } -} /// Format a number with thousands separators #[cfg(feature = "alloc")] diff --git a/crates/libafl_bolts/src/math.rs b/crates/libafl_bolts/src/math.rs index d4b879c3c4d..2755335d127 100644 --- a/crates/libafl_bolts/src/math.rs +++ b/crates/libafl_bolts/src/math.rs @@ -2,9 +2,7 @@ use core::ops::AddAssign; -use libafl_core::Error; - -use libafl_core::format; +use libafl_core::{Error, format}; /// Returns the cumulative distribution function for a discrete distribution. pub fn calculate_cumulative_distribution_in_place(probabilities: &mut [f32]) -> Result<(), Error> { diff --git a/crates/libafl_bolts/src/os.rs b/crates/libafl_bolts/src/os.rs index a35f77cb6a9..e3b5d480ec2 100644 --- a/crates/libafl_bolts/src/os.rs +++ b/crates/libafl_bolts/src/os.rs @@ -1,8 +1,5 @@ //! Operating System specific abstractions -#[cfg(any(unix, all(windows, feature = "std")))] -use crate::Error; - #[cfg(all(unix, feature = "std"))] use alloc::{borrow::Cow, ffi::CString}; #[cfg(all(unix, feature = "std"))] @@ -19,13 +16,15 @@ use std::{ }; use libafl_core::format; - // Allow a few extra features we need for the whole module #[cfg(unix)] use libc::pid_t; #[cfg(all(windows, feature = "std"))] pub use windows_exceptions::CTRL_C_EXIT; +#[cfg(any(unix, all(windows, feature = "std")))] +use crate::Error; + /// A file that we keep open, pointing to /dev/null #[cfg(all(feature = "std", unix))] static NULL_FILE: OnceLock = OnceLock::new(); diff --git a/crates/libafl_core/Cargo.toml b/crates/libafl_core/Cargo.toml index 44e45049052..84f13b03b71 100644 --- a/crates/libafl_core/Cargo.toml +++ b/crates/libafl_core/Cargo.toml @@ -26,7 +26,7 @@ document-features = ["dep:document-features"] #! ### General Features ## Enables features that need rust's `std` lib to work, like print, env, ... support -std = [] +std = ["alloc"] ## Enables all features that allocate in `no_std` alloc = [] diff --git a/crates/libafl_core/src/lib.rs b/crates/libafl_core/src/lib.rs index 38a18e79d90..99548451ffd 100644 --- a/crates/libafl_core/src/lib.rs +++ b/crates/libafl_core/src/lib.rs @@ -63,7 +63,7 @@ macro_rules! format { } /// Re-export of the "format" macro #[cfg(feature = "alloc")] -pub use alloc::format; +pub use alloc::{borrow::Cow, format}; #[cfg(feature = "std")] #[macro_use] @@ -728,3 +728,94 @@ where Ok(new_vec) } } + +/// We need fixed names for many parts of this lib. +#[cfg(feature = "alloc")] +pub trait Named { + /// Provide the name of this element. + fn name(&self) -> &Cow<'static, str>; +} + +#[cfg(feature = "alloc")] +impl Named for () { + #[inline] + fn name(&self) -> &Cow<'static, str> { + static NAME: Cow<'static, str> = Cow::Borrowed("()"); + &NAME + } +} + +/// Has a length field +pub trait HasLen { + /// The length + fn len(&self) -> usize; + + /// Returns `true` if it has no elements. + fn is_empty(&self) -> bool { + self.len() == 0 + } +} + +#[cfg(feature = "alloc")] +impl HasLen for Vec { + #[inline] + fn len(&self) -> usize { + Vec::::len(self) + } +} + +impl HasLen for &mut T { + fn len(&self) -> usize { + self.deref().len() + } +} + +impl HasLen for (Head, Tail) +where + Tail: HasLen, +{ + #[inline] + fn len(&self) -> usize { + self.1.len() + 1 + } +} + +impl HasLen for (Tail,) +where + Tail: HasLen, +{ + #[inline] + fn len(&self) -> usize { + self.0.len() + } +} + +impl HasLen for () { + #[inline] + fn len(&self) -> usize { + 0 + } +} + +/// Trait to truncate slices and maps to a new size +pub trait Truncate { + /// Reduce the size of the slice + fn truncate(&mut self, len: usize); +} + +impl Truncate for &[T] { + fn truncate(&mut self, len: usize) { + *self = &self[..len]; + } +} + +impl Truncate for &mut [T] { + fn truncate(&mut self, len: usize) { + let value = core::mem::take(self); + let len = value.len().min(len); + let truncated = value + .get_mut(..len) + .expect("Truncate with len <= len() should always work"); + let _: &mut [T] = core::mem::replace(self, truncated); + } +} diff --git a/crates/libafl_targets/Cargo.toml b/crates/libafl_targets/Cargo.toml index 4fec14199dd..c5a6fbba88f 100644 --- a/crates/libafl_targets/Cargo.toml +++ b/crates/libafl_targets/Cargo.toml @@ -79,6 +79,9 @@ rustversion = "1.0.17" [dependencies] libafl = { workspace = true, features = [], default-features = false } libafl_bolts = { workspace = true, features = [] } +fast_rands = { workspace = true } +ownedref = { workspace = true } +shmem_providers = { workspace = true } libc = { workspace = true } nix = { workspace = true, optional = true } hashbrown = { workspace = true, default-features = true } diff --git a/crates/libafl_targets/src/cmps/mod.rs b/crates/libafl_targets/src/cmps/mod.rs index f80491e0df3..fc3966667d7 100644 --- a/crates/libafl_targets/src/cmps/mod.rs +++ b/crates/libafl_targets/src/cmps/mod.rs @@ -12,12 +12,11 @@ use core::{ ptr, slice, }; -use libafl::{ - Error, - observers::{CmpMap, CmpValues, CmplogBytes, cmp::AflppCmpLogHeader}, -}; -use libafl_bolts::HasLen; +use libafl::observers::{CmpMap, CmpValues, CmplogBytes, cmp::AflppCmpLogHeader}; +use libafl_bolts::{HasLen, ownedref::OwnedRefMut}; +use libafl_core::Error; use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use shmem_providers::ShMem; pub use stages::*; use crate::{CMPLOG_MAP_H, CMPLOG_MAP_W}; @@ -510,6 +509,18 @@ impl HasLen for AflppCmpLogMap { } impl AflppCmpLogMap { + /// Returns a new [`OwnedRefMut`] to an [`AflppCmpLogMap`], pointing to the given [`ShMem`]. + /// + /// # Panics + /// Panics if the given shared mem is too small + /// + /// # Safety + /// The shared memory needs to start with a valid [`AflppCmpLogMap`] object. + /// Any use of this [`OwnedRefMut`] will dereference a pointer to the given shared memory accordingly + pub unsafe fn from_shmem(shmem: &mut SHM) -> OwnedRefMut<'_, Self> { + unsafe { OwnedRefMut::from_mut_ptr(shmem.as_mut_ptr_of().unwrap()) } + } + #[must_use] #[expect(clippy::cast_ptr_alignment)] /// Instantiate a new boxed zeroed `AflppCmpLogMap`. This should be used to create a new diff --git a/crates/libafl_targets/src/coverage.rs b/crates/libafl_targets/src/coverage.rs index 032b09794a4..ebcf1e32898 100644 --- a/crates/libafl_targets/src/coverage.rs +++ b/crates/libafl_targets/src/coverage.rs @@ -10,7 +10,9 @@ use alloc::borrow::Cow; #[cfg(any(target_os = "linux", target_vendor = "apple"))] -use libafl::{Error, mutators::Tokens}; +use libafl::mutators::Tokens; +#[cfg(any(target_os = "linux", target_vendor = "apple"))] +use libafl_core::Error; use crate::{ACCOUNTING_MAP_SIZE, EDGES_MAP_ALLOCATED_SIZE, EDGES_MAP_DEFAULT_SIZE}; diff --git a/crates/libafl_targets/src/drcov.rs b/crates/libafl_targets/src/drcov.rs index c26b202e0de..c5fa5d9db6b 100644 --- a/crates/libafl_targets/src/drcov.rs +++ b/crates/libafl_targets/src/drcov.rs @@ -12,7 +12,7 @@ use std::{ }; use hashbrown::HashSet; -use libafl::Error; +use libafl_core::Error; use rangemap::RangeMap; /// A basic block struct diff --git a/crates/libafl_targets/src/forkserver.rs b/crates/libafl_targets/src/forkserver.rs index 0620ff081f6..ab24c3773ad 100644 --- a/crates/libafl_targets/src/forkserver.rs +++ b/crates/libafl_targets/src/forkserver.rs @@ -10,22 +10,18 @@ use std::{ use libafl::executors::forkserver::FS_NEW_OPT_AUTODTCT; #[cfg(feature = "cmplog")] use libafl::executors::forkserver::SHM_CMPLOG_ENV_VAR; -use libafl::{ - Error, - executors::forkserver::{ - AFL_MAP_SIZE_ENV_VAR, FORKSRV_FD, FS_ERROR_SHM_OPEN, FS_NEW_OPT_MAPSIZE, - FS_NEW_OPT_SHDMEM_FUZZ, FS_NEW_VERSION_MAX, FS_OPT_ERROR, MAX_INPUT_SIZE_DEFAULT, - SHM_ENV_VAR, SHM_FUZZ_ENV_VAR, SHM_FUZZ_MAP_SIZE_ENV_VAR, SHMEM_FUZZ_HDR_SIZE, - }, -}; -use libafl_bolts::{ - os::{ChildHandle, ForkResult}, - shmem::{ShMem, ShMemId, ShMemProvider}, +use libafl::executors::forkserver::{ + AFL_MAP_SIZE_ENV_VAR, FORKSRV_FD, FS_ERROR_SHM_OPEN, FS_NEW_OPT_MAPSIZE, + FS_NEW_OPT_SHDMEM_FUZZ, FS_NEW_VERSION_MAX, FS_OPT_ERROR, MAX_INPUT_SIZE_DEFAULT, SHM_ENV_VAR, + SHM_FUZZ_ENV_VAR, SHM_FUZZ_MAP_SIZE_ENV_VAR, SHMEM_FUZZ_HDR_SIZE, }; +use libafl_bolts::os::{ChildHandle, ForkResult}; +use libafl_core::Error; use nix::{ sys::signal::{SigHandler, Signal}, unistd::Pid, }; +use shmem_providers::{ShMem, ShMemId, ShMemProvider}; #[cfg(feature = "cmplog_extended_instrumentation")] use crate::cmps::EXTENDED_CMPLOG_MAP_PTR; diff --git a/crates/libafl_targets/src/libfuzzer/mutators.rs b/crates/libafl_targets/src/libfuzzer/mutators.rs index 52bfb634ee2..bfa804c66d9 100644 --- a/crates/libafl_targets/src/libfuzzer/mutators.rs +++ b/crates/libafl_targets/src/libfuzzer/mutators.rs @@ -6,8 +6,8 @@ use alloc::{ }; use core::{cell::RefCell, marker::PhantomData, ops::Deref}; +use fast_rands::Rand; use libafl::{ - Error, corpus::{Corpus, CorpusId}, inputs::{BytesInput, HasMutatorBytes, ResizableMutator}, mutators::{ @@ -16,7 +16,7 @@ use libafl::{ random_corpus_id_with_disabled, state::{HasCorpus, HasMaxSize, HasRand}, }; -use libafl_bolts::{AsSlice, HasLen, Named, rands::Rand}; +use libafl_core::{AsSlice, Error, HasLen, Named}; unsafe extern "C" { fn libafl_targets_has_libfuzzer_custom_mutator() -> bool; diff --git a/crates/libafl_targets/src/libfuzzer/observers/oom.rs b/crates/libafl_targets/src/libfuzzer/observers/oom.rs index bc8f3b1522e..4bdfe2676c0 100644 --- a/crates/libafl_targets/src/libfuzzer/observers/oom.rs +++ b/crates/libafl_targets/src/libfuzzer/observers/oom.rs @@ -6,12 +6,11 @@ use core::{ }; use libafl::{ - Error, executors::ExitKind, feedbacks::{Feedback, StateInitializer}, observers::Observer, }; -use libafl_bolts::Named; +use libafl_core::{Error, Named}; use libc::SIGABRT; use serde::{Deserialize, Serialize}; diff --git a/crates/libafl_targets/src/sancov_8bit.rs b/crates/libafl_targets/src/sancov_8bit.rs index 9ce2fa4ab6a..33d3f6b9c7c 100644 --- a/crates/libafl_targets/src/sancov_8bit.rs +++ b/crates/libafl_targets/src/sancov_8bit.rs @@ -1,7 +1,8 @@ //! [`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::{AsSlice, AsSliceMut, ownedref::OwnedMutSlice}; +use libafl_core::{AsSlice, AsSliceMut}; +use ownedref::OwnedMutSlice; /// A [`Vec`] of `8-bit-counters` maps for multiple modules. /// They are initialized by calling [`__sanitizer_cov_8bit_counters_init`]( diff --git a/crates/ll_mp/Cargo.toml b/crates/ll_mp/Cargo.toml index 651a5291060..5ef705a3a95 100644 --- a/crates/ll_mp/Cargo.toml +++ b/crates/ll_mp/Cargo.toml @@ -69,7 +69,7 @@ miniz_oxide = { version = "0.8.0", optional = true } hostname = { version = "0.4.0", optional = true } # Is there really no gethostname in the stdlib? postcard = { workspace = true, optional = true } # no_std compatible serde serialization format log = { workspace = true } -tuple_list = { version = "0.1.3" } +tuple_list = { workspace = true } libafl_core = { workspace = true } nix = { workspace = true, features = ["socket"] } no_std_time = { workspace = true } diff --git a/crates/ll_mp/src/lib.rs b/crates/ll_mp/src/lib.rs index c9324d642a8..c5b43c544f7 100644 --- a/crates/ll_mp/src/lib.rs +++ b/crates/ll_mp/src/lib.rs @@ -104,6 +104,7 @@ Check out the `llmp_test` example in ./examples, or build it with `cargo run --e #[cfg(feature = "std")] #[macro_use] extern crate std; +#[macro_use] #[doc(hidden)] pub extern crate alloc; diff --git a/crates/minibsod/Cargo.toml b/crates/minibsod/Cargo.toml index e9cd11a93c1..3518a1650c2 100644 --- a/crates/minibsod/Cargo.toml +++ b/crates/minibsod/Cargo.toml @@ -5,15 +5,15 @@ authors = [ "Andrea Fioraldi ", "Dominik Maier ", ] -description = "A library to dump current register states" +description = "A library to dump current register states, etc., on crash" documentation = "https://docs.rs/libafl" repository = "https://github.com/AFLplusplus/LibAFL/" readme = "./README.md" license = "MIT OR Apache-2.0" -keywords = ["os", "shmem", "no-std"] +keywords = ["os", "bsod"] edition = "2024" rust-version = "1.87" -categories = ["embedded", "os", "no-std"] +categories = ["os"] [package.metadata.docs.rs] features = ["document-features"] diff --git a/crates/minibsod/src/lib.rs b/crates/minibsod/src/lib.rs index 4a404951351..03400a1a9f5 100644 --- a/crates/minibsod/src/lib.rs +++ b/crates/minibsod/src/lib.rs @@ -3,7 +3,6 @@ #![doc = include_str!("../../../README.md")] /*! */ #![cfg_attr(feature = "document-features", doc = document_features::document_features!())] -#![no_std] #![cfg_attr(not(test), warn( missing_debug_implementations, missing_docs, @@ -45,7 +44,6 @@ ) )] -#[cfg(feature = "std")] #[macro_use] extern crate std; #[doc(hidden)] diff --git a/crates/ownedref/Cargo.toml b/crates/ownedref/Cargo.toml index 33ef0a54df4..4fee6ed3b9c 100644 --- a/crates/ownedref/Cargo.toml +++ b/crates/ownedref/Cargo.toml @@ -41,5 +41,8 @@ rustversion = { workspace = true } # Document all features of this crate (for `cargo doc`) document-features = { workspace = true, optional = true } +libafl_core = { workspace = true } +serde = { workspace = true } + [lints] workspace = true diff --git a/crates/ownedref/src/lib.rs b/crates/ownedref/src/lib.rs index e89f232c450..13d70ace810 100644 --- a/crates/ownedref/src/lib.rs +++ b/crates/ownedref/src/lib.rs @@ -63,17 +63,16 @@ use core::{ slice::{Iter, IterMut, SliceIndex}, }; -use libafl_core::{AsSizedSlice, AsSizedSliceMut, AsSlice, AsSliceMut, IntoOwned}; +use libafl_core::{AsSizedSlice, AsSizedSliceMut, AsSlice, AsSliceMut, IntoOwned, Truncate}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use crate::{Truncate, shmem::ShMem}; - /// Constant size array visitor for serde deserialization. /// Mostly taken from mod arrays { use alloc::{boxed::Box, fmt, vec::Vec}; use core::{convert::TryInto, marker::PhantomData}; + use libafl_core::format; use serde::{ Deserialize, Deserializer, de::{SeqAccess, Visitor}, @@ -217,18 +216,6 @@ impl OwnedRef<'_, T> where T: Sized + 'static, { - /// Returns a new [`OwnedRef`], pointing to the given [`ShMem`]. - /// - /// # Panics - /// Panics if the given shared mem is too small - /// - /// # Safety - /// 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 { - unsafe { Self::from_ptr(shmem.as_mut_ptr_of().unwrap()) } - } - /// Returns a new [`OwnedRef`], owning the given value. pub fn owned(val: T) -> Self { Self::Owned(Box::new(val)) @@ -350,18 +337,6 @@ impl OwnedRefMut<'_, T> where T: Sized + 'static, { - /// Returns a new [`OwnedRefMut`], pointing to the given [`ShMem`]. - /// - /// # Panics - /// Panics if the given shared mem is too small - /// - /// # Safety - /// 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 { - unsafe { Self::from_mut_ptr(shmem.as_mut_ptr_of().unwrap()) } - } - /// Returns a new [`OwnedRefMut`], owning the given value. pub fn owned(val: T) -> Self { Self::Owned(Box::new(val)) diff --git a/crates/ownedref/src/subrange.rs b/crates/ownedref/src/subrange.rs index a8132973278..65d787fe970 100644 --- a/crates/ownedref/src/subrange.rs +++ b/crates/ownedref/src/subrange.rs @@ -6,10 +6,9 @@ use core::{ ops::{Bound, Range, RangeBounds}, }; -use crate::{ - ownedref::{OwnedMutSlice, OwnedSlice}, - tuples::HasLen, -}; +use libafl_core::HasLen; + +use crate::{OwnedMutSlice, OwnedSlice}; /// An immutable contiguous subslice of a byte slice. /// It is mostly useful to cheaply wrap a subslice of a given input. @@ -35,6 +34,20 @@ pub struct SubRangeMutSlice<'a, T> { range: Range, } +impl HasLen for SubRangeSlice<'_, T> { + #[inline] + fn len(&self) -> usize { + self.range.len() + } +} + +impl HasLen for SubRangeMutSlice<'_, T> { + #[inline] + fn len(&self) -> usize { + self.range.len() + } +} + /// Slice wrapper keeping track of the current read position. /// Convenient wrapper when the slice must be split in multiple sub-slices and read sequentially. #[derive(Debug)] @@ -96,20 +109,6 @@ impl<'a, T> From<&'a [T]> for SliceReader<'a, T> { } } -impl HasLen for SubRangeSlice<'_, T> { - #[inline] - fn len(&self) -> usize { - self.range.len() - } -} - -impl HasLen for SubRangeMutSlice<'_, T> { - #[inline] - fn len(&self) -> usize { - self.range.len() - } -} - /// Gets the relevant concrete start index from [`RangeBounds`] (inclusive) pub fn start_index(range: &R) -> usize where diff --git a/crates/serde_anymap/Cargo.toml b/crates/serde_anymap/Cargo.toml index ce110337d86..80020ec3eaa 100644 --- a/crates/serde_anymap/Cargo.toml +++ b/crates/serde_anymap/Cargo.toml @@ -20,17 +20,21 @@ features = ["document-features"] all-features = true [features] -default = ["std", "alloc"] +default = ["std", "alloc", "stable_anymap"] document-features = ["dep:document-features"] #! # Feature Flags #! ### General Features ## Enables features that need rust's `std` lib to work, like print, env, ... support -std = [] +std = ["alloc", "libafl_core/std"] ## Enables all features that allocate in `no_std` -alloc = [] +alloc = ["erased-serde/alloc", "libafl_core/alloc"] + +## Create keys that are more stable between compilations +stable_anymap = [] +serdeany_autoreg = [] [build-dependencies] rustversion = { workspace = true } @@ -41,5 +45,13 @@ rustversion = { workspace = true } # Document all features of this crate (for `cargo doc`) document-features = { workspace = true, optional = true } +libafl_core = { workspace = true } +static_assertions = { workspace = true } +serde = { workspace = true } +erased-serde = { workspace = true, default-features = false } +hashbrown = { workspace = true } +ahash = { workspace = true } +postcard = { workspace = true } + [lints] workspace = true diff --git a/crates/serde_anymap/src/serdeany.rs b/crates/serde_anymap/src/serdeany.rs index 0c712f54fd4..3e9173ce130 100644 --- a/crates/serde_anymap/src/serdeany.rs +++ b/crates/serde_anymap/src/serdeany.rs @@ -124,14 +124,12 @@ pub mod serdeany_registry { HashMap, hash_map::{Values, ValuesMut}, }; + use libafl_core::{Error, format}; use serde::{Deserialize, Serialize, de}; - use crate::{ - Error, - serdeany::{ - DeserializeCallback, DeserializeCallbackSeed, SerdeAny, TypeRepr, type_repr, - type_repr_owned, - }, + use crate::serdeany::{ + DeserializeCallback, DeserializeCallbackSeed, SerdeAny, TypeRepr, type_repr, + type_repr_owned, }; /// A [`HashMap`] that maps from [`TypeRepr`] to a deserializer and its [`TypeRepr`]. diff --git a/crates/tuple_list_ex/Cargo.toml b/crates/tuple_list_ex/Cargo.toml index fa19442c1e3..1feca3e0404 100644 --- a/crates/tuple_list_ex/Cargo.toml +++ b/crates/tuple_list_ex/Cargo.toml @@ -32,6 +32,9 @@ std = [] ## Enables all features that allocate in `no_std` alloc = [] +## Enables serde support for tuple lists +serde = ["alloc", "dep:serde"] + [build-dependencies] rustversion = { workspace = true } @@ -41,5 +44,14 @@ rustversion = { workspace = true } # Document all features of this crate (for `cargo doc`) document-features = { workspace = true, optional = true } +libafl_core = { workspace = true } + +serde = { workspace = true, default-features = false, features = [ + "derive", + "alloc", +], optional = true } +tuple_list = { workspace = true } +typeid = { workspace = true } + [lints] workspace = true diff --git a/crates/tuple_list_ex/src/lib.rs b/crates/tuple_list_ex/src/lib.rs index 18fc066187c..64ed2f22fb3 100644 --- a/crates/tuple_list_ex/src/lib.rs +++ b/crates/tuple_list_ex/src/lib.rs @@ -48,7 +48,6 @@ #[macro_use] extern crate std; #[cfg(feature = "alloc")] -#[macro_use] #[doc(hidden)] pub extern crate alloc; @@ -63,87 +62,17 @@ use core::{ ops::{Deref, DerefMut, Index, IndexMut}, }; -#[cfg(feature = "alloc")] +use libafl_core::Named; +#[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; pub use tuple_list::{TupleList, tuple_list, tuple_list_type}; -#[cfg(any(feature = "xxh3", feature = "alloc"))] -use crate::hash_std; - /// Returns if the type `T` is equal to `U`, ignoring lifetimes. #[must_use] pub fn type_eq() -> bool { typeid::of::() == typeid::of::() } -/// We need fixed names for many parts of this lib. -#[cfg(feature = "alloc")] -pub trait Named { - /// Provide the name of this element. - fn name(&self) -> &Cow<'static, str>; -} - -#[cfg(feature = "alloc")] -impl Named for () { - #[inline] - fn name(&self) -> &Cow<'static, str> { - static NAME: Cow<'static, str> = Cow::Borrowed("()"); - &NAME - } -} - -/// Has a length field -pub trait HasLen { - /// The length - fn len(&self) -> usize; - - /// Returns `true` if it has no elements. - fn is_empty(&self) -> bool { - self.len() == 0 - } -} - -#[cfg(feature = "alloc")] -impl HasLen for Vec { - #[inline] - fn len(&self) -> usize { - Vec::::len(self) - } -} - -impl HasLen for &mut T { - fn len(&self) -> usize { - self.deref().len() - } -} - -impl HasLen for (Head, Tail) -where - Tail: HasLen, -{ - #[inline] - fn len(&self) -> usize { - self.1.len() + 1 - } -} - -impl HasLen for (Tail,) -where - Tail: HasLen, -{ - #[inline] - fn len(&self) -> usize { - self.0.len() - } -} - -impl HasLen for () { - #[inline] - fn len(&self) -> usize { - 0 - } -} - /// Borrow each member of the tuple pub trait SplitBorrow<'a> { /// The Resulting [`TupleList`], of an [`SplitBorrow::borrow()`] call @@ -227,58 +156,6 @@ where const LEN: usize = 1 + Tail::LEN; } -/// Finds the `const_name` and `name_id` -pub trait HasNameId { - /// Gets the `const_name` for this entry - fn const_name(&self) -> &'static str; - - /// Gets the `name_id` for this entry - fn name_id(&self) -> u64 { - hash_std(self.const_name().as_bytes()) - } -} - -/// Gets the id and `const_name` for the given index in a tuple -pub trait HasNameIdTuple: HasConstLen { - /// Gets the `const_name` for the entry at the given index - fn const_name_for(&self, index: usize) -> Option<&'static str>; - - /// Gets the `name_id` for the entry at the given index - fn name_id_for(&self, index: usize) -> Option; -} - -impl HasNameIdTuple for () { - fn const_name_for(&self, _index: usize) -> Option<&'static str> { - None - } - - fn name_id_for(&self, _index: usize) -> Option { - None - } -} - -impl HasNameIdTuple for (Head, Tail) -where - Head: HasNameId, - Tail: HasNameIdTuple, -{ - fn const_name_for(&self, index: usize) -> Option<&'static str> { - if index == 0 { - Some(self.0.const_name()) - } else { - self.1.const_name_for(index - 1) - } - } - - fn name_id_for(&self, index: usize) -> Option { - if index == 0 { - Some(self.0.name_id()) - } else { - self.1.name_id_for(index - 1) - } - } -} - /// Returns the first element with the given type pub trait MatchFirstType { /// Returns the first element with the given type as borrow, or [`None`] @@ -577,11 +454,11 @@ pub trait Handled: Named { impl Handled for N where N: Named {} /// Object with the type T and the name associated with its concrete value -#[derive(Serialize, Deserialize)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg(feature = "alloc")] pub struct Handle { name: Cow<'static, str>, - #[serde(skip)] + #[cfg_attr(feature = "serde", serde(skip))] phantom: PhantomData, } From 6aa3f866eb216eabf12f7fe7d870253d6cbd3dd4 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Tue, 15 Jul 2025 01:57:03 +0200 Subject: [PATCH 07/18] mroe fix --- crates/libafl_bolts/Cargo.toml | 5 ----- crates/ll_mp/src/lib.rs | 1 - 2 files changed, 6 deletions(-) diff --git a/crates/libafl_bolts/Cargo.toml b/crates/libafl_bolts/Cargo.toml index 9c25205d1dd..d2926079878 100644 --- a/crates/libafl_bolts/Cargo.toml +++ b/crates/libafl_bolts/Cargo.toml @@ -150,11 +150,6 @@ shmem_providers = { workspace = true } static_assertions = { workspace = true } tuple_list_ex = { workspace = true } typeid = { workspace = true } -shmem_providers = { workspace = true } -fast_rands = { workspace = true } -no_std_time = { workspace = true } - -tuple_list = { version = "0.1.3" } ahash = { workspace = true, optional = true } # The hash function already used in hashbrown backtrace = { workspace = true, default-features = true, optional = true } # Used to get the stacktrace in StacktraceObserver diff --git a/crates/ll_mp/src/lib.rs b/crates/ll_mp/src/lib.rs index a1adf1c93a9..99e167363f6 100644 --- a/crates/ll_mp/src/lib.rs +++ b/crates/ll_mp/src/lib.rs @@ -104,7 +104,6 @@ Check out the `llmp_test` example in ./examples, or build it with `cargo run --e #[cfg(feature = "std")] #[macro_use] extern crate std; -#[macro_use] #[doc(hidden)] pub extern crate alloc; From 698e6d0e115aedaad855df976ea4706eda8c22d8 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Tue, 15 Jul 2025 02:00:22 +0200 Subject: [PATCH 08/18] Move rust-toolchain file to toml --- fuzzers/fuzz_anything/baby_no_std/Cargo.lock | 86 ++++++++++++------- .../fuzz_anything/baby_no_std/rust-toolchain | 1 - .../baby_no_std/rust-toolchain.toml | 2 + 3 files changed, 57 insertions(+), 32 deletions(-) delete mode 100644 fuzzers/fuzz_anything/baby_no_std/rust-toolchain create mode 100644 fuzzers/fuzz_anything/baby_no_std/rust-toolchain.toml diff --git a/fuzzers/fuzz_anything/baby_no_std/Cargo.lock b/fuzzers/fuzz_anything/baby_no_std/Cargo.lock index 20945aa8db2..526ce7b47e0 100644 --- a/fuzzers/fuzz_anything/baby_no_std/Cargo.lock +++ b/fuzzers/fuzz_anything/baby_no_std/Cargo.lock @@ -28,13 +28,13 @@ checksum = "825297538d77367557b912770ca3083f778a196054b3ee63b22673c4a3cae0a5" [[package]] name = "autocfg" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "baby_no_std" -version = "0.15.2" +version = "0.15.3" dependencies = [ "libafl", "libafl_bolts", @@ -57,15 +57,18 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" [[package]] name = "cobs" -version = "0.2.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" +checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" +dependencies = [ + "thiserror", +] [[package]] name = "const_format" @@ -127,7 +130,7 @@ dependencies = [ [[package]] name = "libafl" -version = "0.15.2" +version = "0.15.3" dependencies = [ "ahash", "arbitrary-int", @@ -151,7 +154,7 @@ dependencies = [ [[package]] name = "libafl_bolts" -version = "0.15.2" +version = "0.15.3" dependencies = [ "ahash", "erased-serde", @@ -174,9 +177,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.172" +version = "0.2.174" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" [[package]] name = "libm" @@ -192,9 +195,9 @@ checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "mach2" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" +checksum = "d640282b302c0bb0a2a8e0233ead9035e3bed871f0b7e81fe4a1ec829765db44" dependencies = [ "libc", ] @@ -220,18 +223,19 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" +checksum = "a973b4e44ce6cad84ce69d797acf9a044532e4184c4f267913d1b546a0727b7a" dependencies = [ "num_enum_derive", + "rustversion", ] [[package]] name = "num_enum_derive" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" +checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d" dependencies = [ "proc-macro2", "quote", @@ -246,9 +250,9 @@ checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "postcard" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "170a2601f67cc9dba8edd8c4870b15f71a6a2dc196daec8c83f72b59dff628a8" +checksum = "6c1de96e20f51df24ca73cafcc4690e044854d803259db27a00a461cb3b9d17a" dependencies = [ "cobs", "embedded-io 0.4.0", @@ -302,9 +306,9 @@ dependencies = [ [[package]] name = "static-alloc" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b2975e035ce16539eecee08d7c6e5626ca26f299c6e90af343b302c6dd2e61e" +checksum = "2e1e06c73b06b04d730f68ecb5f805e86b8d509cf80072a28128160025fbf928" dependencies = [ "alloc-traits", ] @@ -317,15 +321,35 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "syn" -version = "2.0.101" +version = "2.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "thiserror" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tuple_list" version = "0.1.3" @@ -425,9 +449,9 @@ dependencies = [ [[package]] name = "windows-link" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" [[package]] name = "windows-result" @@ -449,9 +473,9 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.53.0" +version = "0.53.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" +checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", @@ -513,18 +537,18 @@ checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" [[package]] name = "zerocopy" -version = "0.8.25" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.25" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" dependencies = [ "proc-macro2", "quote", diff --git a/fuzzers/fuzz_anything/baby_no_std/rust-toolchain b/fuzzers/fuzz_anything/baby_no_std/rust-toolchain deleted file mode 100644 index bf867e0ae5b..00000000000 --- a/fuzzers/fuzz_anything/baby_no_std/rust-toolchain +++ /dev/null @@ -1 +0,0 @@ -nightly diff --git a/fuzzers/fuzz_anything/baby_no_std/rust-toolchain.toml b/fuzzers/fuzz_anything/baby_no_std/rust-toolchain.toml new file mode 100644 index 00000000000..5d56faf9ae0 --- /dev/null +++ b/fuzzers/fuzz_anything/baby_no_std/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly" From 52cb4043ef85a6e078b6b9bf934b0b14062dd236 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Tue, 15 Jul 2025 12:20:41 +0200 Subject: [PATCH 09/18] builds oO --- Cargo.toml | 1 + crates/core_affinity2/Cargo.toml | 9 +- crates/exceptional/src/lib.rs | 3 - crates/fast_rands/Cargo.toml | 2 +- crates/libafl/Cargo.toml | 128 ++-- .../nautilus/grammartec/recursion_info.rs | 6 +- crates/libafl/src/events/llmp/restarting.rs | 9 +- crates/libafl/src/mutators/havoc_mutations.rs | 5 +- crates/libafl/src/observers/stacktrace.rs | 25 +- crates/libafl_bolts/Cargo.toml | 34 +- crates/libafl_bolts/src/lib.rs | 9 +- crates/libafl_bolts/src/os.rs | 8 + crates/libafl_sugar/src/forkserver.rs | 4 +- crates/libafl_targets/src/cmps/mod.rs | 3 +- crates/libafl_targets/src/coverage.rs | 2 +- crates/libafl_targets/src/drcov.rs | 2 +- crates/libafl_targets/src/forkserver.rs | 6 +- crates/ll_mp/Cargo.toml | 15 +- crates/ll_mp/src/lib.rs | 14 +- crates/minibsod/Cargo.toml | 13 +- crates/minibsod/src/lib.rs | 2 +- crates/no_std_time/Cargo.toml | 2 +- crates/ownedref/Cargo.toml | 2 +- crates/serde_anymap/Cargo.toml | 11 +- crates/serde_anymap/src/lib.rs | 4 + crates/serde_anymap/src/serdeany.rs | 2 +- crates/tuple_list_ex/Cargo.toml | 5 +- crates/tuple_list_ex/src/lib.rs | 12 +- .../c_code_with_fork_executor/src/main.rs | 8 +- .../rust_code_with_fork_executor/src/main.rs | 9 +- .../fuzzbench_forkserver/src/main.rs | 2 +- .../fuzzbench_forkserver_cmplog/src/main.rs | 2 +- .../fuzzbench_forkserver_sand/src/main.rs | 2 +- fuzzers/forkserver/libafl-fuzz/src/fuzzer.rs | 2 +- fuzzers/fuzz_anything/baby_no_std/Cargo.lock | 554 +++++++++++++++++- .../baby_fuzzer_nautilus/Cargo.lock | 229 ++++++-- 36 files changed, 929 insertions(+), 217 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a5ec71af09c..6544d5598c6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -129,6 +129,7 @@ capstone = "0.13.0" # Disassembler used in libafl_unicorn to provide disassembly cc = "1.1.21" clap = "4.5.18" cmake = "0.1.51" +ctor = "0.4.0" document-features = "0.2.10" erased-serde = { version = "0.4.5", default-features = false } # erased serde fastbloom = { version = "0.12.0", default-features = false } diff --git a/crates/core_affinity2/Cargo.toml b/crates/core_affinity2/Cargo.toml index 02a09161855..d6c657a37bb 100644 --- a/crates/core_affinity2/Cargo.toml +++ b/crates/core_affinity2/Cargo.toml @@ -20,15 +20,8 @@ features = ["document-features"] all-features = true [features] -default = ["std"] document-features = ["dep:document-features"] -#! # Feature Flags -#! ### General Features - -## Enables features that need rust's `std` lib to work, like print, env, ... support -std = ["libafl_core/std"] - [build-dependencies] rustversion = { workspace = true } @@ -38,7 +31,7 @@ rustversion = { workspace = true } # Document all features of this crate (for `cargo doc`) document-features = { workspace = true, optional = true } serde = { workspace = true, features = ["alloc", "derive"] } -libafl_core = { workspace = true, features = ["alloc"] } +libafl_core = { workspace = true, features = ["alloc", "std"] } libc = { workspace = true } [lints] diff --git a/crates/exceptional/src/lib.rs b/crates/exceptional/src/lib.rs index 5f3cfb2933d..42200d19c6e 100644 --- a/crates/exceptional/src/lib.rs +++ b/crates/exceptional/src/lib.rs @@ -58,6 +58,3 @@ pub mod unix_signals; #[cfg(all(windows, feature = "std"))] #[expect(missing_docs, overflowing_literals)] pub mod windows_exceptions; - -#[cfg(unix)] -pub use unix_signals::CTRL_C_EXIT; diff --git a/crates/fast_rands/Cargo.toml b/crates/fast_rands/Cargo.toml index 36abc98cae0..d67c2c4398d 100644 --- a/crates/fast_rands/Cargo.toml +++ b/crates/fast_rands/Cargo.toml @@ -27,7 +27,7 @@ document-features = ["dep:document-features"] #! ### General Features ## Enables features that need rust's `std` lib to work, like print, env, ... support -std = [] +std = ["alloc"] ## Enables all features that allocate in `no_std` alloc = [] diff --git a/crates/libafl/Cargo.toml b/crates/libafl/Cargo.toml index 1863fcdc909..af18329c5d9 100644 --- a/crates/libafl/Cargo.toml +++ b/crates/libafl/Cargo.toml @@ -31,19 +31,19 @@ workspace = true [features] default = [ - "std", "derive", + "errors_backtrace", + "fork", + "gzip", + "libafl_bolts/xxh3", + "llmp_broker_timeouts", "llmp_compression", "llmp_small_maps", - "llmp_broker_timeouts", "rand_trait", - "fork", - "gzip", "regex", "serdeany_autoreg", - "libafl_bolts/xxh3", "simd", - "errors_backtrace", + "std", ] document-features = ["dep:document-features"] @@ -52,19 +52,20 @@ document-features = ["dep:document-features"] ## Enables features that need rust's `std` lib to work, like print, env, ... support std = [ + "backtrace", + "bincode", + "dep:nix", + "fastbloom", + "fs2", + "libafl_bolts/std", + "ll_mp/std", "serde_json", "serde_json/std", - "dep:nix", "serde/std", - "bincode", - "wait-timeout", - "uuid", - "backtrace", "serial_test", - "libafl_bolts/std", "typed-builder", - "fastbloom", - "fs2", + "uuid", + "wait-timeout", ] ## Tracks the Feedbacks and the Objectives that were interesting for a Testcase @@ -218,51 +219,66 @@ static_assertions = { workspace = true } [dependencies] libafl_bolts = { workspace = true, features = ["alloc"] } +libafl_core = { workspace = true } libafl_derive = { workspace = true, default-features = true, optional = true } libafl_intelpt = { workspace = true, default-features = true, optional = true } ll_mp = { workspace = true } -rustversion = { workspace = true } -tuple_list = { workspace = true } +ahash = { workspace = true } # The hash function already used in hashbrown +arbitrary-int = { workspace = true } +arrayvec = { version = "0.7.6", optional = true, default-features = false } # used for fixed-len collects +async-std = { version = "1.13.0", features = ["attributes"], optional = true } +backtrace = { workspace = true, optional = true } # Used to get the stacktrace in StacktraceObserver +bincode = { version = "2.0.1", optional = true, features = ["serde"] } +bitbybit = { workspace = true } +bitvec = { version = "1.0.1", optional = true, features = [ + "serde", +] } # used for string range storage +cadence = { version = "1.5.0", optional = true } # For the statsd monitor +clap = { workspace = true, optional = true } +const_format = "0.2.33" # used for providing helpful compiler output +const_panic = { version = "0.2.9", default-features = false } # similarly, for formatting const panic output +crossterm = { version = "0.29.0", optional = true } +enumflags2 = { version = "0.7.10", optional = true } +fastbloom = { workspace = true, optional = true } +fs2 = { workspace = true, optional = true } # used by OnDisk Corpus for file locking +futures = { version = "0.3.30", optional = true } hashbrown = { workspace = true, features = [ "serde", "ahash", ], default-features = false } # A faster hashmap, nostd compatible -num-traits = { workspace = true, default-features = false } -serde = { workspace = true, features = ["alloc"] } # serialization lib -postcard = { workspace = true } # no_std compatible serde serialization format -bincode = { version = "2.0.1", optional = true, features = ["serde"] } -bitbybit = { workspace = true } -arbitrary-int = { workspace = true } -ahash = { workspace = true } # The hash function already used in hashbrown +libcasr = { version = "2.12.1", optional = true } +libm = "0.2.8" +log = { workspace = true } meminterval = { workspace = true, features = ["serde"] } -backtrace = { workspace = true, optional = true } # Used to get the stacktrace in StacktraceObserver -typed-builder = { workspace = true, optional = true } # Implement the builder pattern at compiletime -send_wrapper = { version = "0.6.0", optional = true } # To move data between threads - -serde_json = { workspace = true, optional = true, default-features = false, features = [ - "alloc", -] } +mlua = { version = "0.10.3", features = [ + "lua54", + "vendored", + "macros", +], optional = true } # For Lua Mutators / TODO: macros is not needed/ a temporary fix for docsrs, see nix = { workspace = true, optional = true, features = [ "signal", "ptrace", "personality", "fs", ] } -regex = { workspace = true, optional = true } -uuid = { workspace = true, optional = true, features = ["serde", "v4"] } -libm = "0.2.8" +num_enum = { workspace = true, optional = true } +num-traits = { workspace = true, default-features = false } +postcard = { workspace = true } # no_std compatible serde serialization format +prometheus-client = { version = "0.23.0", optional = true } # For the prometheus monitor +pyo3 = { workspace = true, optional = true } ratatui = { version = "0.29.0", default-features = false, features = [ 'crossterm', ], optional = true } # Commandline rendering, for TUI Monitor -crossterm = { version = "0.29.0", optional = true } - -cadence = { version = "1.5.0", optional = true } # For the statsd monitor -prometheus-client = { version = "0.23.0", optional = true } # For the prometheus monitor +regex = { workspace = true, optional = true } +regex-syntax = { version = "0.8.4", optional = true } # For nautilus +rustversion = { workspace = true } +send_wrapper = { version = "0.6.0", optional = true } # To move data between threads +serde = { workspace = true, features = ["alloc"] } # serialization lib +serde_json = { workspace = true, optional = true, default-features = false, features = [ + "alloc", +] } tide = { version = "0.16.0", optional = true } -async-std = { version = "1.13.0", features = ["attributes"], optional = true } -futures = { version = "0.3.30", optional = true } -log = { workspace = true } tokio = { version = "1.40.0", optional = true, features = [ "sync", "net", @@ -272,26 +288,11 @@ tokio = { version = "1.40.0", optional = true, features = [ "rt-multi-thread", "time", ] } # used for TCP Event Manager and multi-machine -enumflags2 = { version = "0.7.10", optional = true } - +tuple_list = { workspace = true } +typed-builder = { workspace = true, optional = true } # Implement the builder pattern at compiletime +uuid = { workspace = true, optional = true, features = ["serde", "v4"] } wait-timeout = { version = "0.2.0", optional = true } # used by CommandExecutor to wait for child process -libcasr = { version = "2.12.1", optional = true } - -bitvec = { version = "1.0.1", optional = true, features = [ - "serde", -] } # used for string range storage - -arrayvec = { version = "0.7.6", optional = true, default-features = false } # used for fixed-len collects - -const_format = "0.2.33" # used for providing helpful compiler output -const_panic = { version = "0.2.9", default-features = false } # similarly, for formatting const panic output - -pyo3 = { workspace = true, optional = true } -regex-syntax = { version = "0.8.4", optional = true } # For nautilus - -fs2 = { workspace = true, optional = true } # used by OnDisk Corpus for file locking - # optional-dev deps (change when target.'cfg(accessible(::std))'.test-dependencies will be stable) serial_test = { workspace = true, optional = true, default-features = false, features = [ "logging", @@ -299,17 +300,6 @@ serial_test = { workspace = true, optional = true, default-features = false, fea # Document all features of this crate (for `cargo doc`) document-features = { workspace = true, optional = true } -# Optional -clap = { workspace = true, optional = true } -num_enum = { workspace = true, optional = true } -fastbloom = { workspace = true, optional = true } -# For Lua Mutators -# TODO: macros is not needed/ a temporary fix for docsrs, see -mlua = { version = "0.10.3", features = [ - "lua54", - "vendored", - "macros", -], optional = true } [target.'cfg(unix)'.dependencies] libc = { workspace = true } # For (*nix) libc diff --git a/crates/libafl/src/common/nautilus/grammartec/recursion_info.rs b/crates/libafl/src/common/nautilus/grammartec/recursion_info.rs index 549e1302ef1..db756dacc69 100644 --- a/crates/libafl/src/common/nautilus/grammartec/recursion_info.rs +++ b/crates/libafl/src/common/nautilus/grammartec/recursion_info.rs @@ -89,7 +89,11 @@ impl RecursionInfo { for v in &mut weights { *v /= norm; } - LoadedDiceSampler::new(&weights) + LoadedDiceSampler::new(&weights).map_err(|err| { + Error::illegal_argument(format!( + "Could not crate LoadedDiceSampler for depths {depths:?}: {err:?}" + )) + }) } pub fn get_random_recursion_pair(&mut self, rand: &mut R) -> (NodeId, NodeId) { diff --git a/crates/libafl/src/events/llmp/restarting.rs b/crates/libafl/src/events/llmp/restarting.rs index 154e779ca55..24220d1aae7 100644 --- a/crates/libafl/src/events/llmp/restarting.rs +++ b/crates/libafl/src/events/llmp/restarting.rs @@ -16,17 +16,14 @@ use core::{ #[cfg(feature = "std")] use std::net::TcpStream; +#[cfg(feature = "std")] +use libafl_bolts::llmp::{TcpRequest, TcpResponse, recv_tcp_msg, send_tcp_msg}; #[cfg(any(windows, not(feature = "fork")))] 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::{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, @@ -43,6 +40,8 @@ use libafl_bolts::{ staterestore::StateRestorer, tuples::tuple_list, }; +#[cfg(feature = "std")] +use libafl_core::IP_LOCALHOST; use serde::{Serialize, de::DeserializeOwned}; use typed_builder::TypedBuilder; diff --git a/crates/libafl/src/mutators/havoc_mutations.rs b/crates/libafl/src/mutators/havoc_mutations.rs index f03b5e903be..5edd85a2b56 100644 --- a/crates/libafl/src/mutators/havoc_mutations.rs +++ b/crates/libafl/src/mutators/havoc_mutations.rs @@ -1,8 +1,7 @@ //! [`crate::mutators::Mutator`] collection equivalent to AFL++'s havoc mutations -use libafl_bolts::{ - map_tuple_list_type, merge_tuple_list_type, - tuples::{Map, Merge, tuple_list, tuple_list_type}, +use libafl_bolts::tuples::{ + Map, Merge, map_tuple_list_type, merge_tuple_list_type, tuple_list, tuple_list_type, }; use crate::mutators::{ diff --git a/crates/libafl/src/observers/stacktrace.rs b/crates/libafl/src/observers/stacktrace.rs index 77ca29a8c8c..0046a171131 100644 --- a/crates/libafl/src/observers/stacktrace.rs +++ b/crates/libafl/src/observers/stacktrace.rs @@ -16,7 +16,7 @@ use std::{ }; use backtrace::Backtrace; -use libafl_bolts::{Named, ownedref::OwnedRefMut}; +use libafl_bolts::{Named, ownedref::OwnedRefMut, shmem::ShMem}; #[allow(unused_imports)] // expect breaks here for some reason #[cfg(feature = "casr")] use libcasr::{ @@ -156,6 +156,29 @@ impl<'a> BacktraceObserver<'a> { } } + /// [`BacktraceObserver`], with the `backtrace_hash` pointing to the given [`ShMem`]. + /// + /// # Panics + /// Panics if the given shared mem is smaller than `sizeof::()` + /// + /// # Safety + /// The shared memory needs to point to a valid u64 hash int. + /// Any use of this [`OwnedRefMut`] will dereference a pointer to the given shared memory accordingly + pub unsafe fn from_shmem( + observer_name: S, + shmem: &mut SHM, + harness_type: HarnessType, + ) -> Self + where + S: Into>, + { + Self::new( + observer_name, + unsafe { OwnedRefMut::from_mut_ptr(shmem.as_mut_ptr_of().unwrap()) }, + harness_type, + ) + } + /// Creates a new [`BacktraceObserver`] with the given name, owning a new `backtrace_hash` variable. #[must_use] pub fn owned(observer_name: S, harness_type: HarnessType) -> Self diff --git a/crates/libafl_bolts/Cargo.toml b/crates/libafl_bolts/Cargo.toml index d2926079878..ad2e7d6fc41 100644 --- a/crates/libafl_bolts/Cargo.toml +++ b/crates/libafl_bolts/Cargo.toml @@ -27,12 +27,12 @@ all-features = true [features] default = [ - "std", + "alloc", "derive", - "rand_trait", "gzip", + "rand_trait", "serdeany_autoreg", - "alloc", + "std", "xxh3", ] document-features = ["dep:document-features"] @@ -44,22 +44,23 @@ document-features = ["dep:document-features"] std = [ "alloc", "backtrace", + "backtrace", + "fast_rands/std", "hostname", "libafl_core/nix", + "libafl_core/nix", + "libafl_core/std", "libafl_core/std", + "ll_mp/std", "nix", "no_std_time/std", "serde/std", - "libafl_core/std", - "libafl_core/nix", - "shmem_providers/std", - "uuid", - "backtrace", - "uds", "serial_test", "shmem_providers/std", "simd", "uds", + "uds", + "uuid", "uuid", ] @@ -67,8 +68,10 @@ std = [ alloc = [ "ahash", "erased-serde/alloc", + "fast_rands/alloc", "hashbrown", "libafl_core/alloc", + "ll_mp/alloc", "no_std_time/alloc", "postcard", "serde/alloc", @@ -81,7 +84,7 @@ derive = ["libafl_derive"] ## If set, libafl_bolt's `rand` implementations will implement `rand_core::CoreRng` ## and, inversely, all seedable `rand_core::RngCore` types can be used as Rng for LibAFL. -rand_trait = ["rand_core"] +rand_trait = ["fast_rands/rand_trait"] ## Will build the `pyo3` bindings python = ["pyo3", "std", "libafl_core/python"] @@ -102,7 +105,7 @@ frida_cli = ["cli"] errors_backtrace = ["backtrace"] ## Enables gzip compression in certain parts of the lib -gzip = ["miniz_oxide", "alloc"] +gzip = ["miniz_oxide", "alloc", "ll_mp/gzip"] ## Replaces `ahash` with the potentially faster [`xxh3`](https://github.com/Cyan4973/xxHash) in some parts of the lib. ## This yields a stable and fast hash, but may increase the resulting binary size slightly @@ -116,10 +119,10 @@ xxh3 = ["xxhash-rust"] ## With this feature, stored state remains deserializable across multiple compilations of LibAFL. ## The rust doc specifically states that "multiple types may map to the same type name", so it could potentially lead to bugs. ## However, we make sure that no two types with the same name ever exist. -stable_anymap = [] +stable_anymap = ["serde_anymap/stable_anymap"] ## Automatically register all `#[derive(SerdeAny)]` types at startup. -serdeany_autoreg = ["ctor"] +serdeany_autoreg = ["serde_anymap/serdeany_autoreg"] #! ### Stable SIMD features @@ -138,6 +141,7 @@ itertools = "0.14.0" [dependencies] build_id2 = { workspace = true } core_affinity2 = { workspace = true } +exceptional = { workspace = true } fast_rands = { workspace = true } libafl_core = { workspace = true, features = ["postcard"] } libafl_derive = { workspace = true, default-features = true, optional = true } @@ -148,7 +152,7 @@ ownedref = { workspace = true } serde_anymap = { workspace = true } shmem_providers = { workspace = true } static_assertions = { workspace = true } -tuple_list_ex = { workspace = true } +tuple_list_ex = { workspace = true, features = ["serde"] } typeid = { workspace = true } ahash = { workspace = true, optional = true } # The hash function already used in hashbrown @@ -157,7 +161,6 @@ clap = { workspace = true, features = [ "derive", "wrap_help", ], optional = true } # CLI parsing, for libafl_bolts::cli / the `cli` feature -ctor = { optional = true, version = "0.4.0" } erased-serde = { version = "0.4.5", default-features = false, optional = true } # erased serde hashbrown = { workspace = true, features = [ "serde", @@ -175,7 +178,6 @@ nix = { workspace = true, optional = true, default-features = false, features = num_enum = { workspace = true, default-features = false } postcard = { workspace = true, optional = true } # no_std compatible serde serialization format pyo3 = { workspace = true, optional = true, features = ["serde", "macros"] } -rand_core = { version = "0.9.0", optional = true } serde = { workspace = true, default-features = false, features = [ "derive", ] } # serialization lib diff --git a/crates/libafl_bolts/src/lib.rs b/crates/libafl_bolts/src/lib.rs index 4ea5c080093..b97f14fcf59 100644 --- a/crates/libafl_bolts/src/lib.rs +++ b/crates/libafl_bolts/src/lib.rs @@ -56,9 +56,6 @@ pub extern crate alloc; #[cfg(feature = "std")] pub use build_id2 as build_id; -#[cfg(feature = "ctor")] -#[doc(hidden)] -pub use ctor; #[cfg(feature = "alloc")] pub use serde_anymap::anymap; #[cfg(all( @@ -82,7 +79,6 @@ pub mod os; pub use serde_anymap::serdeany; #[cfg(feature = "std")] pub mod staterestore; -// TODO: reenable once ahash works in no-alloc #[cfg(any(feature = "xxh3", feature = "alloc"))] pub use tuple_list_ex as tuples; @@ -93,6 +89,9 @@ pub use argparse::*; #[cfg(feature = "std")] pub mod target_args; +pub use no_std_time::format_duration; +#[cfg(feature = "alloc")] +pub use serde_anymap::impl_serdeany; #[cfg(feature = "std")] pub use target_args::*; @@ -103,7 +102,7 @@ pub use libafl_core::{ AsIter, AsIterMut, AsSlice, AsSliceMut, ClientId, Error, HasLen, HasRefCnt, Named, Truncate, }; pub use no_std_time::current_time; -pub use ownedref; +pub use ownedref::{self, subrange}; pub use shmem_providers as shmem; /// The purpose of this module is to alleviate imports of the bolts by adding a glob import. diff --git a/crates/libafl_bolts/src/os.rs b/crates/libafl_bolts/src/os.rs index e3b5d480ec2..ad09f465811 100644 --- a/crates/libafl_bolts/src/os.rs +++ b/crates/libafl_bolts/src/os.rs @@ -15,10 +15,18 @@ use std::{ sync::OnceLock, }; +#[cfg(unix)] +pub use exceptional::unix_signals; +#[cfg(unix)] +pub use exceptional::unix_signals::CTRL_C_EXIT; +#[cfg(windows)] +pub use exceptional::windows_exceptions; use libafl_core::format; // Allow a few extra features we need for the whole module #[cfg(unix)] use libc::pid_t; +#[cfg(all(unix, feature = "std"))] +pub use shmem_providers::pipes; #[cfg(all(windows, feature = "std"))] pub use windows_exceptions::CTRL_C_EXIT; diff --git a/crates/libafl_sugar/src/forkserver.rs b/crates/libafl_sugar/src/forkserver.rs index aacbf55d985..e32fdd7ba7f 100644 --- a/crates/libafl_sugar/src/forkserver.rs +++ b/crates/libafl_sugar/src/forkserver.rs @@ -34,7 +34,6 @@ use libafl_bolts::{ AsSliceMut, StdTargetArgs, core_affinity::Cores, nonzero, - ownedref::OwnedRefMut, rands::StdRand, shmem::{ShMem, ShMemProvider, UnixShMemProvider}, tuples::{Merge, tuple_list}, @@ -271,8 +270,7 @@ impl ForkserverBytesCoverageSugar<'_> { unsafe { cmplog_shmem.write_to_env(SHM_CMPLOG_ENV_VAR).unwrap(); } - let cmpmap = - unsafe { OwnedRefMut::::from_shmem(&mut cmplog_shmem) }; + let cmpmap = unsafe { AflppCmpLogMap::from_shmem(&mut cmplog_shmem) }; let cmplog_observer = StdCmpObserver::new("cmplog", cmpmap, true); diff --git a/crates/libafl_targets/src/cmps/mod.rs b/crates/libafl_targets/src/cmps/mod.rs index fc3966667d7..b52eec3a685 100644 --- a/crates/libafl_targets/src/cmps/mod.rs +++ b/crates/libafl_targets/src/cmps/mod.rs @@ -13,8 +13,7 @@ use core::{ }; use libafl::observers::{CmpMap, CmpValues, CmplogBytes, cmp::AflppCmpLogHeader}; -use libafl_bolts::{HasLen, ownedref::OwnedRefMut}; -use libafl_core::Error; +use libafl_bolts::{Error, HasLen, ownedref::OwnedRefMut}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use shmem_providers::ShMem; pub use stages::*; diff --git a/crates/libafl_targets/src/coverage.rs b/crates/libafl_targets/src/coverage.rs index ebcf1e32898..03e7ac7bfc1 100644 --- a/crates/libafl_targets/src/coverage.rs +++ b/crates/libafl_targets/src/coverage.rs @@ -12,7 +12,7 @@ use alloc::borrow::Cow; #[cfg(any(target_os = "linux", target_vendor = "apple"))] use libafl::mutators::Tokens; #[cfg(any(target_os = "linux", target_vendor = "apple"))] -use libafl_core::Error; +use libafl_bolts::Error; use crate::{ACCOUNTING_MAP_SIZE, EDGES_MAP_ALLOCATED_SIZE, EDGES_MAP_DEFAULT_SIZE}; diff --git a/crates/libafl_targets/src/drcov.rs b/crates/libafl_targets/src/drcov.rs index c5fa5d9db6b..d51825fc5a9 100644 --- a/crates/libafl_targets/src/drcov.rs +++ b/crates/libafl_targets/src/drcov.rs @@ -12,7 +12,7 @@ use std::{ }; use hashbrown::HashSet; -use libafl_core::Error; +use libafl_bolts::Error; use rangemap::RangeMap; /// A basic block struct diff --git a/crates/libafl_targets/src/forkserver.rs b/crates/libafl_targets/src/forkserver.rs index ab24c3773ad..0c9465fef7c 100644 --- a/crates/libafl_targets/src/forkserver.rs +++ b/crates/libafl_targets/src/forkserver.rs @@ -15,8 +15,10 @@ use libafl::executors::forkserver::{ FS_NEW_OPT_SHDMEM_FUZZ, FS_NEW_VERSION_MAX, FS_OPT_ERROR, MAX_INPUT_SIZE_DEFAULT, SHM_ENV_VAR, SHM_FUZZ_ENV_VAR, SHM_FUZZ_MAP_SIZE_ENV_VAR, SHMEM_FUZZ_HDR_SIZE, }; -use libafl_bolts::os::{ChildHandle, ForkResult}; -use libafl_core::Error; +use libafl_bolts::{ + Error, + os::{ChildHandle, ForkResult}, +}; use nix::{ sys::signal::{SigHandler, Signal}, unistd::Pid, diff --git a/crates/ll_mp/Cargo.toml b/crates/ll_mp/Cargo.toml index 5ef705a3a95..d8af8cba26d 100644 --- a/crates/ll_mp/Cargo.toml +++ b/crates/ll_mp/Cargo.toml @@ -27,7 +27,7 @@ document-features = ["dep:document-features"] #! ### General Features ## Enables features that need rust's `std` lib to work, like print, env, ... support -std = ["libafl_core/std", "shmem_providers/std"] +std = ["libafl_core/std", "shmem_providers/std", "alloc"] ## Enables all features that allocate in `no_std` alloc = [ @@ -64,19 +64,20 @@ rustversion = { workspace = true } [dependencies] # Document all features of this crate (for `cargo doc`) +backtrace = { workspace = true } document-features = { workspace = true, optional = true } -miniz_oxide = { version = "0.8.0", optional = true } +exceptional = { workspace = true } hostname = { version = "0.4.0", optional = true } # Is there really no gethostname in the stdlib? -postcard = { workspace = true, optional = true } # no_std compatible serde serialization format +libafl_core = { workspace = true, features = ["serde"] } log = { workspace = true } -tuple_list = { workspace = true } -libafl_core = { workspace = true } +miniz_oxide = { version = "0.8.0", optional = true } nix = { workspace = true, features = ["socket"] } no_std_time = { workspace = true } +postcard = { workspace = true, optional = true } # no_std compatible serde serialization format serde = { workspace = true, features = ["alloc", "derive"] } -shmem_providers = { workspace = true } -exceptional = { workspace = true } serial_test = { workspace = true } +shmem_providers = { workspace = true } +tuple_list = { workspace = true } [[example]] name = "llmp_test" diff --git a/crates/ll_mp/src/lib.rs b/crates/ll_mp/src/lib.rs index 99e167363f6..b67c2d83fd1 100644 --- a/crates/ll_mp/src/lib.rs +++ b/crates/ll_mp/src/lib.rs @@ -101,19 +101,15 @@ Check out the `llmp_test` example in ./examples, or build it with `cargo run --e ) )] +extern crate alloc; #[cfg(feature = "std")] -#[macro_use] extern crate std; -#[doc(hidden)] -pub extern crate alloc; #[cfg(feature = "std")] use alloc::boxed::Box; #[cfg(feature = "std")] use alloc::string::ToString; -#[cfg(feature = "alloc")] -use alloc::vec; -use alloc::{string::String, vec::Vec}; +use alloc::{string::String, vec, vec::Vec}; #[cfg(feature = "std")] use core::net::SocketAddr; #[cfg(not(target_pointer_width = "64"))] @@ -327,6 +323,7 @@ pub enum TcpRequest { }, } +#[cfg(feature = "std")] impl TryFrom<&Vec> for TcpRequest { type Error = Error; @@ -335,6 +332,7 @@ impl TryFrom<&Vec> for TcpRequest { } } +#[cfg(feature = "std")] impl TryFrom> for TcpRequest { type Error = Error; @@ -356,6 +354,7 @@ pub struct TcpRemoteNewMessage { payload: Vec, } +#[cfg(feature = "std")] impl TryFrom<&Vec> for TcpRemoteNewMessage { type Error = Error; @@ -364,6 +363,7 @@ impl TryFrom<&Vec> for TcpRemoteNewMessage { } } +#[cfg(feature = "std")] impl TryFrom> for TcpRemoteNewMessage { type Error = Error; @@ -400,6 +400,7 @@ pub enum TcpResponse { }, } +#[cfg(feature = "std")] impl TryFrom<&Vec> for TcpResponse { type Error = Error; @@ -408,6 +409,7 @@ impl TryFrom<&Vec> for TcpResponse { } } +#[cfg(feature = "std")] impl TryFrom> for TcpResponse { type Error = Error; diff --git a/crates/minibsod/Cargo.toml b/crates/minibsod/Cargo.toml index 3518a1650c2..80091363a2a 100644 --- a/crates/minibsod/Cargo.toml +++ b/crates/minibsod/Cargo.toml @@ -20,18 +20,8 @@ features = ["document-features"] all-features = true [features] -default = ["std", "alloc"] document-features = ["dep:document-features"] -#! # Feature Flags -#! ### General Features - -## Enables features that need rust's `std` lib to work, like print, env, ... support -std = [] - -## Enables all features that allocate in `no_std` -alloc = [] - [build-dependencies] rustversion = { workspace = true } @@ -40,9 +30,8 @@ rustversion = { workspace = true } [dependencies] # Document all features of this crate (for `cargo doc`) document-features = { workspace = true, optional = true } -backtrace = { workspace = true } libc = { workspace = true } -exceptional = { workspace = true } +exceptional = { workspace = true, features = ["alloc"] } [target.'cfg(target_vendor = "apple")'.dependencies] mach2 = "0.4.2" diff --git a/crates/minibsod/src/lib.rs b/crates/minibsod/src/lib.rs index 03400a1a9f5..ac39b6183f5 100644 --- a/crates/minibsod/src/lib.rs +++ b/crates/minibsod/src/lib.rs @@ -1166,7 +1166,7 @@ pub fn generate_minibsod( writeln!(writer, "Received signal {signal}")?; } writeln!(writer, "{:━^100}", " BACKTRACE ")?; - writeln!(writer, "{:?}", backtrace::Backtrace::new())?; + writeln!(writer, "{:?}", std::backtrace::Backtrace::force_capture())?; writeln!(writer, "{:━^100}", " MAPS ")?; write_minibsod(writer) } diff --git a/crates/no_std_time/Cargo.toml b/crates/no_std_time/Cargo.toml index 605680c0b14..514d7de4069 100644 --- a/crates/no_std_time/Cargo.toml +++ b/crates/no_std_time/Cargo.toml @@ -27,7 +27,7 @@ document-features = ["dep:document-features"] #! ### General Features ## Enables features that need rust's `std` lib to work, like print, env, ... support -std = [] +std = ["alloc"] ## Enables all features that allocate in `no_std` alloc = [] diff --git a/crates/ownedref/Cargo.toml b/crates/ownedref/Cargo.toml index 4fee6ed3b9c..d6b564f5f24 100644 --- a/crates/ownedref/Cargo.toml +++ b/crates/ownedref/Cargo.toml @@ -27,7 +27,7 @@ document-features = ["dep:document-features"] #! ### General Features ## Enables features that need rust's `std` lib to work, like print, env, ... support -std = [] +std = ["alloc"] ## Enables all features that allocate in `no_std` alloc = [] diff --git a/crates/serde_anymap/Cargo.toml b/crates/serde_anymap/Cargo.toml index 80020ec3eaa..7a476bd94e9 100644 --- a/crates/serde_anymap/Cargo.toml +++ b/crates/serde_anymap/Cargo.toml @@ -34,7 +34,7 @@ alloc = ["erased-serde/alloc", "libafl_core/alloc"] ## Create keys that are more stable between compilations stable_anymap = [] -serdeany_autoreg = [] +serdeany_autoreg = ["ctor"] [build-dependencies] rustversion = { workspace = true } @@ -45,13 +45,14 @@ rustversion = { workspace = true } # Document all features of this crate (for `cargo doc`) document-features = { workspace = true, optional = true } -libafl_core = { workspace = true } -static_assertions = { workspace = true } -serde = { workspace = true } +ahash = { workspace = true } +ctor = { workspace = true, optional = true } erased-serde = { workspace = true, default-features = false } hashbrown = { workspace = true } -ahash = { workspace = true } +libafl_core = { workspace = true } postcard = { workspace = true } +serde = { workspace = true } +static_assertions = { workspace = true } [lints] workspace = true diff --git a/crates/serde_anymap/src/lib.rs b/crates/serde_anymap/src/lib.rs index a671429e28e..354df44af3e 100644 --- a/crates/serde_anymap/src/lib.rs +++ b/crates/serde_anymap/src/lib.rs @@ -50,5 +50,9 @@ extern crate std; #[doc(hidden)] pub extern crate alloc; +#[cfg(feature = "serdeany_autoreg")] +#[doc(hidden)] +pub use ctor; + pub mod anymap; pub mod serdeany; diff --git a/crates/serde_anymap/src/serdeany.rs b/crates/serde_anymap/src/serdeany.rs index 3e9173ce130..bbed4ac0b75 100644 --- a/crates/serde_anymap/src/serdeany.rs +++ b/crates/serde_anymap/src/serdeany.rs @@ -24,7 +24,7 @@ pub type TypeRepr = u128; pub type TypeRepr = Cow<'static, str>; /// Error string when no types at all have been registered yet. -pub(crate) const ERR_EMPTY_TYPES_REGISTER: &str = "Empty types registry. Please enable the `serdeany_autoreg` feature in libafl_bolts or register all required types manually using RegistryBuilder::register()."; +pub(crate) const ERR_EMPTY_TYPES_REGISTER: &str = "Empty types registry. Please enable the `serdeany_autoreg` feature for serde_anymap or register all required types manually using RegistryBuilder::register()."; #[cfg(not(feature = "stable_anymap"))] fn type_repr() -> TypeRepr diff --git a/crates/tuple_list_ex/Cargo.toml b/crates/tuple_list_ex/Cargo.toml index 1feca3e0404..d13ef86759b 100644 --- a/crates/tuple_list_ex/Cargo.toml +++ b/crates/tuple_list_ex/Cargo.toml @@ -27,10 +27,10 @@ document-features = ["dep:document-features"] #! ### General Features ## Enables features that need rust's `std` lib to work, like print, env, ... support -std = [] +std = ["alloc"] ## Enables all features that allocate in `no_std` -alloc = [] +alloc = ["ownedref"] ## Enables serde support for tuple lists serde = ["alloc", "dep:serde"] @@ -52,6 +52,7 @@ serde = { workspace = true, default-features = false, features = [ ], optional = true } tuple_list = { workspace = true } typeid = { workspace = true } +ownedref = { workspace = true, optional = true } [lints] workspace = true diff --git a/crates/tuple_list_ex/src/lib.rs b/crates/tuple_list_ex/src/lib.rs index 64ed2f22fb3..7ff1a8f63f7 100644 --- a/crates/tuple_list_ex/src/lib.rs +++ b/crates/tuple_list_ex/src/lib.rs @@ -793,7 +793,7 @@ macro_rules! tuple_for_each_mut { #[macro_export] macro_rules! map_tuple_list_type { ($Tuple:ty, $Mapper:ty) => { - <$Tuple as $crate::tuples::Map<$Mapper>>::MapResult + <$Tuple as $crate::Map<$Mapper>>::MapResult }; } @@ -828,13 +828,13 @@ macro_rules! merge_tuple_list_type { // Base case: when only two types are provided, apply the Merge trait directly ($Type1:ty, $Type2:ty) => { - <$Type1 as $crate::tuples::Merge<$Type2>>::MergeResult + <$Type1 as $crate::Merge<$Type2>>::MergeResult }; // Recursive case: when more than two types are provided ($Type1:ty, $Type2:ty, $( $rest:ty ),+) => { merge_tuple_list_type!( - <$Type1 as $crate::tuples::Merge<$Type2>>::MergeResult, + <$Type1 as $crate::Merge<$Type2>>::MergeResult, $( $rest ),+ ) }; @@ -873,11 +873,11 @@ impl PlusOne for (Head, Tail) where mod test { use core::marker::PhantomData; + #[cfg(feature = "alloc")] + use ownedref::OwnedMutSlice; use tuple_list::{tuple_list, tuple_list_type}; - #[cfg(feature = "alloc")] - use crate::ownedref::OwnedMutSlice; - use crate::tuples::{Map, MappingFunctor, Merge, type_eq}; + use crate::{Map, MappingFunctor, Merge, type_eq}; #[test] // for type name tests diff --git a/fuzzers/baby/backtrace_baby_fuzzers/c_code_with_fork_executor/src/main.rs b/fuzzers/baby/backtrace_baby_fuzzers/c_code_with_fork_executor/src/main.rs index f840803134e..20062146498 100644 --- a/fuzzers/baby/backtrace_baby_fuzzers/c_code_with_fork_executor/src/main.rs +++ b/fuzzers/baby/backtrace_baby_fuzzers/c_code_with_fork_executor/src/main.rs @@ -55,11 +55,13 @@ pub fn main() { }; // Create a stacktrace observer let mut bt = shmem_provider.new_on_shmem::>(None).unwrap(); - let bt_observer = BacktraceObserver::new( + // # Safety + // We just created the shmem and it's large enough. + let bt_observer = unsafe { BacktraceObserver::from_shmem( "BacktraceObserver", - unsafe { OwnedRefMut::from_shmem(&mut bt) }, + &mut bt, libafl::observers::HarnessType::Child, - ); + )}; // Feedback to rate the interestingness of an input, obtained by ANDing the interestingness of both feedbacks let mut feedback = MaxMapFeedback::new(&observer); diff --git a/fuzzers/baby/backtrace_baby_fuzzers/rust_code_with_fork_executor/src/main.rs b/fuzzers/baby/backtrace_baby_fuzzers/rust_code_with_fork_executor/src/main.rs index 43c3c9a5019..ed6336c646e 100644 --- a/fuzzers/baby/backtrace_baby_fuzzers/rust_code_with_fork_executor/src/main.rs +++ b/fuzzers/baby/backtrace_baby_fuzzers/rust_code_with_fork_executor/src/main.rs @@ -67,12 +67,13 @@ pub fn main() { // Create an observation channel using the signals map let observer = unsafe { StdMapObserver::from_mut_ptr("signals", signals_ptr, signals_len) }; - // Create a stacktrace observer - let bt_observer = BacktraceObserver::new( + // # Safety + // We just created the shmem and it's large enough. + let bt_observer = unsafe { BacktraceObserver::from_shmem( "BacktraceObserver", - unsafe { OwnedRefMut::from_shmem(&mut bt) }, + &mut bt, libafl::observers::HarnessType::Child, - ); + )}; // Feedback to rate the interestingness of an input, obtained by ANDing the interestingness of both feedbacks let mut feedback = MaxMapFeedback::new(&observer); diff --git a/fuzzers/forkserver/fuzzbench_forkserver/src/main.rs b/fuzzers/forkserver/fuzzbench_forkserver/src/main.rs index 1e547fd16d1..99fc78698d9 100644 --- a/fuzzers/forkserver/fuzzbench_forkserver/src/main.rs +++ b/fuzzers/forkserver/fuzzbench_forkserver/src/main.rs @@ -356,7 +356,7 @@ fn fuzz( unsafe { cmplog_shmem.write_to_env(SHM_CMPLOG_ENV_VAR).unwrap(); } - let cmpmap = unsafe { OwnedRefMut::::from_shmem(&mut cmplog_shmem) }; + let cmpmap = unsafe { AflppCmpLogMap::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 3775a3bc335..2e6d5661093 100644 --- a/fuzzers/forkserver/fuzzbench_forkserver_cmplog/src/main.rs +++ b/fuzzers/forkserver/fuzzbench_forkserver_cmplog/src/main.rs @@ -359,7 +359,7 @@ fn fuzz( unsafe { cmplog_shmem.write_to_env(SHM_CMPLOG_ENV_VAR).unwrap(); } - let cmpmap = unsafe { OwnedRefMut::from_shmem(&mut cmplog_shmem) }; + let cmpmap = unsafe { AflppCmpLogMap::from_shmem(&mut cmplog_shmem) }; let cmplog_observer = AflppCmpLogObserver::new("cmplog", cmpmap, true); let cmplog_ref = cmplog_observer.handle(); diff --git a/fuzzers/forkserver/fuzzbench_forkserver_sand/src/main.rs b/fuzzers/forkserver/fuzzbench_forkserver_sand/src/main.rs index a3b06f7ff09..6d42988324c 100644 --- a/fuzzers/forkserver/fuzzbench_forkserver_sand/src/main.rs +++ b/fuzzers/forkserver/fuzzbench_forkserver_sand/src/main.rs @@ -405,7 +405,7 @@ fn fuzz( unsafe { cmplog_shmem.write_to_env(SHM_CMPLOG_ENV_VAR).unwrap(); } - let cmpmap = unsafe { OwnedRefMut::::from_shmem(&mut cmplog_shmem) }; + let cmpmap = unsafe { AflppCmpLogMap::from_shmem(&mut cmplog_shmem) }; let cmplog_observer = StdCmpObserver::new("cmplog", cmpmap, true); diff --git a/fuzzers/forkserver/libafl-fuzz/src/fuzzer.rs b/fuzzers/forkserver/libafl-fuzz/src/fuzzer.rs index 8e31f621943..e3aa8394d6c 100644 --- a/fuzzers/forkserver/libafl-fuzz/src/fuzzer.rs +++ b/fuzzers/forkserver/libafl-fuzz/src/fuzzer.rs @@ -481,7 +481,7 @@ define_run_client!(state, mgr, fuzzer_dir, core_id, opt, is_main_node, { unsafe { cmplog_shmem.write_to_env(SHM_CMPLOG_ENV_VAR).unwrap(); } - let cmpmap = unsafe { OwnedRefMut::from_shmem(&mut cmplog_shmem) }; + let cmpmap = unsafe { AflppCmpLogMap::from_shmem(&mut cmplog_shmem) }; // Create the CmpLog observer. let cmplog_observer = AflppCmpLogObserver::new("cmplog", cmpmap, true); diff --git a/fuzzers/fuzz_anything/baby_no_std/Cargo.lock b/fuzzers/fuzz_anything/baby_no_std/Cargo.lock index 526ce7b47e0..e20a08feaff 100644 --- a/fuzzers/fuzz_anything/baby_no_std/Cargo.lock +++ b/fuzzers/fuzz_anything/baby_no_std/Cargo.lock @@ -2,6 +2,21 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + [[package]] name = "ahash" version = "0.8.12" @@ -43,6 +58,21 @@ dependencies = [ "static-alloc", ] +[[package]] +name = "backtrace" +version = "0.3.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets 0.52.6", +] + [[package]] name = "bitbybit" version = "1.3.2" @@ -55,12 +85,39 @@ dependencies = [ "syn", ] +[[package]] +name = "bitflags" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" + +[[package]] +name = "build_id2" +version = "0.15.3" +dependencies = [ + "ahash", + "rustversion", + "uuid", +] + +[[package]] +name = "bumpalo" +version = "3.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + [[package]] name = "cfg-if" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "cobs" version = "0.3.0" @@ -96,6 +153,16 @@ version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2459fc9262a1aa204eb4b5764ad4f189caec88aea9634389c0a25f8be7f6265e" +[[package]] +name = "core_affinity2" +version = "0.15.3" +dependencies = [ + "libafl_core", + "libc", + "rustversion", + "serde", +] + [[package]] name = "embedded-io" version = "0.4.0" @@ -118,6 +185,42 @@ dependencies = [ "typeid", ] +[[package]] +name = "exceptional" +version = "0.15.3" +dependencies = [ + "libafl_core", + "libc", + "num_enum", + "rustversion", +] + +[[package]] +name = "fast_rands" +version = "0.15.3" +dependencies = [ + "rustversion", + "serde", +] + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + [[package]] name = "hashbrown" version = "0.14.5" @@ -128,6 +231,27 @@ dependencies = [ "serde", ] +[[package]] +name = "hostname" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56f203cd1c76362b69e3863fd987520ac36cf70a8c92627449b2f64a8cf7d65" +dependencies = [ + "cfg-if", + "libc", + "windows-link", +] + +[[package]] +name = "js-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + [[package]] name = "libafl" version = "0.15.3" @@ -139,8 +263,10 @@ dependencies = [ "const_panic", "hashbrown", "libafl_bolts", + "libafl_core", "libc", "libm", + "ll_mp", "log", "meminterval", "num-traits", @@ -157,24 +283,45 @@ name = "libafl_bolts" version = "0.15.3" dependencies = [ "ahash", + "build_id2", + "core_affinity2", "erased-serde", + "exceptional", + "fast_rands", "hashbrown", + "libafl_core", "libc", + "ll_mp", "log", "mach2", + "minibsod", + "no_std_time", "num_enum", "once_cell", + "ownedref", "postcard", "rustversion", "serde", + "serde_anymap", + "shmem_providers", "static_assertions", "tuple_list", + "tuple_list_ex", "typeid", "winapi", "windows", "windows-result", ] +[[package]] +name = "libafl_core" +version = "0.15.3" +dependencies = [ + "postcard", + "rustversion", + "serde", +] + [[package]] name = "libc" version = "0.2.174" @@ -187,6 +334,35 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" +[[package]] +name = "ll_mp" +version = "0.15.3" +dependencies = [ + "backtrace", + "exceptional", + "hostname", + "libafl_core", + "log", + "nix", + "no_std_time", + "postcard", + "rustversion", + "serde", + "serial_test", + "shmem_providers", + "tuple_list", +] + +[[package]] +name = "lock_api" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +dependencies = [ + "autocfg", + "scopeguard", +] + [[package]] name = "log" version = "0.4.27" @@ -202,6 +378,12 @@ dependencies = [ "libc", ] +[[package]] +name = "memchr" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" + [[package]] name = "meminterval" version = "0.4.1" @@ -212,6 +394,54 @@ dependencies = [ "serde", ] +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "minibsod" +version = "0.15.3" +dependencies = [ + "exceptional", + "libc", + "mach2", + "rustversion", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", +] + +[[package]] +name = "nix" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" +dependencies = [ + "bitflags", + "cfg-if", + "cfg_aliases", + "libc", + "memoffset", +] + +[[package]] +name = "no_std_time" +version = "0.15.3" +dependencies = [ + "rustversion", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -242,12 +472,53 @@ dependencies = [ "syn", ] +[[package]] +name = "object" +version = "0.36.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +[[package]] +name = "ownedref" +version = "0.15.3" +dependencies = [ + "libafl_core", + "rustversion", + "serde", +] + +[[package]] +name = "parking_lot" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.6", +] + [[package]] name = "postcard" version = "1.1.2" @@ -278,12 +549,54 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "redox_syscall" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6" +dependencies = [ + "bitflags", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" + [[package]] name = "rustversion" version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" +[[package]] +name = "scc" +version = "2.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22b2d775fb28f245817589471dd49c5edf64237f4a19d10ce9a92ff4651a27f4" +dependencies = [ + "sdd", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sdd" +version = "3.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62f5557d2bbddd5afd236ba7856b0e494f5acc7ce805bb0774cc5674b20a06b4" + [[package]] name = "serde" version = "1.0.219" @@ -293,6 +606,20 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde_anymap" +version = "0.15.3" +dependencies = [ + "ahash", + "erased-serde", + "hashbrown", + "libafl_core", + "postcard", + "rustversion", + "serde", + "static_assertions", +] + [[package]] name = "serde_derive" version = "1.0.219" @@ -304,6 +631,49 @@ dependencies = [ "syn", ] +[[package]] +name = "serial_test" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b258109f244e1d6891bf1053a55d63a5cd4f8f4c30cf9a1280989f80e7a1fa9" +dependencies = [ + "once_cell", + "parking_lot", + "scc", + "serial_test_derive", +] + +[[package]] +name = "serial_test_derive" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "shmem_providers" +version = "0.15.3" +dependencies = [ + "fast_rands", + "hashbrown", + "libafl_core", + "libc", + "log", + "postcard", + "rustversion", + "serde", +] + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + [[package]] name = "static-alloc" version = "0.2.6" @@ -356,6 +726,18 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "141fb9f71ee586d956d7d6e4d5a9ef8e946061188520140f7591b668841d502e" +[[package]] +name = "tuple_list_ex" +version = "0.15.3" +dependencies = [ + "libafl_core", + "ownedref", + "rustversion", + "serde", + "tuple_list", + "typeid", +] + [[package]] name = "typeid" version = "1.0.3" @@ -374,12 +756,91 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +[[package]] +name = "uuid" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" +dependencies = [ + "getrandom", + "js-sys", + "serde", + "wasm-bindgen", +] + [[package]] name = "version_check" version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] + [[package]] name = "winapi" version = "0.3.9" @@ -409,7 +870,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f919aee0a93304be7f62e8e5027811bbba96bcb1de84d6618be56e43f8a32a1" dependencies = [ "windows-core", - "windows-targets", + "windows-targets 0.53.2", ] [[package]] @@ -422,7 +883,7 @@ dependencies = [ "windows-interface", "windows-result", "windows-strings", - "windows-targets", + "windows-targets 0.53.2", ] [[package]] @@ -471,70 +932,143 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + [[package]] name = "windows-targets" version = "0.53.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + [[package]] name = "windows_aarch64_gnullvm" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + [[package]] name = "windows_aarch64_msvc" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + [[package]] name = "windows_i686_gnu" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + [[package]] name = "windows_i686_gnullvm" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + [[package]] name = "windows_i686_msvc" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + [[package]] name = "windows_x86_64_gnu" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + [[package]] name = "windows_x86_64_gnullvm" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + [[package]] name = "windows_x86_64_msvc" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags", +] + [[package]] name = "zerocopy" version = "0.8.26" diff --git a/fuzzers/structure_aware/baby_fuzzer_nautilus/Cargo.lock b/fuzzers/structure_aware/baby_fuzzer_nautilus/Cargo.lock index 24e08429a0e..c49934634a5 100644 --- a/fuzzers/structure_aware/baby_fuzzer_nautilus/Cargo.lock +++ b/fuzzers/structure_aware/baby_fuzzer_nautilus/Cargo.lock @@ -52,7 +52,7 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "baby_fuzzer_nautilus" -version = "0.15.2" +version = "0.15.3" dependencies = [ "libafl", "libafl_bolts", @@ -76,11 +76,22 @@ dependencies = [ [[package]] name = "bincode" -version = "1.3.3" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +checksum = "36eaf5d7b090263e8150820482d5d93cd964a81e4019913c972f4edcc6edb740" dependencies = [ + "bincode_derive", "serde", + "unty", +] + +[[package]] +name = "bincode_derive" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf95709a440f45e986983918d0e8a1f30a9b1df04918fc828670606804ac3c09" +dependencies = [ + "virtue", ] [[package]] @@ -101,6 +112,15 @@ version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +[[package]] +name = "build_id2" +version = "0.15.3" +dependencies = [ + "ahash", + "rustversion", + "uuid", +] + [[package]] name = "bumpalo" version = "3.17.0" @@ -157,6 +177,16 @@ version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2459fc9262a1aa204eb4b5764ad4f189caec88aea9634389c0a25f8be7f6265e" +[[package]] +name = "core_affinity2" +version = "0.15.3" +dependencies = [ + "libafl_core", + "libc", + "rustversion", + "serde", +] + [[package]] name = "ctor" version = "0.4.2" @@ -210,15 +240,33 @@ dependencies = [ "typeid", ] +[[package]] +name = "exceptional" +version = "0.15.3" +dependencies = [ + "libafl_core", + "libc", + "num_enum", + "rustversion", +] + +[[package]] +name = "fast_rands" +version = "0.15.3" +dependencies = [ + "rand_core", + "rustversion", + "serde", +] + [[package]] name = "fastbloom" -version = "0.9.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27cea6e7f512d43b098939ff4d5a5d6fe3db07971e1d05176fe26c642d33f5b8" +checksum = "29ec576c163744bef8707859f6aeb322bcf56b8da61215d99f77d6e33160ff01" dependencies = [ "getrandom", "siphasher", - "wide 0.7.32 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -288,7 +336,7 @@ dependencies = [ [[package]] name = "libafl" -version = "0.15.2" +version = "0.15.3" dependencies = [ "ahash", "arbitrary-int", @@ -301,9 +349,11 @@ dependencies = [ "fs2", "hashbrown", "libafl_bolts", + "libafl_core", "libafl_derive", "libc", "libm", + "ll_mp", "log", "meminterval", "nix", @@ -325,48 +375,78 @@ dependencies = [ [[package]] name = "libafl_bolts" -version = "0.15.2" +version = "0.15.3" dependencies = [ "ahash", "backtrace", - "ctor", + "build_id2", + "core_affinity2", "erased-serde", + "exceptional", + "fast_rands", "hashbrown", "hostname", + "libafl_core", "libafl_derive", + "libafl_wide", "libc", + "ll_mp", "log", "mach2", + "minibsod", "miniz_oxide", "nix", + "no_std_time", "num_enum", "once_cell", + "ownedref", "postcard", - "rand_core", "rustversion", "serde", + "serde_anymap", "serial_test", + "shmem_providers", "static_assertions", "tuple_list", + "tuple_list_ex", "typeid", "uds", "uuid", - "wide 0.7.32 (git+https://github.com/Lokathor/wide?rev=71b5df0b2620da753836fafce5f99076181a49fe)", "winapi", "windows", "windows-result", "xxhash-rust", ] +[[package]] +name = "libafl_core" +version = "0.15.3" +dependencies = [ + "nix", + "postcard", + "rustversion", + "serde", +] + [[package]] name = "libafl_derive" -version = "0.15.2" +version = "0.15.3" dependencies = [ "proc-macro2", "quote", "syn", ] +[[package]] +name = "libafl_wide" +version = "0.7.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2f28d525f6e361b6cd55c0da5347027860a902d638d15194c16dc2f39a5ba9f" +dependencies = [ + "bytemuck", + "safe_arch", +] + [[package]] name = "libc" version = "0.2.172" @@ -379,6 +459,26 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" +[[package]] +name = "ll_mp" +version = "0.15.3" +dependencies = [ + "backtrace", + "exceptional", + "hostname", + "libafl_core", + "log", + "miniz_oxide", + "nix", + "no_std_time", + "postcard", + "rustversion", + "serde", + "serial_test", + "shmem_providers", + "tuple_list", +] + [[package]] name = "lock_api" version = "0.4.12" @@ -429,6 +529,16 @@ dependencies = [ "autocfg", ] +[[package]] +name = "minibsod" +version = "0.15.3" +dependencies = [ + "exceptional", + "libc", + "mach2", + "rustversion", +] + [[package]] name = "miniz_oxide" version = "0.8.8" @@ -440,9 +550,9 @@ dependencies = [ [[package]] name = "nix" -version = "0.29.0" +version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" dependencies = [ "bitflags", "cfg-if", @@ -451,6 +561,13 @@ dependencies = [ "memoffset", ] +[[package]] +name = "no_std_time" +version = "0.15.3" +dependencies = [ + "rustversion", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -495,6 +612,15 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +[[package]] +name = "ownedref" +version = "0.15.3" +dependencies = [ + "libafl_core", + "rustversion", + "serde", +] + [[package]] name = "parking_lot" version = "0.12.3" @@ -655,6 +781,21 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde_anymap" +version = "0.15.3" +dependencies = [ + "ahash", + "ctor", + "erased-serde", + "hashbrown", + "libafl_core", + "postcard", + "rustversion", + "serde", + "static_assertions", +] + [[package]] name = "serde_derive" version = "1.0.219" @@ -702,6 +843,23 @@ dependencies = [ "syn", ] +[[package]] +name = "shmem_providers" +version = "0.15.3" +dependencies = [ + "fast_rands", + "hashbrown", + "libafl_core", + "libc", + "log", + "nix", + "postcard", + "rustversion", + "serde", + "serial_test", + "uds", +] + [[package]] name = "siphasher" version = "1.0.1" @@ -737,6 +895,18 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "141fb9f71ee586d956d7d6e4d5a9ef8e946061188520140f7591b668841d502e" +[[package]] +name = "tuple_list_ex" +version = "0.15.3" +dependencies = [ + "libafl_core", + "ownedref", + "rustversion", + "serde", + "tuple_list", + "typeid", +] + [[package]] name = "typed-builder" version = "0.21.0" @@ -784,6 +954,12 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +[[package]] +name = "unty" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae" + [[package]] name = "uuid" version = "1.17.0" @@ -802,6 +978,12 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "virtue" +version = "0.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "051eb1abcf10076295e815102942cc58f9d5e3b4560e46e53c21e8ff6f3af7b1" + [[package]] name = "wait-timeout" version = "0.2.1" @@ -878,25 +1060,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "wide" -version = "0.7.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41b5576b9a81633f3e8df296ce0063042a73507636cbe956c61133dd7034ab22" -dependencies = [ - "bytemuck", - "safe_arch", -] - -[[package]] -name = "wide" -version = "0.7.32" -source = "git+https://github.com/Lokathor/wide?rev=71b5df0b2620da753836fafce5f99076181a49fe#71b5df0b2620da753836fafce5f99076181a49fe" -dependencies = [ - "bytemuck", - "safe_arch", -] - [[package]] name = "winapi" version = "0.3.9" From 84a4a910782a48ea302bf952ead0fa617c480254 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Tue, 15 Jul 2025 12:21:08 +0200 Subject: [PATCH 10/18] fmt --- .../c_code_with_fork_executor/src/main.rs | 12 +++++++----- .../rust_code_with_fork_executor/src/main.rs | 12 +++++++----- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/fuzzers/baby/backtrace_baby_fuzzers/c_code_with_fork_executor/src/main.rs b/fuzzers/baby/backtrace_baby_fuzzers/c_code_with_fork_executor/src/main.rs index 20062146498..5173ed5259d 100644 --- a/fuzzers/baby/backtrace_baby_fuzzers/c_code_with_fork_executor/src/main.rs +++ b/fuzzers/baby/backtrace_baby_fuzzers/c_code_with_fork_executor/src/main.rs @@ -57,11 +57,13 @@ pub fn main() { let mut bt = shmem_provider.new_on_shmem::>(None).unwrap(); // # Safety // We just created the shmem and it's large enough. - let bt_observer = unsafe { BacktraceObserver::from_shmem( - "BacktraceObserver", - &mut bt, - libafl::observers::HarnessType::Child, - )}; + let bt_observer = unsafe { + BacktraceObserver::from_shmem( + "BacktraceObserver", + &mut bt, + libafl::observers::HarnessType::Child, + ) + }; // Feedback to rate the interestingness of an input, obtained by ANDing the interestingness of both feedbacks let mut feedback = MaxMapFeedback::new(&observer); diff --git a/fuzzers/baby/backtrace_baby_fuzzers/rust_code_with_fork_executor/src/main.rs b/fuzzers/baby/backtrace_baby_fuzzers/rust_code_with_fork_executor/src/main.rs index ed6336c646e..dae8d591f46 100644 --- a/fuzzers/baby/backtrace_baby_fuzzers/rust_code_with_fork_executor/src/main.rs +++ b/fuzzers/baby/backtrace_baby_fuzzers/rust_code_with_fork_executor/src/main.rs @@ -69,11 +69,13 @@ pub fn main() { let observer = unsafe { StdMapObserver::from_mut_ptr("signals", signals_ptr, signals_len) }; // # Safety // We just created the shmem and it's large enough. - let bt_observer = unsafe { BacktraceObserver::from_shmem( - "BacktraceObserver", - &mut bt, - libafl::observers::HarnessType::Child, - )}; + let bt_observer = unsafe { + BacktraceObserver::from_shmem( + "BacktraceObserver", + &mut bt, + libafl::observers::HarnessType::Child, + ) + }; // Feedback to rate the interestingness of an input, obtained by ANDing the interestingness of both feedbacks let mut feedback = MaxMapFeedback::new(&observer); From 1cea49436cb9743bd3db36be013d6e765c62ca8c Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Tue, 15 Jul 2025 12:25:44 +0200 Subject: [PATCH 11/18] bring back unused features --- crates/libafl_bolts/Cargo.toml | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/crates/libafl_bolts/Cargo.toml b/crates/libafl_bolts/Cargo.toml index ad2e7d6fc41..d7860df9b0e 100644 --- a/crates/libafl_bolts/Cargo.toml +++ b/crates/libafl_bolts/Cargo.toml @@ -44,7 +44,6 @@ document-features = ["dep:document-features"] std = [ "alloc", "backtrace", - "backtrace", "fast_rands/std", "hostname", "libafl_core/nix", @@ -102,7 +101,7 @@ qemu_cli = ["cli"] frida_cli = ["cli"] ## Stores the backtraces of all generated `Error`s. Good for debugging, but may come with a slight performance hit. -errors_backtrace = ["backtrace"] +errors_backtrace = ["libafl_core/errors_backtrace"] ## Enables gzip compression in certain parts of the lib gzip = ["miniz_oxide", "alloc", "ll_mp/gzip"] @@ -124,6 +123,20 @@ stable_anymap = ["serde_anymap/stable_anymap"] ## Automatically register all `#[derive(SerdeAny)]` types at startup. serdeany_autoreg = ["serde_anymap/serdeany_autoreg"] +#! ### LLMP features + +## If set, llmp will bind to 0.0.0.0, allowing cross-device communication. Binds to localhost by default. +llmp_bind_public = ["ll_mp/llmp_bind_public"] + +## Enables llmp compression using GZip +llmp_compression = ["ll_mp/llmp_compression"] + +## Enables debug output for LLMP (also needs a `logger` installed) +llmp_debug = ["ll_mp/llmp_debug"] + +## Reduces the initial map size for llmp +llmp_small_maps = ["ll_mp/llmp_small_maps"] + #! ### Stable SIMD features ## Use the best SIMD implementation by our benchmark. From ebc5fc0d538ca49a81553b0f98045d071b0d9271 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Tue, 15 Jul 2025 12:31:33 +0200 Subject: [PATCH 12/18] no_std --- crates/fast_rands/src/loaded_dice.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/fast_rands/src/loaded_dice.rs b/crates/fast_rands/src/loaded_dice.rs index 713fa43fe20..ca1fae49498 100644 --- a/crates/fast_rands/src/loaded_dice.rs +++ b/crates/fast_rands/src/loaded_dice.rs @@ -23,6 +23,7 @@ Original code by @eqv, see */ use alloc::vec::Vec; +use alloc::vec; use core::fmt::{self, Debug, Formatter}; use super::Rand; From bee0bcc9ec97e3a30c7566ef13f8f387e7eac922 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Tue, 15 Jul 2025 13:46:51 +0200 Subject: [PATCH 13/18] remove once_cell --- crates/libafl_bolts/Cargo.toml | 1 - crates/libafl_bolts/src/lib.rs | 2 +- crates/libafl_targets/Cargo.toml | 1 - crates/libafl_targets/src/call.rs | 5 +++-- fuzzers/fuzz_anything/baby_no_std/Cargo.lock | 1 - 5 files changed, 4 insertions(+), 6 deletions(-) diff --git a/crates/libafl_bolts/Cargo.toml b/crates/libafl_bolts/Cargo.toml index d7860df9b0e..36ab9096a5f 100644 --- a/crates/libafl_bolts/Cargo.toml +++ b/crates/libafl_bolts/Cargo.toml @@ -227,7 +227,6 @@ windows = { workspace = true, features = [ "Win32_System_SystemInformation", "Win32_System_Threading", ] } -once_cell = "1.10.0" winapi = { version = "0.3", features = [ "fileapi", "handleapi", diff --git a/crates/libafl_bolts/src/lib.rs b/crates/libafl_bolts/src/lib.rs index b97f14fcf59..22b0c3b1fbf 100644 --- a/crates/libafl_bolts/src/lib.rs +++ b/crates/libafl_bolts/src/lib.rs @@ -356,7 +356,7 @@ pub fn get_thread_id() -> u64 { mod windows_logging { use core::ptr; - use once_cell::sync::OnceCell; + use std::cell::OnceCell; use winapi::um::{ fileapi::WriteFile, handleapi::INVALID_HANDLE_VALUE, processenv::GetStdHandle, winbase::STD_OUTPUT_HANDLE, winnt::HANDLE, diff --git a/crates/libafl_targets/Cargo.toml b/crates/libafl_targets/Cargo.toml index c5a6fbba88f..69a431fcb41 100644 --- a/crates/libafl_targets/Cargo.toml +++ b/crates/libafl_targets/Cargo.toml @@ -85,7 +85,6 @@ shmem_providers = { workspace = true } libc = { workspace = true } nix = { workspace = true, optional = true } hashbrown = { workspace = true, default-features = true } -once_cell = "1.19.0" log = { workspace = true } rustversion = { workspace = true } diff --git a/crates/libafl_targets/src/call.rs b/crates/libafl_targets/src/call.rs index d0581e18e09..4b7875aafc7 100644 --- a/crates/libafl_targets/src/call.rs +++ b/crates/libafl_targets/src/call.rs @@ -2,9 +2,10 @@ use core::marker::PhantomData; use hashbrown::HashMap; use libafl::executors::hooks::ExecutorHook; -use once_cell::sync::Lazy; +use std::cell::LazyCell; + /// The list of functions that this execution has observed -pub static mut FUNCTION_LIST: Lazy> = Lazy::new(HashMap::new); +pub static mut FUNCTION_LIST: LazyCell> = LazyCell::new(HashMap::new); #[unsafe(no_mangle)] /// The runtime code inserted at every callinst invokation (if you used the function-logging.cc) diff --git a/fuzzers/fuzz_anything/baby_no_std/Cargo.lock b/fuzzers/fuzz_anything/baby_no_std/Cargo.lock index e20a08feaff..bd92ae9d2d5 100644 --- a/fuzzers/fuzz_anything/baby_no_std/Cargo.lock +++ b/fuzzers/fuzz_anything/baby_no_std/Cargo.lock @@ -297,7 +297,6 @@ dependencies = [ "minibsod", "no_std_time", "num_enum", - "once_cell", "ownedref", "postcard", "rustversion", From 800d726efd650b149ad73013373160504e6704ab Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Tue, 15 Jul 2025 13:49:22 +0200 Subject: [PATCH 14/18] remove this stuff --- crates/fast_rands/src/loaded_dice.rs | 3 +-- crates/libafl_bolts/src/lib.rs | 2 +- crates/libafl_targets/src/call.rs | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/crates/fast_rands/src/loaded_dice.rs b/crates/fast_rands/src/loaded_dice.rs index ca1fae49498..93f8cdb8618 100644 --- a/crates/fast_rands/src/loaded_dice.rs +++ b/crates/fast_rands/src/loaded_dice.rs @@ -22,8 +22,7 @@ fn main() { Original code by @eqv, see */ -use alloc::vec::Vec; -use alloc::vec; +use alloc::{vec, vec::Vec}; use core::fmt::{self, Debug, Formatter}; use super::Rand; diff --git a/crates/libafl_bolts/src/lib.rs b/crates/libafl_bolts/src/lib.rs index 22b0c3b1fbf..406049fe589 100644 --- a/crates/libafl_bolts/src/lib.rs +++ b/crates/libafl_bolts/src/lib.rs @@ -355,8 +355,8 @@ pub fn get_thread_id() -> u64 { #[cfg(target_os = "windows")] mod windows_logging { use core::ptr; - use std::cell::OnceCell; + use winapi::um::{ fileapi::WriteFile, handleapi::INVALID_HANDLE_VALUE, processenv::GetStdHandle, winbase::STD_OUTPUT_HANDLE, winnt::HANDLE, diff --git a/crates/libafl_targets/src/call.rs b/crates/libafl_targets/src/call.rs index 4b7875aafc7..22a95a459a0 100644 --- a/crates/libafl_targets/src/call.rs +++ b/crates/libafl_targets/src/call.rs @@ -1,8 +1,8 @@ use core::marker::PhantomData; +use std::cell::LazyCell; use hashbrown::HashMap; use libafl::executors::hooks::ExecutorHook; -use std::cell::LazyCell; /// The list of functions that this execution has observed pub static mut FUNCTION_LIST: LazyCell> = LazyCell::new(HashMap::new); From c0cb42058c1b52661df89e64093115c906756f50 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Tue, 15 Jul 2025 15:30:30 +0200 Subject: [PATCH 15/18] more less std --- crates/libafl_bolts/Cargo.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/libafl_bolts/Cargo.toml b/crates/libafl_bolts/Cargo.toml index 36ab9096a5f..101b6fd72de 100644 --- a/crates/libafl_bolts/Cargo.toml +++ b/crates/libafl_bolts/Cargo.toml @@ -74,6 +74,7 @@ alloc = [ "no_std_time/alloc", "postcard", "serde/alloc", + "serde_anymap", "shmem_providers/alloc", "tuple_list_ex/alloc", ] @@ -162,7 +163,7 @@ ll_mp = { workspace = true } minibsod = { workspace = true } no_std_time = { workspace = true } ownedref = { workspace = true } -serde_anymap = { workspace = true } +serde_anymap = { workspace = true, optional = true } shmem_providers = { workspace = true } static_assertions = { workspace = true } tuple_list_ex = { workspace = true, features = ["serde"] } From 95279ac547a3cfe0499063501891789340465978 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Tue, 15 Jul 2025 18:05:13 +0200 Subject: [PATCH 16/18] no_std --- crates/libafl_bolts/Cargo.toml | 15 +- crates/libafl_core/src/lib.rs | 38 +- crates/ll_mp/Cargo.toml | 25 +- crates/shmem_providers/Cargo.toml | 4 +- fuzzers/fuzz_anything/baby_no_std/Cargo.lock | 445 +------------------ 5 files changed, 53 insertions(+), 474 deletions(-) diff --git a/crates/libafl_bolts/Cargo.toml b/crates/libafl_bolts/Cargo.toml index 101b6fd72de..07a1af34c5d 100644 --- a/crates/libafl_bolts/Cargo.toml +++ b/crates/libafl_bolts/Cargo.toml @@ -44,6 +44,8 @@ document-features = ["dep:document-features"] std = [ "alloc", "backtrace", + "build_id2", + "core_affinity2", "fast_rands/std", "hostname", "libafl_core/nix", @@ -51,6 +53,7 @@ std = [ "libafl_core/std", "libafl_core/std", "ll_mp/std", + "minibsod", "nix", "no_std_time/std", "serde/std", @@ -58,9 +61,6 @@ std = [ "shmem_providers/std", "simd", "uds", - "uds", - "uuid", - "uuid", ] ## Enables all features that allocate in `no_std` @@ -153,14 +153,14 @@ chrono = "0.4.40" itertools = "0.14.0" [dependencies] -build_id2 = { workspace = true } -core_affinity2 = { workspace = true } +build_id2 = { workspace = true, optional = true } +core_affinity2 = { workspace = true, optional = true } exceptional = { workspace = true } fast_rands = { workspace = true } -libafl_core = { workspace = true, features = ["postcard"] } +libafl_core = { workspace = true } libafl_derive = { workspace = true, default-features = true, optional = true } ll_mp = { workspace = true } -minibsod = { workspace = true } +minibsod = { workspace = true, optional = true } no_std_time = { workspace = true } ownedref = { workspace = true } serde_anymap = { workspace = true, optional = true } @@ -196,7 +196,6 @@ serde = { workspace = true, default-features = false, features = [ "derive", ] } # serialization lib tuple_list = { workspace = true } -uuid = { workspace = true, optional = true, features = ["serde", "v4"] } xxhash-rust = { version = "0.8.12", features = [ "xxh3", ], optional = true } # xxh3 hashing for rust diff --git a/crates/libafl_core/src/lib.rs b/crates/libafl_core/src/lib.rs index 99548451ffd..1d90f19f783 100644 --- a/crates/libafl_core/src/lib.rs +++ b/crates/libafl_core/src/lib.rs @@ -102,8 +102,8 @@ pub const IP_LOCALHOST: &str = "127.0.0.1"; pub struct ClientId(pub u32); #[cfg(feature = "errors_backtrace")] -/// Error Backtrace type when `errors_backtrace` feature is enabled (== [`backtrace::Backtrace`]) -pub type ErrorBacktrace = backtrace::Backtrace; +/// Error Backtrace type when `errors_backtrace` feature is enabled (== [`Backtrace`](std::backtrace::Backtrace`)) +pub type ErrorBacktrace = std::backtrace::Backtrace; #[cfg(not(feature = "errors_backtrace"))] #[derive(Debug, Default)] @@ -114,7 +114,7 @@ pub struct ErrorBacktrace; impl ErrorBacktrace { /// Nop #[must_use] - pub fn new() -> Self { + pub fn capture() -> Self { Self } } @@ -174,7 +174,7 @@ impl Error { where S: Into, { - Error::Serialize(arg.into(), ErrorBacktrace::new()) + Error::Serialize(arg.into(), ErrorBacktrace::capture()) } /// Optional val was supposed to be set, but isn't. @@ -183,7 +183,7 @@ impl Error { where S: Into, { - Error::EmptyOptional(arg.into(), ErrorBacktrace::new()) + Error::EmptyOptional(arg.into(), ErrorBacktrace::capture()) } /// The `Input` was invalid @@ -192,7 +192,7 @@ impl Error { where S: Into, { - Error::InvalidInput(reason.into(), ErrorBacktrace::new()) + Error::InvalidInput(reason.into(), ErrorBacktrace::capture()) } /// Key not in Map @@ -201,7 +201,7 @@ impl Error { where S: Into, { - Error::KeyNotFound(arg.into(), ErrorBacktrace::new()) + Error::KeyNotFound(arg.into(), ErrorBacktrace::capture()) } /// Key already exists in Map @@ -210,7 +210,7 @@ impl Error { where S: Into, { - Error::KeyExists(arg.into(), ErrorBacktrace::new()) + Error::KeyExists(arg.into(), ErrorBacktrace::capture()) } /// No elements in the current item @@ -219,7 +219,7 @@ impl Error { where S: Into, { - Error::Empty(arg.into(), ErrorBacktrace::new()) + Error::Empty(arg.into(), ErrorBacktrace::capture()) } /// End of iteration @@ -228,7 +228,7 @@ impl Error { where S: Into, { - Error::IteratorEnd(arg.into(), ErrorBacktrace::new()) + Error::IteratorEnd(arg.into(), ErrorBacktrace::capture()) } /// This is not supported (yet) @@ -237,7 +237,7 @@ impl Error { where S: Into, { - Error::NotImplemented(arg.into(), ErrorBacktrace::new()) + Error::NotImplemented(arg.into(), ErrorBacktrace::capture()) } /// You're holding it wrong @@ -246,7 +246,7 @@ impl Error { where S: Into, { - Error::IllegalState(arg.into(), ErrorBacktrace::new()) + Error::IllegalState(arg.into(), ErrorBacktrace::capture()) } /// The argument passed to this method or function is not valid @@ -255,7 +255,7 @@ impl Error { where S: Into, { - Error::IllegalArgument(arg.into(), ErrorBacktrace::new()) + Error::IllegalArgument(arg.into(), ErrorBacktrace::capture()) } /// Shutting down, not really an error. @@ -270,7 +270,7 @@ impl Error { where S: Into, { - Error::Unsupported(arg.into(), ErrorBacktrace::new()) + Error::Unsupported(arg.into(), ErrorBacktrace::capture()) } /// OS error with additional message @@ -280,7 +280,7 @@ impl Error { where S: Into, { - Error::OsError(err, msg.into(), ErrorBacktrace::new()) + Error::OsError(err, msg.into(), ErrorBacktrace::capture()) } /// OS error from [`io::Error::last_os_error`] with additional message @@ -293,7 +293,7 @@ impl Error { Error::OsError( io::Error::last_os_error(), msg.into(), - ErrorBacktrace::new(), + ErrorBacktrace::capture(), ) } @@ -303,7 +303,7 @@ impl Error { where S: Into, { - Error::Unknown(arg.into(), ErrorBacktrace::new()) + Error::Unknown(arg.into(), ErrorBacktrace::capture()) } /// Error with corpora @@ -312,7 +312,7 @@ impl Error { where S: Into, { - Error::InvalidCorpus(arg.into(), ErrorBacktrace::new()) + Error::InvalidCorpus(arg.into(), ErrorBacktrace::capture()) } /// Error specific to some runtime, like QEMU or Frida @@ -321,7 +321,7 @@ impl Error { where S: Into, { - Error::Runtime(arg.into(), ErrorBacktrace::new()) + Error::Runtime(arg.into(), ErrorBacktrace::capture()) } } diff --git a/crates/ll_mp/Cargo.toml b/crates/ll_mp/Cargo.toml index d8af8cba26d..4ccdbe91f5a 100644 --- a/crates/ll_mp/Cargo.toml +++ b/crates/ll_mp/Cargo.toml @@ -27,15 +27,21 @@ document-features = ["dep:document-features"] #! ### General Features ## Enables features that need rust's `std` lib to work, like print, env, ... support -std = ["libafl_core/std", "shmem_providers/std", "alloc"] +std = [ + "libafl_core/std", + "shmem_providers/std", + "alloc", + "nix", + "serial_test", + "hostname", +] ## Enables all features that allocate in `no_std` alloc = [ - "hostname", - "postcard", + "exceptional/alloc", "libafl_core/alloc", "libafl_core/serde", - "exceptional/alloc", + "postcard", "shmem_providers/alloc", ] @@ -64,18 +70,17 @@ rustversion = { workspace = true } [dependencies] # Document all features of this crate (for `cargo doc`) -backtrace = { workspace = true } document-features = { workspace = true, optional = true } exceptional = { workspace = true } -hostname = { version = "0.4.0", optional = true } # Is there really no gethostname in the stdlib? -libafl_core = { workspace = true, features = ["serde"] } +hostname = { version = "0.4.0", optional = true } # Is there really no gethostname in the stdlib? +libafl_core = { workspace = true } log = { workspace = true } miniz_oxide = { version = "0.8.0", optional = true } -nix = { workspace = true, features = ["socket"] } +nix = { workspace = true, features = ["socket"], optional = true } no_std_time = { workspace = true } -postcard = { workspace = true, optional = true } # no_std compatible serde serialization format +postcard = { workspace = true, optional = true } # no_std compatible serde serialization format serde = { workspace = true, features = ["alloc", "derive"] } -serial_test = { workspace = true } +serial_test = { workspace = true, optional = true } shmem_providers = { workspace = true } tuple_list = { workspace = true } diff --git a/crates/shmem_providers/Cargo.toml b/crates/shmem_providers/Cargo.toml index 7a1dff7e9b8..c4422c08b08 100644 --- a/crates/shmem_providers/Cargo.toml +++ b/crates/shmem_providers/Cargo.toml @@ -30,7 +30,7 @@ document-features = ["dep:document-features"] std = ["libafl_core/std", "uds", "nix", "libafl_core/nix", "serial_test"] ## Enables all features that allocate in `no_std` -alloc = ["libafl_core/alloc", "hashbrown", "postcard"] +alloc = ["libafl_core/alloc", "hashbrown", "postcard", "libafl_core/postcard"] [build-dependencies] rustversion = { workspace = true } @@ -41,7 +41,7 @@ rustversion = { workspace = true } # Document all features of this crate (for `cargo doc`) document-features = { workspace = true, optional = true } fast_rands = { workspace = true } -libafl_core = { workspace = true, features = ["postcard"] } +libafl_core = { workspace = true } log = { workspace = true } postcard = { workspace = true, optional = true } # no_std compatible serde serialization format serde = { workspace = true, features = ["derive"] } diff --git a/fuzzers/fuzz_anything/baby_no_std/Cargo.lock b/fuzzers/fuzz_anything/baby_no_std/Cargo.lock index bd92ae9d2d5..7c26be0e911 100644 --- a/fuzzers/fuzz_anything/baby_no_std/Cargo.lock +++ b/fuzzers/fuzz_anything/baby_no_std/Cargo.lock @@ -2,21 +2,6 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "addr2line" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler2" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" - [[package]] name = "ahash" version = "0.8.12" @@ -58,21 +43,6 @@ dependencies = [ "static-alloc", ] -[[package]] -name = "backtrace" -version = "0.3.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets 0.52.6", -] - [[package]] name = "bitbybit" version = "1.3.2" @@ -85,39 +55,12 @@ dependencies = [ "syn", ] -[[package]] -name = "bitflags" -version = "2.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" - -[[package]] -name = "build_id2" -version = "0.15.3" -dependencies = [ - "ahash", - "rustversion", - "uuid", -] - -[[package]] -name = "bumpalo" -version = "3.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" - [[package]] name = "cfg-if" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" -[[package]] -name = "cfg_aliases" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" - [[package]] name = "cobs" version = "0.3.0" @@ -153,16 +96,6 @@ version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2459fc9262a1aa204eb4b5764ad4f189caec88aea9634389c0a25f8be7f6265e" -[[package]] -name = "core_affinity2" -version = "0.15.3" -dependencies = [ - "libafl_core", - "libc", - "rustversion", - "serde", -] - [[package]] name = "embedded-io" version = "0.4.0" @@ -203,24 +136,6 @@ dependencies = [ "serde", ] -[[package]] -name = "getrandom" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" -dependencies = [ - "cfg-if", - "libc", - "r-efi", - "wasi", -] - -[[package]] -name = "gimli" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" - [[package]] name = "hashbrown" version = "0.14.5" @@ -231,27 +146,6 @@ dependencies = [ "serde", ] -[[package]] -name = "hostname" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56f203cd1c76362b69e3863fd987520ac36cf70a8c92627449b2f64a8cf7d65" -dependencies = [ - "cfg-if", - "libc", - "windows-link", -] - -[[package]] -name = "js-sys" -version = "0.3.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" -dependencies = [ - "once_cell", - "wasm-bindgen", -] - [[package]] name = "libafl" version = "0.15.3" @@ -283,8 +177,6 @@ name = "libafl_bolts" version = "0.15.3" dependencies = [ "ahash", - "build_id2", - "core_affinity2", "erased-serde", "exceptional", "fast_rands", @@ -294,7 +186,6 @@ dependencies = [ "ll_mp", "log", "mach2", - "minibsod", "no_std_time", "num_enum", "ownedref", @@ -337,31 +228,17 @@ checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" name = "ll_mp" version = "0.15.3" dependencies = [ - "backtrace", "exceptional", - "hostname", "libafl_core", "log", - "nix", "no_std_time", "postcard", "rustversion", "serde", - "serial_test", "shmem_providers", "tuple_list", ] -[[package]] -name = "lock_api" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" -dependencies = [ - "autocfg", - "scopeguard", -] - [[package]] name = "log" version = "0.4.27" @@ -377,12 +254,6 @@ dependencies = [ "libc", ] -[[package]] -name = "memchr" -version = "2.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" - [[package]] name = "meminterval" version = "0.4.1" @@ -393,47 +264,6 @@ dependencies = [ "serde", ] -[[package]] -name = "memoffset" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" -dependencies = [ - "autocfg", -] - -[[package]] -name = "minibsod" -version = "0.15.3" -dependencies = [ - "exceptional", - "libc", - "mach2", - "rustversion", -] - -[[package]] -name = "miniz_oxide" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" -dependencies = [ - "adler2", -] - -[[package]] -name = "nix" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" -dependencies = [ - "bitflags", - "cfg-if", - "cfg_aliases", - "libc", - "memoffset", -] - [[package]] name = "no_std_time" version = "0.15.3" @@ -471,15 +301,6 @@ dependencies = [ "syn", ] -[[package]] -name = "object" -version = "0.36.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" -dependencies = [ - "memchr", -] - [[package]] name = "once_cell" version = "1.21.3" @@ -495,29 +316,6 @@ dependencies = [ "serde", ] -[[package]] -name = "parking_lot" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets 0.52.6", -] - [[package]] name = "postcard" version = "1.1.2" @@ -548,54 +346,12 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "r-efi" -version = "5.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" - -[[package]] -name = "redox_syscall" -version = "0.5.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6" -dependencies = [ - "bitflags", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" - [[package]] name = "rustversion" version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" -[[package]] -name = "scc" -version = "2.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22b2d775fb28f245817589471dd49c5edf64237f4a19d10ce9a92ff4651a27f4" -dependencies = [ - "sdd", -] - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "sdd" -version = "3.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f5557d2bbddd5afd236ba7856b0e494f5acc7ce805bb0774cc5674b20a06b4" - [[package]] name = "serde" version = "1.0.219" @@ -630,29 +386,6 @@ dependencies = [ "syn", ] -[[package]] -name = "serial_test" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b258109f244e1d6891bf1053a55d63a5cd4f8f4c30cf9a1280989f80e7a1fa9" -dependencies = [ - "once_cell", - "parking_lot", - "scc", - "serial_test_derive", -] - -[[package]] -name = "serial_test_derive" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "shmem_providers" version = "0.15.3" @@ -667,12 +400,6 @@ dependencies = [ "serde", ] -[[package]] -name = "smallvec" -version = "1.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" - [[package]] name = "static-alloc" version = "0.2.6" @@ -755,91 +482,12 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" -[[package]] -name = "uuid" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" -dependencies = [ - "getrandom", - "js-sys", - "serde", - "wasm-bindgen", -] - [[package]] name = "version_check" version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" -[[package]] -name = "wasi" -version = "0.14.2+wasi-0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" -dependencies = [ - "wit-bindgen-rt", -] - -[[package]] -name = "wasm-bindgen" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" -dependencies = [ - "cfg-if", - "once_cell", - "rustversion", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" -dependencies = [ - "unicode-ident", -] - [[package]] name = "winapi" version = "0.3.9" @@ -869,7 +517,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f919aee0a93304be7f62e8e5027811bbba96bcb1de84d6618be56e43f8a32a1" dependencies = [ "windows-core", - "windows-targets 0.53.2", + "windows-targets", ] [[package]] @@ -882,7 +530,7 @@ dependencies = [ "windows-interface", "windows-result", "windows-strings", - "windows-targets 0.53.2", + "windows-targets", ] [[package]] @@ -931,143 +579,70 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", -] - [[package]] name = "windows-targets" version = "0.53.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" dependencies = [ - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - [[package]] name = "windows_aarch64_gnullvm" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - [[package]] name = "windows_aarch64_msvc" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - [[package]] name = "windows_i686_gnu" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - [[package]] name = "windows_i686_gnullvm" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - [[package]] name = "windows_i686_msvc" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - [[package]] name = "windows_x86_64_gnu" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - [[package]] name = "windows_x86_64_gnullvm" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - [[package]] name = "windows_x86_64_msvc" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" -[[package]] -name = "wit-bindgen-rt" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags", -] - [[package]] name = "zerocopy" version = "0.8.26" From 4788eb900a51cba0a617cf1c7bad13326f8174f5 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Tue, 15 Jul 2025 18:12:49 +0200 Subject: [PATCH 17/18] clippy --- crates/build_id2/src/lib.rs | 2 +- crates/libafl_core/src/lib.rs | 2 +- crates/no_std_time/src/lib.rs | 2 +- crates/serde_anymap/src/lib.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/build_id2/src/lib.rs b/crates/build_id2/src/lib.rs index 5abe977e49f..903db20603b 100644 --- a/crates/build_id2/src/lib.rs +++ b/crates/build_id2/src/lib.rs @@ -1,7 +1,7 @@ //! Based on //! (C) Alec Mocatta under license MIT or Apache 2 //! -//! Maintained by the LibAFL team. +//! Maintained by the `LibAFL` team. #![doc = include_str!("../../../README.md")] /*! */ #![cfg_attr(not(test), warn( diff --git a/crates/libafl_core/src/lib.rs b/crates/libafl_core/src/lib.rs index 1d90f19f783..a2dfd3396a8 100644 --- a/crates/libafl_core/src/lib.rs +++ b/crates/libafl_core/src/lib.rs @@ -95,7 +95,7 @@ use { /// Localhost addr, this is used, for example, for LLMP Client, which connects to this address pub const IP_LOCALHOST: &str = "127.0.0.1"; -/// The client ID for various use cases across LibAFL +/// The client ID for various use cases across `LibAFL` #[repr(transparent)] #[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] diff --git a/crates/no_std_time/src/lib.rs b/crates/no_std_time/src/lib.rs index a486a44d237..339a9c71560 100644 --- a/crates/no_std_time/src/lib.rs +++ b/crates/no_std_time/src/lib.rs @@ -1,4 +1,4 @@ -//! Time functions that can be used on no_std +//! Time functions that can be used on `no_std` #![doc = include_str!("../../../README.md")] /*! */ #![cfg_attr(feature = "document-features", doc = document_features::document_features!())] diff --git a/crates/serde_anymap/src/lib.rs b/crates/serde_anymap/src/lib.rs index 354df44af3e..d2138e79050 100644 --- a/crates/serde_anymap/src/lib.rs +++ b/crates/serde_anymap/src/lib.rs @@ -1,4 +1,4 @@ -//! A map that can retrieve values by type - and is SerDe serializable. +//! A map that can retrieve values by type - and is `Serde` serializable. #![doc = include_str!("../../../README.md")] /*! */ #![cfg_attr(feature = "document-features", doc = document_features::document_features!())] From f5b5f4509b16e35caaba9afbc863e44392d1c445 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Fri, 25 Jul 2025 04:47:57 +0200 Subject: [PATCH 18/18] More work --- crates/libafl_bolts/src/lib.rs | 14 +++++--------- crates/ll_mp/src/lib.rs | 10 +++++----- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/crates/libafl_bolts/src/lib.rs b/crates/libafl_bolts/src/lib.rs index 406049fe589..93d897a2d83 100644 --- a/crates/libafl_bolts/src/lib.rs +++ b/crates/libafl_bolts/src/lib.rs @@ -89,21 +89,17 @@ pub use argparse::*; #[cfg(feature = "std")] pub mod target_args; -pub use no_std_time::format_duration; -#[cfg(feature = "alloc")] -pub use serde_anymap::impl_serdeany; -#[cfg(feature = "std")] -pub use target_args::*; - -pub mod simd; - pub use fast_rands as rands; pub use libafl_core::{ AsIter, AsIterMut, AsSlice, AsSliceMut, ClientId, Error, HasLen, HasRefCnt, Named, Truncate, }; -pub use no_std_time::current_time; +pub use no_std_time::{current_milliseconds, current_nanos, current_time, format_duration}; pub use ownedref::{self, subrange}; +#[cfg(feature = "alloc")] +pub use serde_anymap::impl_serdeany; pub use shmem_providers as shmem; +#[cfg(feature = "std")] +pub use target_args::*; /// The purpose of this module is to alleviate imports of the bolts by adding a glob import. #[cfg(feature = "prelude")] diff --git a/crates/ll_mp/src/lib.rs b/crates/ll_mp/src/lib.rs index b67c2d83fd1..7470d5ee9e4 100644 --- a/crates/ll_mp/src/lib.rs +++ b/crates/ll_mp/src/lib.rs @@ -127,6 +127,8 @@ use core::{ sync::atomic::{AtomicU16, Ordering, fence}, time::Duration, }; +#[cfg(all(debug_assertions, feature = "llmp_debug", feature = "std"))] +use std::backtrace::Backtrace; #[cfg(feature = "std")] use std::{ env, @@ -136,8 +138,6 @@ use std::{ thread, }; -#[cfg(all(debug_assertions, feature = "llmp_debug", feature = "std"))] -use backtrace::Backtrace; #[cfg(all(unix, not(miri)))] use exceptional::unix_signals::setup_signal_handler; #[cfg(unix)] @@ -1183,7 +1183,7 @@ where #[cfg(all(feature = "llmp_debug", feature = "std"))] { #[cfg(debug_assertions)] - let bt = Backtrace::new(); + let bt = Backtrace::capture(); #[cfg(not(debug_assertions))] let bt = ""; let shm = self.out_shmems.last().unwrap(); @@ -2059,7 +2059,7 @@ where #[cfg(feature = "llmp_debug")] //{ //#[cfg(debug_assertions)] - //let bt = Backtrace::new(); + //let bt = Backtrace::capture(); //#[cfg(not(debug_assertions))] //let bt = ""; log::info!( @@ -3924,7 +3924,7 @@ impl LlmpClient { mod tests { use core::time::Duration; - use std::thread::sleep; + use std::{thread::sleep, vec}; use serial_test::serial; use shmem_providers::{ShMemProvider, StdShMemProvider};