Repository navigation
chore(main): release 0.20.0 #468
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Fuzzing Smoke Tests | |
| on: | |
| pull_request: | |
| branches: [ main, develop ] | |
| paths: | |
| - 'rust/**' | |
| - '.github/workflows/fuzz-smoke.yml' | |
| permissions: | |
| contents: read | |
| pull-requests: read | |
| env: | |
| CARGO_TERM_COLOR: always | |
| RUST_BACKTRACE: 1 | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| fuzz-smoke: | |
| name: Fuzz Smoke Test (60s per target) | |
| runs-on: ubuntu-latest | |
| # Budget (cold): ~2 min rustup + ~10 min cargo-fuzz install + ~10 min | |
| # one-shot ASAN build of all targets + ~1 min per fuzz target (count derived | |
| # from `cargo fuzz list`, ~14 min today) + slack. rust-cache below skips the | |
| # install and most of the build on a warm run — this workflow is PR-only, so | |
| # a PR's first push is cold and later pushes to the same PR are warm. | |
| timeout-minutes: 45 | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 | |
| - name: Validate corpus layout | |
| run: | | |
| cd rust/fuzz | |
| # Every [[bin]] target must have committed seeds in corpus/<target>/ — | |
| # a target without them fuzzes cold from random bytes and the run is | |
| # far shallower than its green badge suggests. Pure bash, | |
| # fails loudly on a missing/empty seed directory or a blown 10MB | |
| # budget. Without this step the seed requirement is manual-only. | |
| # | |
| # Runs before the toolchain install deliberately: it needs only bash + | |
| # coreutils and reads files present straight from checkout, so putting | |
| # it here fails a missing seed directory in seconds instead of after | |
| # ~12 min of rustup + cargo-fuzz install. | |
| bash scripts/validate_corpus.sh | |
| - name: Install Rust nightly | |
| run: | | |
| # Pin nightly: cargo-fuzz's rustix dependency uses | |
| # rustc_layout_scalar_valid_range_* attributes reserved after | |
| # nightly-2026-04-27. Last known-good date. | |
| rustup toolchain install nightly-2026-04-27 | |
| rustup default nightly-2026-04-27 | |
| # After the toolchain step so the cache key hashes the pinned nightly, not | |
| # the image's stable. Caches ~/.cargo/bin (cargo-fuzz) and the fuzz crate's | |
| # dependency artifacts; the fuzz targets themselves always rebuild. | |
| - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 | |
| with: | |
| workspaces: rust/fuzz | |
| - name: Install cargo-fuzz | |
| # Version-pinned: a floating `cargo install` hands a hijacked cargo-fuzz | |
| # release immediate code exec on the CI runner. | |
| run: cargo install --locked cargo-fuzz --version 0.13.2 | |
| - name: Verify fuzz lockfile is current | |
| run: | | |
| cd rust/fuzz | |
| # `cargo fuzz build/run` have no --locked passthrough, so the committed | |
| # Cargo.lock is advisory to them: on any manifest/lock drift cargo would | |
| # silently re-resolve every transitive to newest-on-crates.io. This is | |
| # the only step that enforces the lock — it fails loudly on drift, and | |
| # warms the registry cache besides. | |
| cargo +nightly-2026-04-27 fetch --locked | |
| - name: Build all fuzz targets | |
| run: | | |
| cd rust/fuzz | |
| # One cargo invocation builds every [[bin]] target, sharing dependency | |
| # compilation. A target that fails to compile fails the job here. | |
| cargo +nightly-2026-04-27 fuzz build | |
| - name: Run fuzzing smoke tests | |
| id: fuzz | |
| run: | | |
| cd rust/fuzz | |
| # Create artifacts directory | |
| mkdir -p artifacts | |
| # Every target `cargo fuzz list` reports runs — no hand-maintained | |
| # allow-list in this workflow to drift out of date. | |
| # Resolve the list in a standalone assignment: `for t in $(cmd)` does | |
| # not propagate a failing $(cmd) under `set -e`, and an empty list | |
| # would loop zero times and go green having fuzzed nothing. | |
| TARGETS=$(cargo +nightly-2026-04-27 fuzz list) | |
| if [ -z "$TARGETS" ]; then | |
| echo "::error::cargo fuzz list returned no targets" | |
| exit 1 | |
| fi | |
| # `cargo fuzz list` enumerates the [[bin]] stanzas in Cargo.toml, NOT the | |
| # files in fuzz_targets/. So a new fuzz_targets/*.rs added without its | |
| # stanza is never built and never run, and this job still goes green — | |
| # the same silent-dark mode the old hardcoded array caused. Nothing in | |
| # cargo enforces that the two agree, so assert it here. Count only | |
| # fuzz_target! sources: validate_corpus.sh deliberately tolerates a | |
| # shared helper module in fuzz_targets/, and an unfiltered count would | |
| # fail this job on the same tree that just passed validation — 12 | |
| # minutes later, with a misleading "add the missing stanza" error. | |
| SRC_COUNT=$(grep -l 'fuzz_target!' fuzz_targets/*.rs | wc -l) | |
| LIST_COUNT=$(printf '%s\n' "$TARGETS" | wc -l) | |
| if [ "$SRC_COUNT" -ne "$LIST_COUNT" ]; then | |
| echo "::error::fuzz_targets/ holds $SRC_COUNT sources but Cargo.toml declares $LIST_COUNT [[bin]] targets — add the missing [[bin]] stanza so the new target actually runs" | |
| exit 1 | |
| fi | |
| # A non-zero exit (crash found, or target failed to run) fails the | |
| # job immediately: green must mean "fuzzed and clean". | |
| for target in $TARGETS; do | |
| echo "Fuzzing $target..." | |
| cargo +nightly-2026-04-27 fuzz run "$target" -- -max_total_time=60 | |
| done | |
| # Belt-and-braces: fail on any crash artifact even if the runs above | |
| # all exited zero. | |
| if find artifacts -name 'crash-*' -o -name 'timeout-*' -o -name 'oom-*' | grep -q .; then | |
| echo "::error::Fuzzing discovered crashes or errors. See artifacts for details." | |
| exit 1 | |
| fi | |
| echo "All fuzz targets completed without crashes" | |
| - name: Upload crash artifacts | |
| if: failure() | |
| uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7 | |
| with: | |
| name: fuzz-crash-artifacts | |
| path: rust/fuzz/artifacts/ | |
| # Short window deliberately: this repo is public and this job runs on | |
| # pull_request, so the artifact is a working libFuzzer reproducer for an | |
| # unfixed defect in the shipped compression/AES-GCM path, downloadable by | |
| # anyone. 3 days is enough to triage; 30 is a month-long public window. | |
| retention-days: 3 | |
| if-no-files-found: warn |