Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions .github/workflows/fuzz.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ jobs:
uses: ./.github/workflows/run-fuzzer.yml
with:
fuzz_target: file_io
family: "m8g.large"
image: "ubuntu24-full-arm64"
secrets:
R2_FUZZ_ACCESS_KEY_ID: ${{ secrets.R2_FUZZ_ACCESS_KEY_ID }}
R2_FUZZ_SECRET_ACCESS_KEY: ${{ secrets.R2_FUZZ_SECRET_ACCESS_KEY }}
Expand Down Expand Up @@ -69,6 +71,8 @@ jobs:
uses: ./.github/workflows/run-fuzzer.yml
with:
fuzz_target: array_ops
family: "m8g.large"
image: "ubuntu24-full-arm64"
secrets:
R2_FUZZ_ACCESS_KEY_ID: ${{ secrets.R2_FUZZ_ACCESS_KEY_ID }}
R2_FUZZ_SECRET_ACCESS_KEY: ${{ secrets.R2_FUZZ_SECRET_ACCESS_KEY }}
Expand Down Expand Up @@ -103,6 +107,45 @@ jobs:
uses: ./.github/workflows/run-fuzzer.yml
with:
fuzz_target: compress_roundtrip
family: "m8g.large"
image: "ubuntu24-full-arm64"
secrets:
R2_FUZZ_ACCESS_KEY_ID: ${{ secrets.R2_FUZZ_ACCESS_KEY_ID }}
R2_FUZZ_SECRET_ACCESS_KEY: ${{ secrets.R2_FUZZ_SECRET_ACCESS_KEY }}

# ============================================================================
# GPU Compress Fuzzer (CUDA)
# ============================================================================
gpu_compress_fuzz:
name: "GPU Compress Fuzz"
uses: ./.github/workflows/run-fuzzer.yml
with:
fuzz_target: compress_gpu
family: "g4dn"
image: "ubuntu24-gpu-x64"
extra_features: "cuda"
secrets:
R2_FUZZ_ACCESS_KEY_ID: ${{ secrets.R2_FUZZ_ACCESS_KEY_ID }}
R2_FUZZ_SECRET_ACCESS_KEY: ${{ secrets.R2_FUZZ_SECRET_ACCESS_KEY }}

# report-gpu-compress-fuzz-failures:
# name: "Report GPU Compress Fuzz Failures"
# needs: gpu_compress_fuzz
# if: always() && needs.gpu_compress_fuzz.outputs.crashes_found == 'true'
# permissions:
# issues: write
# contents: read
# id-token: write
# pull-requests: read
# uses: ./.github/workflows/report-fuzz-crash.yml
# with:
# fuzz_target: compress_gpu
# crash_file: ${{ needs.gpu_compress_fuzz.outputs.first_crash_name }}
# artifact_url: ${{ needs.gpu_compress_fuzz.outputs.artifact_url }}
# artifact_name: compress_gpu-crash-artifacts
# logs_artifact_name: compress_gpu-logs
# branch: ${{ github.ref_name }}
# commit: ${{ github.sha }}
# secrets:
# claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
# gh_token: ${{ secrets.GITHUB_TOKEN }}
39 changes: 32 additions & 7 deletions .github/workflows/run-fuzzer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,21 @@ on:
required: false
type: number
default: 7200
family:
description: "Runner family (e.g., m8g.large for CPU, g5+g4dn+g6 for 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"
extra_features:
description: "Extra cargo features to enable (e.g., cuda)"
required: false
type: string
default: ""
outputs:
crashes_found:
description: "Whether crashes were found"
Expand All @@ -34,20 +49,15 @@ jobs:
timeout-minutes: 230 # almost 4 hours
runs-on:
- runs-on=${{ github.run_id }}
- family=m8g.large
- image=ubuntu24-full-arm64
- family=${{ inputs.family }}
- image=${{ inputs.image }}
- disk=large
- extras=s3-cache
- tag=${{ inputs.fuzz_target }}-fuzz
outputs:
crashes_found: ${{ steps.check.outputs.crashes_found }}
first_crash_name: ${{ steps.check.outputs.first_crash_name }}
artifact_url: ${{ steps.upload_artifacts.outputs.artifact-url }}
env:
AWS_ACCESS_KEY_ID: ${{ secrets.R2_FUZZ_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_FUZZ_SECRET_ACCESS_KEY }}
AWS_REGION: "us-east-1"
AWS_ENDPOINT_URL: "https://01e9655179bbec953276890b183039bc.r2.cloudflarestorage.com"
steps:
- uses: runs-on/action@v2
with:
Expand All @@ -70,6 +80,11 @@ jobs:

