name: Fuzz
on:
schedule:
- cron: "0 4 * * *"
workflow_dispatch:
inputs:
seconds:
description: "Seconds per fuzz target"
required: false
default: "300"
pull_request:
paths:
- "fuzz/**"
- "src/fuzzing.rs"
- "src/lib.rs"
- "src/core/hlc.rs"
- "src/core/property/**"
- "src/core/temporal.rs"
- "src/storage/historical/**"
- "src/storage/wal/**"
- "tests/fuzz_infrastructure.rs"
- "Cargo.toml"
- "Cargo.lock"
- ".github/workflows/fuzz.yml"
permissions:
contents: read
jobs:
fuzz:
name: ${{ matrix.target }}
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
target:
- wal_entry_parsing
- wal_replay
- temporal_reconstruction
- property_serialization
- timestamp_arithmetic
env:
FUZZ_SECONDS: ${{ github.event.inputs.seconds || '60' }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Rust stable
uses: dtolnay/rust-toolchain@stable
- name: Install Rust nightly
uses: dtolnay/rust-toolchain@nightly
- name: Cache cargo artifacts
uses: actions/cache@v5
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
fuzz/target/
key: ${{ runner.os }}-fuzz-${{ hashFiles('Cargo.lock', 'fuzz/Cargo.toml') }}
- name: Install cargo-fuzz
run: |
if ! command -v cargo-fuzz >/dev/null 2>&1; then
cargo +stable install cargo-fuzz --locked
fi
- name: Run fuzz target with AddressSanitizer
run: |
cargo +nightly fuzz run --sanitizer address "${{ matrix.target }}" -- -max_total_time="${FUZZ_SECONDS}"
- name: Upload crash artifacts
if: failure()
uses: actions/upload-artifact@v7
with:
name: fuzz-artifacts-${{ matrix.target }}
path: fuzz/artifacts/${{ matrix.target }}/
if-no-files-found: ignore
- name: Write fuzz dashboard summary
if: always()
run: |
{
echo "## Fuzz target: ${{ matrix.target }}"
echo ""
echo "- Duration: ${FUZZ_SECONDS}s"
echo "- Sanitizer: address"
echo "- Corpus: fuzz/corpus/${{ matrix.target }}"
echo "- Crash artifacts: fuzz/artifacts/${{ matrix.target }}"
} >> "${GITHUB_STEP_SUMMARY}"