#!/usr/bin/env bash # Run libFuzzer targets via cargo-fuzz (LLVM coverage + mutation). # Usage: # ./scripts/fuzz-libfuzzer.sh # all targets, 60s each, sanitizer none (stable-friendly) # FUZZ_TIME=300 ./scripts/fuzz-libfuzzer.sh session_decrypt # FUZZ_RUNS=2000 ./scripts/fuzz-libfuzzer.sh # fixed iterations (e.g. CI), all targets # SANITIZER=address ./scripts/fuzz-libfuzzer.sh # needs nightly rustc (rustup) set -euo pipefail export PATH="${HOME}/.cargo/bin:${PATH}" ROOT="$(cd "$(dirname "$0")/.." && pwd)" cd "$ROOT" if ! command -v cargo-fuzz >/dev/null 2>&1; then echo "Install cargo-fuzz: cargo install cargo-fuzz" >&2 exit 1 fi FUZZ_TIME="${FUZZ_TIME:-60}" FUZZ_RUNS="${FUZZ_RUNS:-}" SANITIZER="${SANITIZER:-none}" discover_targets() { local list # `cargo fuzz list` reflects the targets registered in `fuzz/Cargo.toml`. # Keep target discovery dynamic so CI fuzz-smoke automatically covers new code. list="$(cargo fuzz list)" if [[ -z "$list" ]]; then echo "No fuzz targets found via 'cargo fuzz list'." >&2 exit 1 fi while IFS= read -r line; do [[ -n "$line" ]] && printf '%s\n' "$line" done <<<"$list" } run_one() { local name="$1" if [[ -n "$FUZZ_RUNS" ]]; then echo "=== cargo-fuzz: $name (-runs=${FUZZ_RUNS}, sanitizer=${SANITIZER}) ===" cargo fuzz run -s "$SANITIZER" "$name" -- -runs="$FUZZ_RUNS" -print_final_stats=1 else echo "=== cargo-fuzz: $name (max_total_time=${FUZZ_TIME}s, sanitizer=${SANITIZER}) ===" cargo fuzz run -s "$SANITIZER" "$name" -- -max_total_time="$FUZZ_TIME" -print_final_stats=1 fi } if [[ $# -gt 0 ]]; then for name in "$@"; do run_one "$name" done else while IFS= read -r name; do run_one "$name" done < <(discover_targets) fi