183 lines
4.4 KiB
Markdown
183 lines
4.4 KiB
Markdown
# Fuzz Testing for Announcement
|
|
|
|
This directory contains fuzz testing infrastructure using [cargo-fuzz](https://github.com/rust-fuzz/cargo-fuzz) and libFuzzer.
|
|
|
|
## Overview
|
|
|
|
We have 4 fuzz targets that test different aspects of the `announcement` library:
|
|
|
|
1. **fuzz_announce** - Tests the announce operation with various data types and patterns
|
|
2. **fuzz_close** - Tests close/drop scenarios and the closed detection API
|
|
3. **fuzz_listen** - Tests listener operations (try_listen, is_announced, etc.)
|
|
4. **fuzz_concurrent** - Tests concurrent access patterns with multiple threads
|
|
|
|
## Prerequisites
|
|
|
|
Fuzzing requires nightly Rust and cargo-fuzz:
|
|
|
|
```bash
|
|
rustup install nightly
|
|
cargo install cargo-fuzz
|
|
```
|
|
|
|
## Running Fuzz Tests
|
|
|
|
Run a single fuzz target:
|
|
|
|
```bash
|
|
cargo +nightly fuzz run fuzz_announce
|
|
```
|
|
|
|
Run with a time limit (recommended for CI):
|
|
|
|
```bash
|
|
cargo +nightly fuzz run fuzz_announce -- -max_total_time=60
|
|
```
|
|
|
|
Run with a specific number of iterations:
|
|
|
|
```bash
|
|
cargo +nightly fuzz run fuzz_announce -- -runs=10000
|
|
```
|
|
|
|
Run all fuzz targets sequentially:
|
|
|
|
```bash
|
|
for target in fuzz_announce fuzz_close fuzz_listen fuzz_concurrent; do
|
|
echo "Running $target..."
|
|
cargo +nightly fuzz run $target -- -runs=10000
|
|
done
|
|
```
|
|
|
|
## Continuous Fuzzing
|
|
|
|
For deeper testing, run fuzz targets for extended periods:
|
|
|
|
```bash
|
|
# Run overnight (8 hours)
|
|
cargo +nightly fuzz run fuzz_concurrent -- -max_total_time=28800
|
|
|
|
# Run until crash (or Ctrl+C)
|
|
cargo +nightly fuzz run fuzz_announce
|
|
```
|
|
|
|
## Understanding Output
|
|
|
|
Fuzzer output includes:
|
|
|
|
- `cov: X` - Code coverage (number of edges covered)
|
|
- `ft: X` - Feature coverage (number of unique code paths)
|
|
- `corp: X/Yb` - Corpus size (X inputs, Y bytes total)
|
|
- `exec/s: X` - Executions per second
|
|
|
|
If a crash is found:
|
|
|
|
- Crash input is saved to `artifacts/FUZZ_TARGET/crash-*`
|
|
- Reproduce with: `cargo +nightly fuzz run FUZZ_TARGET artifacts/FUZZ_TARGET/crash-*`
|
|
|
|
## Fuzz Target Details
|
|
|
|
### fuzz_announce
|
|
|
|
Tests basic announce operations:
|
|
- Various data types (Vec<u8>, String, u64, Arc<T>)
|
|
- Multiple listeners receiving the same data
|
|
- is_announced() flag behavior
|
|
- Data integrity verification
|
|
|
|
### fuzz_close
|
|
|
|
Tests closed detection API:
|
|
- Drop without announce
|
|
- Explicit close() call
|
|
- Announce then drop (should not be closed)
|
|
- Multiple listeners with close
|
|
- Listener created after close
|
|
|
|
### fuzz_listen
|
|
|
|
Tests listener operations:
|
|
- try_listen() before and after announce
|
|
- Multiple try_listen() calls
|
|
- Multiple listeners
|
|
- Clone and listener creation
|
|
- is_announced() vs is_closed() states
|
|
|
|
### fuzz_concurrent
|
|
|
|
Tests thread safety:
|
|
- Multiple threads with concurrent listeners
|
|
- Concurrent clone and listener creation
|
|
- Concurrent is_announced() checks
|
|
- Concurrent is_closed() checks
|
|
- Various timing patterns with barriers
|
|
|
|
## Adding New Fuzz Targets
|
|
|
|
1. Create a new file in `fuzz_targets/` (e.g., `fuzz_new_feature.rs`)
|
|
2. Use the template:
|
|
|
|
```rust
|
|
#![no_main]
|
|
use libfuzzer_sys::fuzz_target;
|
|
use announcement::Announcement;
|
|
|
|
fuzz_target!(|data: &[u8]| {
|
|
// Your fuzz test here
|
|
});
|
|
```
|
|
|
|
3. Add to `fuzz/Cargo.toml`:
|
|
|
|
```toml
|
|
[[bin]]
|
|
name = "fuzz_new_feature"
|
|
path = "fuzz_targets/fuzz_new_feature.rs"
|
|
test = false
|
|
doc = false
|
|
bench = false
|
|
```
|
|
|
|
4. Build and run:
|
|
|
|
```bash
|
|
cargo +nightly fuzz build
|
|
cargo +nightly fuzz run fuzz_new_feature
|
|
```
|
|
|
|
## CI Integration
|
|
|
|
Fuzzing runs automatically in CI on every push/PR:
|
|
- Each target runs for 60-120 seconds
|
|
- Targets run 1,000-10,000 iterations minimum
|
|
- Any crashes fail the build
|
|
|
|
See `.github/workflows/ci.yml` for details.
|
|
|
|
## Corpus Management
|
|
|
|
The fuzzer builds a corpus of interesting inputs in `corpus/FUZZ_TARGET/`. These inputs:
|
|
- Are automatically discovered during fuzzing
|
|
- Can be committed to Git for regression testing
|
|
- Help future fuzzing sessions start with good coverage
|
|
|
|
To minimize the corpus:
|
|
|
|
```bash
|
|
cargo +nightly fuzz cmin fuzz_announce
|
|
```
|
|
|
|
## Tips
|
|
|
|
1. **Start with short runs** - Use `-max_total_time=60` to catch obvious bugs quickly
|
|
2. **Run overnight** - For thorough testing, run for hours or days
|
|
3. **Check coverage** - Monitor `cov:` values to ensure good code coverage
|
|
4. **Save crashes** - Commit crash artifacts as regression tests
|
|
5. **Update regularly** - Re-run fuzzing when adding new features
|
|
|
|
## References
|
|
|
|
- [cargo-fuzz book](https://rust-fuzz.github.io/book/cargo-fuzz.html)
|
|
- [libFuzzer documentation](https://llvm.org/docs/LibFuzzer.html)
|
|
- [Fuzzing in Rust](https://rust-fuzz.github.io/book/)
|