Make bolts work without alloc (#1401)
* Make bolts work without alloc * Use core::Error where available * unstable_feature -> nightly * windows no_alloc
This commit is contained in:
parent
a0c03fccc5
commit
dfaf06a22e
4
.github/workflows/build_and_test.yml
vendored
4
.github/workflows/build_and_test.yml
vendored
@ -49,6 +49,8 @@ jobs:
|
|||||||
run: cargo test
|
run: cargo test
|
||||||
- name: Test libafl no_std
|
- name: Test libafl no_std
|
||||||
run: cd libafl && cargo test --no-default-features
|
run: cd libafl && cargo test --no-default-features
|
||||||
|
- name: Test libafl_bolts no_std no_alloc
|
||||||
|
run: cd libafl_bolts && cargo test --no-default-features
|
||||||
- name: Test libafl_targets no_std
|
- name: Test libafl_targets no_std
|
||||||
run: cd libafl_targets && cargo test --no-default-features
|
run: cd libafl_targets && cargo test --no-default-features
|
||||||
|
|
||||||
@ -285,6 +287,8 @@ jobs:
|
|||||||
run: cd ./libafl && cargo test --no-default-features
|
run: cd ./libafl && cargo test --no-default-features
|
||||||
- name: libafl armv6m-none-eabi (32 bit no_std) clippy
|
- name: libafl armv6m-none-eabi (32 bit no_std) clippy
|
||||||
run: cd ./libafl && cargo clippy --target thumbv6m-none-eabi --no-default-features
|
run: cd ./libafl && cargo clippy --target thumbv6m-none-eabi --no-default-features
|
||||||
|
- name: Build no_std no_alloc bolts
|
||||||
|
run: cd ./libafl_bolts && cargo +nightly build -Zbuild-std=core --target aarch64-unknown-none --no-default-features -v --release && cd ../
|
||||||
|
|
||||||
build-docker:
|
build-docker:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
@ -61,7 +61,7 @@ serde_json = { version = "1.0", default-features = false, features = ["alloc"] }
|
|||||||
bytecount = "0.6.3"
|
bytecount = "0.6.3"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libafl_bolts = { version = "0.10.1", path = "../libafl_bolts", default-features = false }
|
libafl_bolts = { version = "0.10.1", path = "../libafl_bolts", default-features = false, features = ["alloc"] }
|
||||||
libafl_derive = { version = "0.10.1", path = "../libafl_derive", optional = true }
|
libafl_derive = { version = "0.10.1", path = "../libafl_derive", optional = true }
|
||||||
|
|
||||||
rustversion = "1.0"
|
rustversion = "1.0"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#[rustversion::nightly]
|
#[rustversion::nightly]
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("cargo:rerun-if-changed=build.rs");
|
println!("cargo:rerun-if-changed=build.rs");
|
||||||
println!("cargo:rustc-cfg=unstable_feature");
|
println!("cargo:rustc-cfg=nightly");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustversion::not(nightly)]
|
#[rustversion::not(nightly)]
|
||||||
|
@ -5,11 +5,11 @@ Welcome to `LibAFL`
|
|||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
// For `type_eq`
|
// For `type_eq`
|
||||||
#![cfg_attr(unstable_feature, feature(specialization))]
|
#![cfg_attr(nightly, feature(specialization))]
|
||||||
// For `type_id` and owned things
|
// For `type_id` and owned things
|
||||||
#![cfg_attr(unstable_feature, feature(intrinsics))]
|
#![cfg_attr(nightly, feature(intrinsics))]
|
||||||
// For `std::simd`
|
// For `std::simd`
|
||||||
#![cfg_attr(unstable_feature, feature(portable_simd))]
|
#![cfg_attr(nightly, feature(portable_simd))]
|
||||||
#![warn(clippy::cargo)]
|
#![warn(clippy::cargo)]
|
||||||
#![allow(ambiguous_glob_reexports)]
|
#![allow(ambiguous_glob_reexports)]
|
||||||
#![deny(clippy::cargo_common_metadata)]
|
#![deny(clippy::cargo_common_metadata)]
|
||||||
|
@ -21,9 +21,9 @@ pub mod concolic;
|
|||||||
pub mod value;
|
pub mod value;
|
||||||
|
|
||||||
// Rust is breaking this with 'error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `type_id`' and so we disable this component for the moment
|
// Rust is breaking this with 'error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `type_id`' and so we disable this component for the moment
|
||||||
//#[cfg(unstable_feature)]
|
//#[cfg(nightly)]
|
||||||
//pub mod owned;
|
//pub mod owned;
|
||||||
//#[cfg(unstable_feature)]
|
//#[cfg(nightly)]
|
||||||
//pub use owned::*;
|
//pub use owned::*;
|
||||||
use alloc::{
|
use alloc::{
|
||||||
string::{String, ToString},
|
string::{String, ToString},
|
||||||
|
@ -12,14 +12,15 @@ edition = "2021"
|
|||||||
categories = ["development-tools::testing", "emulators", "embedded", "os", "no-std"]
|
categories = ["development-tools::testing", "emulators", "embedded", "os", "no-std"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["std", "derive", "llmp_compression", "llmp_small_maps", "rand_trait", "prelude", "gzip", "serdeany_autoreg"]
|
default = ["std", "derive", "llmp_compression", "llmp_small_maps", "rand_trait", "prelude", "gzip", "serdeany_autoreg", "alloc"]
|
||||||
std = ["serde_json", "serde_json/std", "hostname", "nix", "serde/std", "once_cell", "uuid", "byteorder", "backtrace", "uds", "serial_test"] # print, env, launcher ... support
|
std = ["serde_json", "serde_json/std", "hostname", "nix", "serde/std", "once_cell", "uuid", "byteorder", "backtrace", "uds", "serial_test", "alloc"] # print, env, ... support
|
||||||
|
alloc = ["serde/alloc", "hashbrown", "postcard", "erased-serde/alloc", "ahash"] # Enables all features that allocate in no_std
|
||||||
derive = ["libafl_derive"] # provide derive(SerdeAny) macro.
|
derive = ["libafl_derive"] # provide derive(SerdeAny) macro.
|
||||||
rand_trait = ["rand_core"] # If set, libafl's rand implementations will implement `rand::Rng`
|
rand_trait = ["rand_core"] # If set, libafl's rand implementations will implement `rand::Rng`
|
||||||
python = ["pyo3"]
|
python = ["pyo3", "std"]
|
||||||
prelude = [] # Expose libafl::prelude for access without additional using directives
|
prelude = [] # Expose libafl::prelude for access without additional using directives
|
||||||
cli = ["clap"] # expose libafl_bolts::cli for easy commandline parsing
|
cli = ["clap"] # expose libafl_bolts::cli for easy commandline parsing
|
||||||
qemu_cli = ["cli"] # Commandline flags for qemu-based fuzzers
|
qemu_cli = ["cli"] # Commandline flagr for qemu-based fuzzers
|
||||||
frida_cli = ["cli"] # Commandline flags for frida-based fuzzers
|
frida_cli = ["cli"] # Commandline flags for frida-based fuzzers
|
||||||
errors_backtrace = ["backtrace"]
|
errors_backtrace = ["backtrace"]
|
||||||
gzip = ["miniz_oxide"] # Enables gzip compression in certain parts of the lib
|
gzip = ["miniz_oxide"] # Enables gzip compression in certain parts of the lib
|
||||||
@ -28,10 +29,10 @@ gzip = ["miniz_oxide"] # Enables gzip compression in certain parts of the lib
|
|||||||
serdeany_autoreg = ["ctor"] # Automatically register all `#[derive(SerdeAny)]` types at startup.
|
serdeany_autoreg = ["ctor"] # Automatically register all `#[derive(SerdeAny)]` types at startup.
|
||||||
|
|
||||||
# LLMP features
|
# LLMP features
|
||||||
llmp_bind_public = [] # If set, llmp will bind to 0.0.0.0, allowing cross-device communication. Binds to localhost by default.
|
llmp_bind_public = ["alloc"] # If set, llmp will bind to 0.0.0.0, allowing cross-device communication. Binds to localhost by default.
|
||||||
llmp_compression = ["gzip"] # llmp compression using GZip
|
llmp_compression = ["alloc", "gzip"] # llmp compression using GZip
|
||||||
llmp_debug = [] # Enables debug output for LLMP
|
llmp_debug = ["alloc"] # Enables debug output for LLMP
|
||||||
llmp_small_maps = [] # reduces initial map size for llmp
|
llmp_small_maps = ["alloc"] # reduces initial map size for llmp
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
rustversion = "1.0"
|
rustversion = "1.0"
|
||||||
@ -45,13 +46,13 @@ libafl_derive = { version = "0.10.1", optional = true, path = "../libafl_derive"
|
|||||||
|
|
||||||
rustversion = "1.0"
|
rustversion = "1.0"
|
||||||
tuple_list = { version = "0.1.3" }
|
tuple_list = { version = "0.1.3" }
|
||||||
hashbrown = { version = "0.14", features = ["serde", "ahash"], default-features=false } # A faster hashmap, nostd compatible
|
hashbrown = { version = "0.14", features = ["serde", "ahash"], default-features=false, optional = true } # A faster hashmap, nostd compatible
|
||||||
xxhash-rust = { version = "0.8.5", features = ["xxh3"] } # xxh3 hashing for rust
|
xxhash-rust = { version = "0.8.5", features = ["xxh3"] } # xxh3 hashing for rust
|
||||||
serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] } # serialization lib
|
serde = { version = "1.0", default-features = false, features = ["derive"] } # serialization lib
|
||||||
erased-serde = { version = "0.3.21", default-features = false, features = ["alloc"] } # erased serde
|
erased-serde = { version = "0.3.21", default-features = false, optional = true } # erased serde
|
||||||
postcard = { version = "1.0", features = ["alloc"] } # no_std compatible serde serialization format
|
postcard = { version = "1.0", features = ["alloc"], optional = true } # no_std compatible serde serialization format
|
||||||
num_enum = { version = "0.5.7", default-features = false }
|
num_enum = { version = "0.5.7", default-features = false }
|
||||||
ahash = { version = "0.8", default-features=false } # The hash function already used in hashbrown
|
ahash = { version = "0.8", default-features=false, optional = true } # The hash function already used in hashbrown
|
||||||
backtrace = {version = "0.3", optional = true} # Used to get the stacktrace in StacktraceObserver
|
backtrace = {version = "0.3", optional = true} # Used to get the stacktrace in StacktraceObserver
|
||||||
|
|
||||||
ctor = { optional = true, version = "0.2" }
|
ctor = { optional = true, version = "0.2" }
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#[rustversion::nightly]
|
#[rustversion::nightly]
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("cargo:rerun-if-changed=build.rs");
|
println!("cargo:rerun-if-changed=build.rs");
|
||||||
println!("cargo:rustc-cfg=unstable_feature");
|
println!("cargo:rustc-cfg=nightly");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustversion::not(nightly)]
|
#[rustversion::not(nightly)]
|
||||||
|
@ -7,11 +7,13 @@ Welcome to `LibAFL`
|
|||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
// For `type_eq`
|
// For `type_eq`
|
||||||
#![cfg_attr(unstable_feature, feature(specialization))]
|
#![cfg_attr(nightly, feature(specialization))]
|
||||||
// For `type_id` and owned things
|
// For `type_id` and owned things
|
||||||
#![cfg_attr(unstable_feature, feature(intrinsics))]
|
#![cfg_attr(nightly, feature(intrinsics))]
|
||||||
// For `std::simd`
|
// For `std::simd`
|
||||||
#![cfg_attr(unstable_feature, feature(portable_simd))]
|
#![cfg_attr(nightly, feature(portable_simd))]
|
||||||
|
// For `core::error`
|
||||||
|
#![cfg_attr(nightly, feature(error_in_core))]
|
||||||
#![warn(clippy::cargo)]
|
#![warn(clippy::cargo)]
|
||||||
#![allow(ambiguous_glob_reexports)]
|
#![allow(ambiguous_glob_reexports)]
|
||||||
#![deny(clippy::cargo_common_metadata)]
|
#![deny(clippy::cargo_common_metadata)]
|
||||||
@ -78,6 +80,7 @@ Welcome to `LibAFL`
|
|||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate std;
|
extern crate std;
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub extern crate alloc;
|
pub extern crate alloc;
|
||||||
@ -98,10 +101,11 @@ pub mod launcher {}
|
|||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate libafl_derive;
|
extern crate libafl_derive;
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
use alloc::string::{FromUtf8Error, String};
|
use alloc::string::{FromUtf8Error, String};
|
||||||
use core::{
|
use core::{
|
||||||
array::TryFromSliceError,
|
array::TryFromSliceError,
|
||||||
fmt,
|
fmt::{self, Display},
|
||||||
num::{ParseIntError, TryFromIntError},
|
num::{ParseIntError, TryFromIntError},
|
||||||
};
|
};
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
@ -110,6 +114,21 @@ use std::{env::VarError, io};
|
|||||||
#[cfg(feature = "libafl_derive")]
|
#[cfg(feature = "libafl_derive")]
|
||||||
pub use libafl_derive::SerdeAny;
|
pub use libafl_derive::SerdeAny;
|
||||||
|
|
||||||
|
/// 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;
|
||||||
|
|
||||||
|
/// We also 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
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
/// We need fixed names for many parts of this lib.
|
/// We need fixed names for many parts of this lib.
|
||||||
pub trait Named {
|
pub trait Named {
|
||||||
/// Provide the name of this element.
|
/// Provide the name of this element.
|
||||||
@ -276,7 +295,7 @@ impl Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Error {
|
impl Display for Error {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Self::Serialize(s, b) => {
|
Self::Serialize(s, b) => {
|
||||||
@ -339,6 +358,7 @@ impl fmt::Display for Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Stringify the postcard serializer error
|
/// Stringify the postcard serializer error
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
impl From<postcard::Error> for Error {
|
impl From<postcard::Error> for Error {
|
||||||
fn from(err: postcard::Error) -> Self {
|
fn from(err: postcard::Error) -> Self {
|
||||||
Self::serialize(format!("{err:?}"))
|
Self::serialize(format!("{err:?}"))
|
||||||
@ -368,7 +388,9 @@ impl From<io::Error> for Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
impl From<FromUtf8Error> for Error {
|
impl From<FromUtf8Error> for Error {
|
||||||
|
#[allow(unused_variables)]
|
||||||
fn from(err: FromUtf8Error) -> Self {
|
fn from(err: FromUtf8Error) -> Self {
|
||||||
Self::unknown(format!("Could not convert byte / utf-8: {err:?}"))
|
Self::unknown(format!("Could not convert byte / utf-8: {err:?}"))
|
||||||
}
|
}
|
||||||
@ -376,24 +398,28 @@ impl From<FromUtf8Error> for Error {
|
|||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
impl From<VarError> for Error {
|
impl From<VarError> for Error {
|
||||||
|
#[allow(unused_variables)]
|
||||||
fn from(err: VarError) -> Self {
|
fn from(err: VarError) -> Self {
|
||||||
Self::empty(format!("Could not get env var: {err:?}"))
|
Self::empty(format!("Could not get env var: {err:?}"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ParseIntError> for Error {
|
impl From<ParseIntError> for Error {
|
||||||
|
#[allow(unused_variables)]
|
||||||
fn from(err: ParseIntError) -> Self {
|
fn from(err: ParseIntError) -> Self {
|
||||||
Self::unknown(format!("Failed to parse Int: {err:?}"))
|
Self::unknown(format!("Failed to parse Int: {err:?}"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<TryFromIntError> for Error {
|
impl From<TryFromIntError> for Error {
|
||||||
|
#[allow(unused_variables)]
|
||||||
fn from(err: TryFromIntError) -> Self {
|
fn from(err: TryFromIntError) -> Self {
|
||||||
Self::illegal_state(format!("Expected conversion failed: {err:?}"))
|
Self::illegal_state(format!("Expected conversion failed: {err:?}"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<TryFromSliceError> for Error {
|
impl From<TryFromSliceError> for Error {
|
||||||
|
#[allow(unused_variables)]
|
||||||
fn from(err: TryFromSliceError) -> Self {
|
fn from(err: TryFromSliceError) -> Self {
|
||||||
Self::illegal_argument(format!("Could not convert slice: {err:?}"))
|
Self::illegal_argument(format!("Could not convert slice: {err:?}"))
|
||||||
}
|
}
|
||||||
@ -401,6 +427,7 @@ impl From<TryFromSliceError> for Error {
|
|||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
impl From<windows::core::Error> for Error {
|
impl From<windows::core::Error> for Error {
|
||||||
|
#[allow(unused_variables)]
|
||||||
fn from(err: windows::core::Error) -> Self {
|
fn from(err: windows::core::Error) -> Self {
|
||||||
Self::unknown(format!("Windows API error: {err:?}"))
|
Self::unknown(format!("Windows API error: {err:?}"))
|
||||||
}
|
}
|
||||||
@ -422,9 +449,12 @@ impl From<pyo3::PyErr> for Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(all(not(nightly), feature = "std"))]
|
||||||
impl std::error::Error for Error {}
|
impl std::error::Error for Error {}
|
||||||
|
|
||||||
|
#[cfg(nightly)]
|
||||||
|
impl core::error::Error for Error {}
|
||||||
|
|
||||||
/// The purpose of this module is to alleviate imports of many components by adding a glob import.
|
/// The purpose of this module is to alleviate imports of many components by adding a glob import.
|
||||||
#[cfg(feature = "prelude")]
|
#[cfg(feature = "prelude")]
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
@ -439,6 +469,7 @@ pub unsafe extern "C" fn external_current_millis() -> u64 {
|
|||||||
1000
|
1000
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
pub mod anymap;
|
pub mod anymap;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub mod build_id;
|
pub mod build_id;
|
||||||
@ -454,18 +485,22 @@ pub mod core_affinity;
|
|||||||
pub mod cpu;
|
pub mod cpu;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub mod fs;
|
pub mod fs;
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
pub mod llmp;
|
pub mod llmp;
|
||||||
#[cfg(all(feature = "std", unix))]
|
#[cfg(all(feature = "std", unix))]
|
||||||
pub mod minibsod;
|
pub mod minibsod;
|
||||||
pub mod os;
|
pub mod os;
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
pub mod ownedref;
|
pub mod ownedref;
|
||||||
pub mod rands;
|
pub mod rands;
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
pub mod serdeany;
|
pub mod serdeany;
|
||||||
pub mod shmem;
|
pub mod shmem;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub mod staterestore;
|
pub mod staterestore;
|
||||||
pub mod tuples;
|
pub mod tuples;
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use core::{iter::Iterator, ops::AddAssign, time};
|
use core::{iter::Iterator, ops::AddAssign, time};
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
@ -499,6 +534,7 @@ pub trait AsMutSlice {
|
|||||||
fn as_mut_slice(&mut self) -> &mut [Self::Entry];
|
fn as_mut_slice(&mut self) -> &mut [Self::Entry];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
impl<T> AsSlice for Vec<T> {
|
impl<T> AsSlice for Vec<T> {
|
||||||
type Entry = T;
|
type Entry = T;
|
||||||
|
|
||||||
@ -507,6 +543,7 @@ impl<T> AsSlice for Vec<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
impl<T> AsMutSlice for Vec<T> {
|
impl<T> AsMutSlice for Vec<T> {
|
||||||
type Entry = T;
|
type Entry = T;
|
||||||
|
|
||||||
@ -653,6 +690,7 @@ pub fn current_milliseconds() -> u64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Format a `Duration` into a HMS string
|
/// Format a `Duration` into a HMS string
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn format_duration_hms(duration: &time::Duration) -> String {
|
pub fn format_duration_hms(duration: &time::Duration) -> String {
|
||||||
let secs = duration.as_secs();
|
let secs = duration.as_secs();
|
||||||
@ -802,9 +840,9 @@ pub mod bolts_prelude {
|
|||||||
pub use super::minibsod::*;
|
pub use super::minibsod::*;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub use super::staterestore::*;
|
pub use super::staterestore::*;
|
||||||
pub use super::{
|
#[cfg(feature = "alloc")]
|
||||||
anymap::*, cpu::*, llmp::*, os::*, ownedref::*, rands::*, serdeany::*, shmem::*, tuples::*,
|
pub use super::{anymap::*, llmp::*, ownedref::*, rands::*, serdeany::*, shmem::*, tuples::*};
|
||||||
};
|
pub use super::{cpu::*, os::*, rands::*};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "python")]
|
#[cfg(feature = "python")]
|
||||||
|
@ -1,12 +1,16 @@
|
|||||||
//! Signal handling for unix
|
//! Signal handling for unix
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
use core::{
|
use core::{
|
||||||
cell::UnsafeCell,
|
cell::UnsafeCell,
|
||||||
fmt::{self, Display, Formatter},
|
ptr::{self, addr_of_mut, write_volatile},
|
||||||
mem, ptr,
|
|
||||||
ptr::{addr_of_mut, write_volatile},
|
|
||||||
sync::atomic::{compiler_fence, Ordering},
|
sync::atomic::{compiler_fence, Ordering},
|
||||||
};
|
};
|
||||||
|
use core::{
|
||||||
|
fmt::{self, Display, Formatter},
|
||||||
|
mem,
|
||||||
|
};
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
|
|
||||||
@ -241,11 +245,15 @@ use libc::ssize_t;
|
|||||||
)))]
|
)))]
|
||||||
pub use libc::ucontext_t;
|
pub use libc::ucontext_t;
|
||||||
use libc::{
|
use libc::{
|
||||||
c_int, malloc, sigaction, sigaddset, sigaltstack, sigemptyset, stack_t, SA_NODEFER, SA_ONSTACK,
|
c_int, SIGABRT, SIGALRM, SIGBUS, SIGFPE, SIGHUP, SIGILL, SIGINT, SIGKILL, SIGPIPE, SIGQUIT,
|
||||||
SA_SIGINFO, SIGABRT, SIGALRM, SIGBUS, SIGFPE, SIGHUP, SIGILL, SIGINT, SIGKILL, SIGPIPE,
|
SIGSEGV, SIGTERM, SIGTRAP, SIGUSR2,
|
||||||
SIGQUIT, SIGSEGV, SIGTERM, SIGTRAP, SIGUSR2,
|
|
||||||
};
|
};
|
||||||
pub use libc::{c_void, siginfo_t};
|
pub use libc::{c_void, siginfo_t};
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
use libc::{
|
||||||
|
malloc, sigaction, sigaddset, sigaltstack, sigemptyset, stack_t, SA_NODEFER, SA_ONSTACK,
|
||||||
|
SA_SIGINFO,
|
||||||
|
};
|
||||||
use num_enum::{IntoPrimitive, TryFromPrimitive};
|
use num_enum::{IntoPrimitive, TryFromPrimitive};
|
||||||
|
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
@ -335,6 +343,7 @@ impl Display for Signal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A trait for `LibAFL` signal handling
|
/// A trait for `LibAFL` signal handling
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
pub trait Handler {
|
pub trait Handler {
|
||||||
/// Handle a signal
|
/// Handle a signal
|
||||||
fn handle(&mut self, signal: Signal, info: siginfo_t, _context: &mut ucontext_t);
|
fn handle(&mut self, signal: Signal, info: siginfo_t, _context: &mut ucontext_t);
|
||||||
@ -342,18 +351,24 @@ pub trait Handler {
|
|||||||
fn signals(&self) -> Vec<Signal>;
|
fn signals(&self) -> Vec<Signal>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
struct HandlerHolder {
|
struct HandlerHolder {
|
||||||
handler: UnsafeCell<*mut dyn Handler>,
|
handler: UnsafeCell<*mut dyn Handler>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
unsafe impl Send for HandlerHolder {}
|
unsafe impl Send for HandlerHolder {}
|
||||||
|
|
||||||
/// Let's get 8 mb for now.
|
/// Let's get 8 mb for now.
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
const SIGNAL_STACK_SIZE: usize = 2 << 22;
|
const SIGNAL_STACK_SIZE: usize = 2 << 22;
|
||||||
|
|
||||||
/// To be able to handle SIGSEGV when the stack is exhausted, we need our own little stack space.
|
/// To be able to handle SIGSEGV when the stack is exhausted, we need our own little stack space.
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
static mut SIGNAL_STACK_PTR: *mut c_void = ptr::null_mut();
|
static mut SIGNAL_STACK_PTR: *mut c_void = ptr::null_mut();
|
||||||
|
|
||||||
/// Keep track of which handler is registered for which signal
|
/// Keep track of which handler is registered for which signal
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
static mut SIGNAL_HANDLERS: [Option<HandlerHolder>; 32] = [
|
static mut SIGNAL_HANDLERS: [Option<HandlerHolder>; 32] = [
|
||||||
// We cannot use [None; 32] because it requires Copy. Ugly, but I don't think there's an
|
// We cannot use [None; 32] because it requires Copy. Ugly, but I don't think there's an
|
||||||
// alternative.
|
// alternative.
|
||||||
@ -362,9 +377,11 @@ static mut SIGNAL_HANDLERS: [Option<HandlerHolder>; 32] = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
/// Internal function that is being called whenever a signal we are registered for arrives.
|
/// Internal function that is being called whenever a signal we are registered for arrives.
|
||||||
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
/// This should be somewhat safe to call for signals previously registered,
|
/// This should be somewhat safe to call for signals previously registered,
|
||||||
/// unless the signal handlers registered using [`setup_signal_handler()`] are broken.
|
/// unless the signal handlers registered using [`setup_signal_handler()`] are broken.
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
unsafe fn handle_signal(sig: c_int, info: siginfo_t, void: *mut c_void) {
|
unsafe fn handle_signal(sig: c_int, info: siginfo_t, void: *mut c_void) {
|
||||||
let signal = &Signal::try_from(sig).unwrap();
|
let signal = &Signal::try_from(sig).unwrap();
|
||||||
let handler = {
|
let handler = {
|
||||||
@ -385,6 +402,7 @@ unsafe fn handle_signal(sig: c_int, info: siginfo_t, void: *mut c_void) {
|
|||||||
///
|
///
|
||||||
/// The signal handlers will be called on any signal. They should (tm) be async safe.
|
/// The signal handlers will be called on any signal. They should (tm) be async safe.
|
||||||
/// A lot can go south in signal handling. Be sure you know what you are doing.
|
/// A lot can go south in signal handling. Be sure you know what you are doing.
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
pub unsafe fn setup_signal_handler<T: 'static + Handler>(handler: &mut T) -> Result<(), Error> {
|
pub unsafe fn setup_signal_handler<T: 'static + Handler>(handler: &mut T) -> Result<(), Error> {
|
||||||
// First, set up our own stack to be used during segfault handling. (and specify `SA_ONSTACK` in `sigaction`)
|
// First, set up our own stack to be used during segfault handling. (and specify `SA_ONSTACK` in `sigaction`)
|
||||||
if SIGNAL_STACK_PTR.is_null() {
|
if SIGNAL_STACK_PTR.is_null() {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
//! Exception handling for Windows
|
//! Exception handling for Windows
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use core::{
|
use core::{
|
||||||
cell::UnsafeCell,
|
cell::UnsafeCell,
|
||||||
@ -282,6 +283,7 @@ pub static EXCEPTION_CODES_MAPPING: [ExceptionCode; 47] = [
|
|||||||
ExceptionCode::Other,
|
ExceptionCode::Other,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
pub trait Handler {
|
pub trait Handler {
|
||||||
/// Handle an exception
|
/// Handle an exception
|
||||||
fn handle(
|
fn handle(
|
||||||
@ -366,6 +368,7 @@ unsafe extern "C" fn handle_signal(_signum: i32) {
|
|||||||
/// Setup Win32 exception handlers in a somewhat rusty way.
|
/// Setup Win32 exception handlers in a somewhat rusty way.
|
||||||
/// # Safety
|
/// # Safety
|
||||||
/// Exception handlers are usually ugly, handle with care!
|
/// Exception handlers are usually ugly, handle with care!
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
pub unsafe fn setup_exception_handler<T: 'static + Handler>(handler: &mut T) -> Result<(), Error> {
|
pub unsafe fn setup_exception_handler<T: 'static + Handler>(handler: &mut T) -> Result<(), Error> {
|
||||||
let exceptions = handler.exceptions();
|
let exceptions = handler.exceptions();
|
||||||
let mut catch_assertions = false;
|
let mut catch_assertions = false;
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
//! A generic shared memory region to be used by any functions (queues or feedbacks
|
//! A generic shared memory region to be used by any functions (queues or feedbacks
|
||||||
//! too.)
|
//! too.)
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
use alloc::{rc::Rc, string::ToString};
|
use alloc::{rc::Rc, string::ToString};
|
||||||
use core::{
|
use core::fmt::Debug;
|
||||||
cell::RefCell,
|
#[cfg(feature = "alloc")]
|
||||||
fmt::{self, Debug, Display},
|
use core::fmt::Display;
|
||||||
mem::ManuallyDrop,
|
#[cfg(feature = "alloc")]
|
||||||
};
|
use core::{cell::RefCell, fmt, mem::ManuallyDrop};
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use std::env;
|
use std::env;
|
||||||
#[cfg(all(unix, feature = "std"))]
|
#[cfg(all(unix, feature = "std"))]
|
||||||
@ -105,6 +106,7 @@ impl ShMemId {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new id from an int
|
/// Create a new id from an int
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn from_int(val: i32) -> Self {
|
pub fn from_int(val: i32) -> Self {
|
||||||
Self::from_string(&val.to_string())
|
Self::from_string(&val.to_string())
|
||||||
@ -140,6 +142,7 @@ impl ShMemId {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a `str` representation of this [`ShMemId`]
|
/// Returns a `str` representation of this [`ShMemId`]
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn as_str(&self) -> &str {
|
pub fn as_str(&self) -> &str {
|
||||||
alloc::str::from_utf8(&self.id[..self.null_pos()]).unwrap()
|
alloc::str::from_utf8(&self.id[..self.null_pos()]).unwrap()
|
||||||
@ -152,12 +155,14 @@ impl AsSlice for ShMemId {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
impl From<ShMemId> for i32 {
|
impl From<ShMemId> for i32 {
|
||||||
fn from(id: ShMemId) -> i32 {
|
fn from(id: ShMemId) -> i32 {
|
||||||
id.as_str().parse().unwrap()
|
id.as_str().parse().unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
impl Display for ShMemId {
|
impl Display for ShMemId {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "{}", self.as_str())
|
write!(f, "{}", self.as_str())
|
||||||
@ -302,12 +307,14 @@ pub trait ShMemProvider: Clone + Default + Debug {
|
|||||||
/// A Reference Counted shared map,
|
/// A Reference Counted shared map,
|
||||||
/// that can use internal mutability.
|
/// that can use internal mutability.
|
||||||
/// Useful if the `ShMemProvider` needs to keep local state.
|
/// Useful if the `ShMemProvider` needs to keep local state.
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct RcShMem<T: ShMemProvider> {
|
pub struct RcShMem<T: ShMemProvider> {
|
||||||
internal: ManuallyDrop<T::ShMem>,
|
internal: ManuallyDrop<T::ShMem>,
|
||||||
provider: Rc<RefCell<T>>,
|
provider: Rc<RefCell<T>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
impl<T> ShMem for RcShMem<T>
|
impl<T> ShMem for RcShMem<T>
|
||||||
where
|
where
|
||||||
T: ShMemProvider + Debug,
|
T: ShMemProvider + Debug,
|
||||||
@ -321,6 +328,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
impl<T> AsSlice for RcShMem<T>
|
impl<T> AsSlice for RcShMem<T>
|
||||||
where
|
where
|
||||||
T: ShMemProvider + Debug,
|
T: ShMemProvider + Debug,
|
||||||
@ -331,6 +339,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
impl<T> AsMutSlice for RcShMem<T>
|
impl<T> AsMutSlice for RcShMem<T>
|
||||||
where
|
where
|
||||||
T: ShMemProvider + Debug,
|
T: ShMemProvider + Debug,
|
||||||
@ -341,6 +350,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
impl<T: ShMemProvider> Drop for RcShMem<T> {
|
impl<T: ShMemProvider> Drop for RcShMem<T> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
self.provider.borrow_mut().release_shmem(&mut self.internal);
|
self.provider.borrow_mut().release_shmem(&mut self.internal);
|
||||||
|
@ -526,14 +526,28 @@ impl<Head, Tail> PlusOne for (Head, Tail) where
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use crate::{ownedref::OwnedMutSlice, tuples::type_eq};
|
#[cfg(feature = "alloc")]
|
||||||
|
use crate::ownedref::OwnedMutSlice;
|
||||||
/// An alias for equality testing
|
use crate::tuples::type_eq;
|
||||||
type OwnedMutSliceAlias<'a> = OwnedMutSlice<'a, u8>;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[allow(unused_qualifications)] // for type name tests
|
#[allow(unused_qualifications)] // for type name tests
|
||||||
|
fn test_type_eq_simple() {
|
||||||
|
// test eq
|
||||||
|
assert!(type_eq::<u64, u64>());
|
||||||
|
|
||||||
|
// test neq
|
||||||
|
assert!(!type_eq::<u64, usize>());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
#[allow(unused_qualifications)] // for type name tests
|
||||||
fn test_type_eq() {
|
fn test_type_eq() {
|
||||||
|
// An alias for equality testing
|
||||||
|
type OwnedMutSliceAlias<'a> = OwnedMutSlice<'a, u8>;
|
||||||
|
|
||||||
|
// A function for lifetime testing
|
||||||
#[allow(clippy::extra_unused_lifetimes)]
|
#[allow(clippy::extra_unused_lifetimes)]
|
||||||
fn test_lifetimes<'a, 'b>() {
|
fn test_lifetimes<'a, 'b>() {
|
||||||
assert!(type_eq::<OwnedMutSlice<'a, u8>, OwnedMutSlice<'b, u8>>());
|
assert!(type_eq::<OwnedMutSlice<'a, u8>, OwnedMutSlice<'b, u8>>());
|
||||||
@ -545,12 +559,6 @@ mod test {
|
|||||||
assert!(type_eq::<OwnedMutSlice<u8>, OwnedMutSliceAlias>());
|
assert!(type_eq::<OwnedMutSlice<u8>, OwnedMutSliceAlias>());
|
||||||
|
|
||||||
test_lifetimes();
|
test_lifetimes();
|
||||||
// test eq
|
|
||||||
assert!(type_eq::<u64, u64>());
|
|
||||||
|
|
||||||
// test neq
|
|
||||||
assert!(!type_eq::<u64, usize>());
|
|
||||||
|
|
||||||
// test weirder lifetime things
|
// test weirder lifetime things
|
||||||
assert!(type_eq::<OwnedMutSlice<u8>, OwnedMutSlice<u8>>());
|
assert!(type_eq::<OwnedMutSlice<u8>, OwnedMutSlice<u8>>());
|
||||||
assert!(!type_eq::<OwnedMutSlice<u8>, OwnedMutSlice<u32>>());
|
assert!(!type_eq::<OwnedMutSlice<u8>, OwnedMutSlice<u32>>());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user