diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml index 45a8d95563c..49758ac260e 100644 --- a/.github/workflows/fuzz.yml +++ b/.github/workflows/fuzz.yml @@ -21,8 +21,7 @@ jobs: uses: ./.github/workflows/run-fuzzer.yml with: fuzz_target: file_io - family: "m8g.large" - image: "ubuntu24-full-arm64" + jobs: 16 secrets: R2_FUZZ_ACCESS_KEY_ID: ${{ secrets.R2_FUZZ_ACCESS_KEY_ID }} R2_FUZZ_SECRET_ACCESS_KEY: ${{ secrets.R2_FUZZ_SECRET_ACCESS_KEY }} @@ -72,8 +71,7 @@ jobs: uses: ./.github/workflows/run-fuzzer.yml with: fuzz_target: array_ops - family: "m8g.large" - image: "ubuntu24-full-arm64" + jobs: 16 secrets: R2_FUZZ_ACCESS_KEY_ID: ${{ secrets.R2_FUZZ_ACCESS_KEY_ID }} R2_FUZZ_SECRET_ACCESS_KEY: ${{ secrets.R2_FUZZ_SECRET_ACCESS_KEY }} @@ -109,8 +107,7 @@ jobs: uses: ./.github/workflows/run-fuzzer.yml with: fuzz_target: compress_roundtrip - family: "m8g.large" - image: "ubuntu24-full-arm64" + jobs: 16 secrets: R2_FUZZ_ACCESS_KEY_ID: ${{ secrets.R2_FUZZ_ACCESS_KEY_ID }} R2_FUZZ_SECRET_ACCESS_KEY: ${{ secrets.R2_FUZZ_SECRET_ACCESS_KEY }} @@ -123,9 +120,9 @@ jobs: uses: ./.github/workflows/run-fuzzer.yml with: fuzz_target: compress_gpu - family: "g4dn" - image: "ubuntu24-gpu-x64" + runner: gpu extra_features: "cuda" + jobs: 8 secrets: R2_FUZZ_ACCESS_KEY_ID: ${{ secrets.R2_FUZZ_ACCESS_KEY_ID }} R2_FUZZ_SECRET_ACCESS_KEY: ${{ secrets.R2_FUZZ_SECRET_ACCESS_KEY }} diff --git a/.github/workflows/run-fuzzer.yml b/.github/workflows/run-fuzzer.yml index d32478c2097..cef97a52e4e 100644 --- a/.github/workflows/run-fuzzer.yml +++ b/.github/workflows/run-fuzzer.yml @@ -12,21 +12,21 @@ on: required: false type: number default: 7200 - family: - description: "Runner family (e.g., m8g.large for CPU, g5+g4dn+g6 for GPU)" + runner: + description: "Runner name from .github-private runs-on.yml (e.g., arm64-medium, gpu)" required: false type: string - default: "m8g.large" - image: - description: "Runner image (e.g., ubuntu24-full-arm64, ubuntu24-gpu-x64)" - required: false - type: string - default: "ubuntu24-full-arm64" + default: "arm64-medium" extra_features: description: "Extra cargo features to enable (e.g., cuda)" required: false type: string default: "" + jobs: + description: "Number of parallel fuzzing jobs (libfuzzer -fork=N). Set to match available vCPUs." + required: false + type: number + default: 1 outputs: crashes_found: description: "Whether crashes were found" @@ -52,7 +52,7 @@ jobs: timeout-minutes: 230 # almost 4 hours runs-on: >- ${{ github.repository == 'vortex-data/vortex' - && format('runs-on={0}/runner=arm64-medium/disk=large/tag={1}-fuzz', github.run_id, inputs.fuzz_target) + && format('runs-on={0}/runner={1}/disk=large/tag={2}-fuzz', github.run_id, inputs.runner, inputs.fuzz_target) || 'ubuntu-latest' }} outputs: crashes_found: ${{ steps.check.outputs.crashes_found }} @@ -108,11 +108,15 @@ jobs: if [ -n "${{ inputs.extra_features }}" ]; then FEATURES_FLAG="--features ${{ inputs.extra_features }}" fi + FORK_FLAG="" + if [ "${{ inputs.jobs }}" -gt 1 ]; then + FORK_FLAG="-fork=${{ inputs.jobs }}" + fi RUSTFLAGS="--cfg vortex_nightly" RUST_BACKTRACE=1 \ cargo +$NIGHTLY_TOOLCHAIN fuzz run --release --debug-assertions \ $FEATURES_FLAG \ ${{ inputs.fuzz_target }} -- \ - -max_total_time=${{ inputs.max_time }} -rss_limit_mb=0 \ + $FORK_FLAG -max_total_time=${{ inputs.max_time }} -rss_limit_mb=0 \ 2>&1 | tee fuzz_output.log continue-on-error: true @@ -137,6 +141,23 @@ jobs: echo "No crashes found" fi + - name: Reproduce crash for full output + if: steps.check.outputs.crashes_found == 'true' && inputs.jobs > 1 + run: | + # In fork mode, child output (backtrace, panic message) is not captured in + # fuzz_output.log. Replay the crashing input in single-process mode to get + # the full output for the crash reporting pipeline. + FEATURES_FLAG="" + if [ -n "${{ inputs.extra_features }}" ]; then + FEATURES_FLAG="--features ${{ inputs.extra_features }}" + fi + RUSTFLAGS="--cfg vortex_nightly" RUST_BACKTRACE=1 \ + cargo +$NIGHTLY_TOOLCHAIN fuzz run --release --debug-assertions \ + $FEATURES_FLAG \ + ${{ inputs.fuzz_target }} \ + "${{ steps.check.outputs.first_crash }}" \ + 2>&1 | tee fuzz_output.log || true + - name: Archive crash artifacts id: upload_artifacts if: steps.check.outputs.crashes_found == 'true'