diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 8904b329e9..0f04045694 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -91,7 +91,7 @@ jobs: # ---- doc check ---- - name: Build Docs - run: cargo doc + run: cargo +nightly doc --all-features - name: Test Docs run: cargo +nightly test --doc --all-features diff --git a/README.md b/README.md index a1d499445b..b47dd2ad4d 100644 --- a/README.md +++ b/README.md @@ -50,31 +50,31 @@ The LLVM tools (including clang, clang++) are needed (newer than LLVM 11.0.0 but - Cargo-make We use cargo-make to build the fuzzers in `fuzzers/` directory. You can install it with -``` +```sh cargo install cargo-make ``` 2. Clone the LibAFL repository with -``` +```sh git clone https://github.com/AFLplusplus/LibAFL ``` 3. Build the library using -``` +```sh cargo build --release ``` 4. Build the API documentation with -``` +```sh cargo doc ``` 5. Browse the LibAFL book (WIP!) with (requires [mdbook](https://rust-lang.github.io/mdBook/index.html)) -``` +```sh cd docs && mdbook serve ``` @@ -82,9 +82,11 @@ We collect all example fuzzers in [`./fuzzers`](./fuzzers/). Be sure to read their documentation (and source), this is *the natural way to get started!* You can run each example fuzzer with -``` + +```sh cargo make run ``` + as long as the fuzzer directory has `Makefile.toml` file. The best-tested fuzzer is [`./fuzzers/libfuzzer_libpng`](./fuzzers/libfuzzer_libpng), a multicore libfuzzer-like fuzzer using LibAFL for a libpng harness. diff --git a/libafl/Cargo.toml b/libafl/Cargo.toml index 78c1e3ff49..e130ec56a0 100644 --- a/libafl/Cargo.toml +++ b/libafl/Cargo.toml @@ -12,48 +12,116 @@ edition = "2021" categories = ["development-tools::testing", "emulators", "embedded", "os", "no-std"] [package.metadata.docs.rs] +features = ["document-features"] all-features = true [features] default = ["std", "derive", "llmp_compression", "llmp_small_maps", "llmp_broker_timeouts", "rand_trait", "fork", "prelude", "gzip", "regex", "serdeany_autoreg", "tui_monitor"] -std = ["serde_json", "serde_json/std", "nix", "serde/std", "bincode", "wait-timeout", "uuid", "backtrace", "serial_test", "libafl_bolts/std", "typed-builder"] # print, env, launcher ... support -derive = ["libafl_derive", "libafl_bolts/derive"] # provide derive(SerdeAny) macro. -fork = ["libafl_bolts/derive"] # uses the fork() syscall to spawn children, instead of launching a new command, if supported by the OS (has no effect on Windows, no_std). -rand_trait = ["libafl_bolts/rand_trait"] # If set, libafl's rand implementations will implement `rand::Rng` -introspection = [] # Include performance statistics of the fuzzing pipeline -concolic_mutation = ["z3"] # include a simple concolic mutator based on z3 + +#! # Feature Flags +#! ### General Features + +## Enables features that need rust's `std` lib to work, like print, env, ... support +std = ["serde_json", "serde_json/std", "nix", "serde/std", "bincode", "wait-timeout", "uuid", "backtrace", "serial_test", "libafl_bolts/std", "typed-builder"] + +## Collects performance statistics of the fuzzing pipeline and displays it on `Monitor` components +introspection = [] + +## Will build the `pyo3` bindings python = ["pyo3", "concat-idents", "libafl_bolts/python"] -prelude = ["libafl_bolts/prelude"] # Expose libafl::prelude for access without additional using directives -tui_monitor = ["tui", "crossterm"] # enable TuiMonitor with crossterm -prometheus_monitor = ["std", "async-std", "prometheus-client", "tide", "futures"] -cli = ["libafl_bolts/cli"] # expose libafl_bolts::cli for easy commandline parsing -qemu_cli = ["cli", "libafl_bolts/qemu_cli"] # Commandline flags for qemu-based fuzzers -frida_cli = ["cli", "libafl_bolts/frida_cli"] # Commandline flags for frida-based fuzzers -afl_exec_sec = [] # calculate exec/sec like AFL + +## Expose `libafl::prelude` for access without additional using directives +prelude = ["libafl_bolts/prelude"] + +## Calculate exec/sec like AFL, using 5 second time windows +afl_exec_sec = [] + +## Stores the backtraces of all generated `Error`s. Good for debugging, but may come with a slight performance hit. errors_backtrace = ["libafl_bolts/errors_backtrace"] -cmin = ["z3"] # corpus minimisation -corpus_btreemap = [] # Switches from HashMap to BTreeMap for CorpusId -gzip = ["libafl_bolts/gzip"] # Enables gzip compression in certain parts of the lib -regex = ["std", "dep:regex"] # enables the NaiveTokenizer and StacktraceObserver -casr = ["libcasr", "std", "regex"] # enables deduplication based on libcasr for StacktraceObserver -tcp_manager = ["tokio", "std"] # A simple EventManager proxying everything via TCP + +## Switches from `HashMap` to `BTreeMap` for `CorpusId` +corpus_btreemap = [] + +## Enables gzip compression in certain parts of the lib +gzip = ["libafl_bolts/gzip"] + +## If set, will use the `fork()` syscall to spawn children, instead of launching a new command, if supported by the OS (has no effect on `Windows`). +fork = ["libafl_bolts/derive"] + +## Collected stats to decide if observers must be serialized or not (which should reduce mem use and increase speed) adaptive_serialization = [] -# features hiding dependencies licensed under GPL -gpl = [] -# features hiding dependencies licensed under AGPL -agpl = ["gpl", "nautilus"] -nautilus = ["grammartec", "std", "serde_json/std"] -# SerdeAny features -serdeany_autoreg = ["libafl_bolts/serdeany_autoreg"] # Automatically register all `#[derive(SerdeAny)]` types at startup. +#! ## Additional Components -# LLMP features -llmp_bind_public = ["libafl_bolts/llmp_bind_public"] # If set, llmp will bind to 0.0.0.0, allowing cross-device communication. Binds to localhost by default. -llmp_compression = ["libafl_bolts/llmp_compression"] # llmp compression using GZip -llmp_debug = ["libafl_bolts/llmp_debug"] # Enables debug output for LLMP +## Enables `TcpEventManager`, a simple EventManager proxying everything via TCP. This uses `tokio`. +tcp_manager = ["tokio", "std"] + +## Enables the `NaiveTokenizer` and `StacktraceObserver` +regex = ["std", "dep:regex"] + +## Enables deduplication based on `libcasr` for `StacktraceObserver` +casr = ["libcasr", "std", "regex"] + +## Enables features for corpus minimization +cmin = ["z3"] + +## Enables the `PrometheusMonitor` which will monitor stats via UDP, for `Grafana` and others. +prometheus_monitor = ["std", "async-std", "prometheus-client", "tide", "futures"] + +## Include a simple concolic mutator based on z3 +concolic_mutation = ["z3"] + +## Enable the fancy TuiMonitor for a termanal UI using crossterm +tui_monitor = ["tui", "crossterm"] + + +#! ## LibAFL-Bolts Features + +## Provide the `#[derive(SerdeAny)]` macro. +derive = ["libafl_derive", "libafl_bolts/derive"] # provide `derive(SerdeAny) macro. + +## Expose `libafl_bolts::cli` for easy commandline parsing of common fuzzer settings +cli = ["libafl_bolts/cli"] + +## Enables extra commandline flags for qemu-based fuzzers in `cli` +qemu_cli = ["cli", "libafl_bolts/qemu_cli"] + +## Enables extra commandline flags for frida-based fuzzers in `cli` +frida_cli = ["cli", "libafl_bolts/frida_cli"] + +## If set, libafl_bolt's `rand` implementations will implement `rand::Rng` +rand_trait = ["libafl_bolts/rand_trait"] + +#! ### SerdeAny features + +## Automatically register all `#[derive(SerdeAny)]` types at startup. +serdeany_autoreg = ["libafl_bolts/serdeany_autoreg"] + +#! ### LLMP features + +## The broker loop will yield occasionally, even without status messages from client nodes +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"] + +## Enables llmp compression using GZip +llmp_compression = ["libafl_bolts/llmp_compression"] + +## Enables debug output for LLMP (also needs a `logger` installed) +llmp_debug = ["libafl_bolts/llmp_debug"] + +## Reduces the initial map size for llmp llmp_small_maps = ["libafl_bolts/llmp_small_maps"] # reduces initial map size for llmp -llmp_broker_timeouts = ["std"] # The broker loop will yield occasionally, even without status messages from client nodes + +#! ## License-Changing Dependencies(!) + +## Enables features hiding dependencies licensed under `AGPL` +agpl = ["nautilus"] + +## Enables the [`Nautilus`](https://wcventure.github.io/FuzzingPaper/Paper/NDSS19_Nautilus.pdf) Grammar Mutator (AGPL-licensed) +nautilus = ["grammartec", "std", "serde_json/std"] [build-dependencies] rustversion = "1.0" @@ -107,6 +175,9 @@ libcasr = { version = "2.7", optional = true} # optional-dev deps (change when target.'cfg(accessible(::std))'.test-dependencies will be stable) serial_test = { version = "2", optional = true, default-features = false, features = ["logging"] } +# Document all features of this crate (for `cargo doc`) +document-features = { version = "0.2" } + # AGPL # !!! this create requires nightly grammartec = { version = "0.3", optional = true } diff --git a/libafl/src/events/tcp.rs b/libafl/src/events/tcp.rs index fb70404ec1..887a985071 100644 --- a/libafl/src/events/tcp.rs +++ b/libafl/src/events/tcp.rs @@ -335,8 +335,7 @@ where } } -/// An [`EventManager`] that forwards all events to other attached fuzzers on shared maps or via tcp, -/// using low-level message passing, [`libafl_bolts::tcp`]. +/// An [`EventManager`] that forwards all events to other attached via tcp. pub struct TcpEventManager where S: UsesInput, @@ -844,7 +843,7 @@ pub enum ManagerKind { /// The CPU core ID of this client cpu_core: Option, }, - /// A [`tcp::TcpBroker`], forwarding the packets of local clients. + /// A broker, forwarding all packets of local clients via TCP. Broker, } diff --git a/libafl/src/lib.rs b/libafl/src/lib.rs index 8d98cf47bf..0f6de21f8d 100644 --- a/libafl/src/lib.rs +++ b/libafl/src/lib.rs @@ -1,7 +1,9 @@ /*! Welcome to `LibAFL` */ - +#![doc = include_str!("../../README.md")] +/*! */ +#![doc = document_features::document_features!()] #![allow(incomplete_features)] #![no_std] // For `type_eq` diff --git a/libafl_bolts/Cargo.toml b/libafl_bolts/Cargo.toml index ed411254f2..72c23c5c66 100644 --- a/libafl_bolts/Cargo.toml +++ b/libafl_bolts/Cargo.toml @@ -12,30 +12,67 @@ edition = "2021" categories = ["development-tools::testing", "emulators", "embedded", "os", "no-std"] [package.metadata.docs.rs] +features = ["document-features"] all-features = true [features] 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", "uuid", "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. -rand_trait = ["rand_core"] # If set, libafl's rand implementations will implement `rand::Rng` + +#! # Feature Flags +#! ### General Features + +## Enables features that need rust's `std` lib to work, like print, env, ... support +std = ["serde_json", "serde_json/std", "hostname", "nix", "serde/std", "uuid", "backtrace", "uds", "serial_test", "alloc"] + +## Enables all features that allocate in `no_std` +alloc = ["serde/alloc", "hashbrown", "postcard", "erased-serde/alloc", "ahash"] + +## Provide the `#[derive(SerdeAny)]` macro. +derive = ["libafl_derive"] + +## If set, libafl_bolt's `rand` implementations will implement `rand::Rng` +rand_trait = ["rand_core"] + +## Will build the `pyo3` bindings python = ["pyo3", "std"] -prelude = [] # Expose libafl::prelude for access without additional using directives -cli = ["clap"] # expose libafl_bolts::cli for easy commandline parsing -qemu_cli = ["cli"] # Commandline flagr for qemu-based fuzzers -frida_cli = ["cli"] # Commandline flags for frida-based fuzzers + +## Expose `libafl::prelude` for direct access to all types without additional `use` directives +prelude = [] + +## Expose `libafl_bolts::cli` for easy commandline parsing of common fuzzer settings +cli = ["clap"] + +## Enables extra commandline flags for qemu-based fuzzers in `cli` +qemu_cli = ["cli"] + +## Enables extra commandline flags for frida-based fuzzers in `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"] -gzip = ["miniz_oxide", "alloc"] # Enables gzip compression in certain parts of the lib -# SerdeAny features -serdeany_autoreg = ["ctor"] # Automatically register all `#[derive(SerdeAny)]` types at startup. +## Enables gzip compression in certain parts of the lib +gzip = ["miniz_oxide", "alloc"] -# LLMP features -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 = ["alloc", "gzip"] # llmp compression using GZip -llmp_debug = ["alloc"] # Enables debug output for LLMP -llmp_small_maps = ["alloc"] # reduces initial map size for llmp +#! ### SerdeAny features + +## 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"] + +## Reduces the initial map size for llmp +llmp_small_maps = ["alloc"] [build-dependencies] rustversion = "1.0" @@ -73,6 +110,9 @@ pyo3 = { version = "0.18.3", optional = true, features = ["serde", "macros"] } # optional-dev deps (change when target.'cfg(accessible(::std))'.test-dependencies will be stable) serial_test = { version = "2", optional = true, default-features = false, features = ["logging"] } +# Document all features of this crate (for `cargo doc`) +document-features = { version = "0.2" } + [target.'cfg(unix)'.dependencies] libc = "0.2" # For (*nix) libc uds = { version = "0.4", optional = true, default-features = false } diff --git a/libafl_bolts/src/lib.rs b/libafl_bolts/src/lib.rs index dd0ef89004..f6b9dc2ce2 100644 --- a/libafl_bolts/src/lib.rs +++ b/libafl_bolts/src/lib.rs @@ -1,9 +1,9 @@ -#![doc = include_str!("../README.md")] - /*! -Welcome to `LibAFL` +* Welcome to `LibAFL_bolts` */ - +#![doc = include_str!("../README.md")] +/*! */ +#![doc = document_features::document_features!()] #![allow(incomplete_features)] #![no_std] // For `type_eq` diff --git a/libafl_targets/src/sancov_8bit.rs b/libafl_targets/src/sancov_8bit.rs index 41f0e3998f..3bf623a932 100644 --- a/libafl_targets/src/sancov_8bit.rs +++ b/libafl_targets/src/sancov_8bit.rs @@ -52,11 +52,11 @@ mod observers { #[must_use] #[export_name = "counters_maps_observer"] - /// Create a new [`CountersMultiMapObserver`] of the [`COUNTERS_MAP`]. + /// Create a new [`CountersMultiMapObserver`] of the [`COUNTERS_MAPS`]. /// - /// This is a special [`MultiMapObserver`] for the [`COUNTERS_MAP`] and may be used when + /// This is a special [`libafl::observers::MultiMapObserver`] for the [`COUNTERS_MAPS`] and may be used when /// 8-bit counters are used for `SanitizerCoverage`. You can utilize this observer in a - /// [`HitcountsIterableMapObserver`] like so: + /// [`libafl::observers::HitcountsIterableMapObserver`] like so: /// /// ```rust,ignore /// use libafl::{