105 lines
3.7 KiB
YAML
105 lines
3.7 KiB
YAML
# Extended robustness: corpus render-stability sweep + libFuzzer run.
|
|
#
|
|
# DELIBERATELY ISOLATED from the main CI gate:
|
|
# - never triggers on push or pull_request, so it can NEVER block a merge,
|
|
# push, or pull;
|
|
# - the whole job is continue-on-error, so a crash finding or a build/runner
|
|
# problem reports red here but does not fail any required check;
|
|
# - runs on a weekly schedule and on manual dispatch only.
|
|
#
|
|
# A full 24h fuzz run needs a self-hosted runner (GitHub-hosted runners cap a job
|
|
# at 6h). Use the workflow_dispatch `duration_seconds` input for that; the weekly
|
|
# schedule does a short smoke instead.
|
|
|
|
name: Fuzz & corpus sweep
|
|
|
|
on:
|
|
schedule:
|
|
- cron: "0 3 * * 0" # Sundays 03:00 UTC — short smoke
|
|
workflow_dispatch:
|
|
inputs:
|
|
duration_seconds:
|
|
description: "libFuzzer -max_total_time (e.g. 1800 smoke, 86400 for 24h on a self-hosted runner)"
|
|
default: "1800"
|
|
sanitizers:
|
|
description: "Sanitizer set (fuzzer,address,undefined needs an ASan/UBSan-built PDFium; fuzzer = coverage-only)"
|
|
default: "fuzzer,address,undefined"
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
concurrency:
|
|
group: fuzz-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
fuzz:
|
|
# Non-blocking by construction: nothing depends on this job and it is allowed to fail.
|
|
continue-on-error: true
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 1500 # permits a 24h dispatch on a self-hosted runner; hosted runners stop at 6h
|
|
env:
|
|
VCPKG_DEFAULT_BINARY_CACHE: ${{ github.workspace }}/.vcpkg-cache
|
|
FUZZ_SANITIZERS: ${{ github.event.inputs.sanitizers || 'fuzzer' }}
|
|
FUZZ_DURATION: ${{ github.event.inputs.duration_seconds || '600' }}
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Install Ninja + Clang
|
|
shell: bash
|
|
run: |
|
|
sudo apt-get update
|
|
sudo apt-get install -y ninja-build clang
|
|
|
|
- name: Locate vcpkg
|
|
shell: bash
|
|
run: |
|
|
echo "VCPKG_ROOT=$VCPKG_INSTALLATION_ROOT" >> "$GITHUB_ENV"
|
|
mkdir -p "$VCPKG_DEFAULT_BINARY_CACHE"
|
|
|
|
- name: Cache vcpkg artifacts
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: ${{ env.VCPKG_DEFAULT_BINARY_CACHE }}
|
|
key: vcpkg-fuzz-${{ hashFiles('vcpkg.json') }}
|
|
restore-keys: vcpkg-fuzz-
|
|
|
|
- name: Pin vcpkg dependency baseline
|
|
shell: bash
|
|
run: |
|
|
if ! grep -q '"builtin-baseline"' vcpkg.json; then
|
|
"$VCPKG_ROOT/vcpkg" x-update-baseline --add-initial-baseline
|
|
fi
|
|
|
|
- name: Configure (fuzz-linux)
|
|
run: cmake --preset fuzz-linux -DPDFENGINE_FUZZ_SANITIZERS="$FUZZ_SANITIZERS"
|
|
|
|
- name: Build fuzzer
|
|
run: cmake --build --preset fuzz-linux --target pdfengine_fuzz
|
|
|
|
- name: Fetch corpus (pinned + hash-verified)
|
|
shell: bash
|
|
run: python3 scripts/fetch_corpus.py --manifest tests/regression/corpus-manifest.json || echo "corpus fetch failed (network) — continuing with committed corpus"
|
|
|
|
- name: Render-stability sweep (replay every corpus PDF once)
|
|
shell: bash
|
|
run: |
|
|
BIN=out/build/fuzz-linux/bin/pdfengine_fuzz
|
|
mkdir -p engine/fuzz/artifacts
|
|
"$BIN" -runs=0 -artifact_prefix=engine/fuzz/artifacts/ corpus/ corpus/fuzz/ || true
|
|
|
|
- name: Fuzz run
|
|
shell: bash
|
|
run: |
|
|
BIN=out/build/fuzz-linux/bin/pdfengine_fuzz
|
|
"$BIN" -max_total_time="$FUZZ_DURATION" -print_final_stats=1 \
|
|
-artifact_prefix=engine/fuzz/artifacts/ corpus/fuzz/ corpus/ || true
|
|
|
|
- name: Upload crash artifacts
|
|
if: always()
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: fuzz-artifacts
|
|
path: engine/fuzz/artifacts/
|
|
if-no-files-found: ignore
|