- name: Restore corpus
shell: bash
env:
AWS_ACCESS_KEY_ID: ${{ secrets.R2_FUZZ_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_FUZZ_SECRET_ACCESS_KEY }}
AWS_REGION: "us-east-1"
AWS_ENDPOINT_URL: "https://01e9655179bbec953276890b183039bc.r2.cloudflarestorage.com"
run: |
CORPUS_KEY="${{ inputs.fuzz_target }}_corpus.tar.zst"
CORPUS_DIR="fuzz/corpus/${{ inputs.fuzz_target }}"
Expand Down Expand Up @@ -99,8 +114,13 @@ jobs:
- name: Run fuzzing target
id: fuzz
run: |
FEATURES_FLAG=""
if [ -n "${{ inputs.extra_features }}" ]; then
FEATURES_FLAG="--features ${{ inputs.extra_features }}"
fi
RUSTFLAGS="--cfg vortex_nightly" RUST_BACKTRACE=1 \
cargo +nightly fuzz run --release --debug-assertions \
$FEATURES_FLAG \
${{ inputs.fuzz_target }} -- \
-max_total_time=${{ inputs.max_time }} -rss_limit_mb=0 \
2>&1 | tee fuzz_output.log
Expand Down Expand Up @@ -149,6 +169,11 @@ jobs:

- name: Persist corpus
shell: bash
env:
AWS_ACCESS_KEY_ID: ${{ secrets.R2_FUZZ_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_FUZZ_SECRET_ACCESS_KEY }}
AWS_REGION: "us-east-1"
AWS_ENDPOINT_URL: "https://01e9655179bbec953276890b183039bc.r2.cloudflarestorage.com"
run: |
CORPUS_KEY="${{ inputs.fuzz_target }}_corpus.tar.zst"
CORPUS_DIR="fuzz/corpus/${{ inputs.fuzz_target }}"
Expand Down
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions fuzz/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ default = ["native"]
native = ["libfuzzer-sys", "zstd", "vortex-file", "vortex/files"]
wasmfuzz = []
zstd = ["vortex/zstd"]
cuda = ["vortex-cuda", "tokio"]

[dependencies]
# Always needed - arbitrary is used for input generation
Expand All @@ -48,6 +49,10 @@ vortex-utils = { workspace = true }
libfuzzer-sys = { workspace = true, optional = true }
vortex-file = { workspace = true, optional = true }

# GPU support dependencies (optional, only for CUDA fuzzing)
vortex-cuda = { path = "../vortex-cuda", optional = true }
tokio = { workspace = true, features = ["rt", "macros"], optional = true }

[lints]
workspace = true

Expand Down Expand Up @@ -82,3 +87,11 @@ name = "compress_roundtrip"
path = "fuzz_targets/compress_roundtrip.rs"
test = false
required-features = ["native"]

[[bin]]
bench = false
doc = false
name = "compress_gpu"
path = "fuzz_targets/compress_gpu.rs"
test = false
required-features = ["native", "cuda"]
26 changes: 26 additions & 0 deletions fuzz/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: Copyright the Vortex contributors

use std::process::Command;

fn main() {
// Declare the cfg so rustc doesn't warn about unexpected cfg.
println!("cargo::rustc-check-cfg=cfg(cuda_available)");

// Only enable CUDA on Linux (matching vortex-cuda's behavior)
if cfg!(not(target_os = "linux")) {
return;
}

// Check if nvcc is available
if has_nvcc() {
println!("cargo:rustc-cfg=cuda_available");
}
}

fn has_nvcc() -> bool {
Command::new("nvcc")
.arg("--version")
.output()
.is_ok_and(|o| o.status.success())
}
27 changes: 27 additions & 0 deletions fuzz/fuzz_targets/compress_gpu.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: Copyright the Vortex contributors

#![no_main]
#![allow(clippy::unwrap_used, clippy::result_large_err)]

use libfuzzer_sys::Corpus;
use libfuzzer_sys::fuzz_target;
use vortex_error::vortex_panic;
use vortex_fuzz::FuzzCompressGpu;
use vortex_fuzz::run_compress_gpu;

fuzz_target!(|fuzz: FuzzCompressGpu| -> Corpus {
// Use tokio runtime to run async GPU fuzzer
let rt = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap();

match rt.block_on(run_compress_gpu(fuzz)) {
Ok(true) => Corpus::Keep,
Ok(false) => Corpus::Reject,
Err(e) => {
vortex_panic!("{e}");
}
}
});
Loading
Loading