Skip to content

Release 0.9.0: security, correctness and performance hardening #544

Release 0.9.0: security, correctness and performance hardening

Release 0.9.0: security, correctness and performance hardening #544

Workflow file for this run

name: CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
env:
CARGO_TERM_COLOR: always
RUSTFLAGS: "-Dwarnings"
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: "true"
DOTNET_CLI_TELEMETRY_OPTOUT: "true"
DOTNET_NOLOGO: "true"
jobs:
# Library testing and linting - no build artifacts needed
check:
name: Check & Test
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
steps:
- name: Checkout code
uses: actions/checkout@v7
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- name: Setup .NET SDK
uses: actions/setup-dotnet@v5
with:
dotnet-version: '8.0.x'
- name: Warm up .NET SDK
run: |
dotnet --info
dotnet new console -n warmup -o ${{ runner.temp }}/warmup
dotnet build ${{ runner.temp }}/warmup
- name: Install Mono and Z3 (Linux)
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y mono-utils libz3-dev
- name: Install Mono and Z3 (macOS)
if: runner.os == 'macOS'
run: |
brew install mono z3
echo "LIBRARY_PATH=$(brew --prefix z3)/lib" >> "$GITHUB_ENV"
- name: Install Z3 and dotnet-ildasm tool (Windows)
if: runner.os == 'Windows'
run: |
dotnet tool install --global dotnet-ildasm
# Download Z3 from GitHub releases (more reliable than Chocolatey)
$z3Version = "4.13.4"
$z3Url = "https://github.com/Z3Prover/z3/releases/download/z3-$z3Version/z3-$z3Version-x64-win.zip"
$z3Zip = "$env:RUNNER_TEMP\z3.zip"
$z3Dir = "$env:RUNNER_TEMP\z3"
Invoke-WebRequest -Uri $z3Url -OutFile $z3Zip
Expand-Archive -Path $z3Zip -DestinationPath $z3Dir
$z3Root = Get-ChildItem -Path $z3Dir -Directory | Select-Object -First 1
echo "Z3_SYS_Z3_HEADER=$(Join-Path $z3Root.FullName 'include\z3.h')" >> $env:GITHUB_ENV
echo "Z3_LIBRARY_PATH_OVERRIDE=$(Join-Path $z3Root.FullName 'bin')" >> $env:GITHUB_ENV
# Add Z3 bin to PATH so libz3.dll is found at runtime
echo "$(Join-Path $z3Root.FullName 'bin')" >> $env:GITHUB_PATH
echo "Installed Z3 $z3Version at: $($z3Root.FullName)"
ls (Join-Path $z3Root.FullName 'bin')
shell: pwsh
- name: Setup Rust cache
uses: Swatinem/rust-cache@v2
with:
key: ${{ matrix.os }}-check
- name: Check formatting
run: cargo fmt --all -- --check
- name: Run clippy
run: cargo clippy --workspace --all-features --all-targets -- -D warnings
- name: Check compilation
run: cargo check --workspace --all-features
- name: Run tests (Linux - full)
if: runner.os == 'Linux'
run: cargo test --workspace --release --features z3 --lib --bins --tests --verbose
- name: Run tests (macOS/Windows - skip expensive tests)
if: runner.os != 'Linux'
run: cargo test --workspace --release --features z3,skip-expensive-tests --lib --bins --tests --verbose
- name: Run doc tests (Linux only)
if: runner.os == 'Linux'
run: cargo test --workspace --release --doc --features z3 -- --test-threads=4
- name: Check documentation
env:
RUSTDOCFLAGS: "-Dwarnings"
run: cargo doc -p dotscope --all-features --no-deps
# Compiles and tests without the legacy-crypto feature (Linux only). Pinned to the declared
# MSRV so this job also guards `rust-version`; the workspace check covers the default-feature
# path, which `--no-default-features` alone would not.
minimal-features:
name: Minimal Features & MSRV
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v7
- name: Install Rust toolchain
uses: dtolnay/[email protected]
- name: Setup Rust cache
uses: Swatinem/rust-cache@v2
with:
key: minimal-features
- name: Check compilation (default features, whole workspace)
run: cargo check --workspace --all-targets
- name: Check compilation (no default features)
run: cargo check -p dotscope --no-default-features
- name: Run tests (no default features)
run: cargo test -p dotscope --no-default-features --release --lib --bins --tests --verbose
# Fuzzing on pushes to main or PRs targeting main
fuzzing:
name: Quick Fuzzing
runs-on: ubuntu-latest
if: |
(github.event_name == 'push' && github.ref == 'refs/heads/main') ||
(github.event_name == 'pull_request' && github.event.pull_request.base.ref == 'main') ||
contains(github.event.head_commit.message, '[fuzz]')
steps:
- name: Checkout code
uses: actions/checkout@v7
- name: Install Rust nightly
uses: dtolnay/rust-toolchain@nightly
- name: Install cargo-fuzz
run: cargo install cargo-fuzz
- name: Setup Rust cache
uses: Swatinem/rust-cache@v2
with:
key: fuzz-quick
- name: Build fuzz targets
run: cargo +nightly fuzz build --release
working-directory: dotscope/fuzz
# Every target gets the committed crash corpus. The inputs are PE-shaped, so they are
# directly meaningful to `cilobject`/`assemblyview` and act as structured starting material
# for the blob and body targets rather than starting them from scratch.
- name: Seed corpora from committed regressions
run: |
for t in cilobject assemblyview signatures customattributes methodbody emulation; do
mkdir -p "dotscope/fuzz/corpus/$t"
cp dotscope/tests/samples/fuzz-regressions/* "dotscope/fuzz/corpus/$t/" || true
done
- name: Run quick fuzz test
run: |
for t in cilobject assemblyview signatures customattributes methodbody emulation; do
echo "::group::fuzz $t"
timeout 60 cargo +nightly fuzz run "$t" --release -- \
-max_total_time=40 -timeout=25 -rss_limit_mb=2048 || true
echo "::endgroup::"
done
working-directory: dotscope/fuzz
- name: Check for crashes
run: |
found=0
for t in cilobject assemblyview signatures customattributes methodbody emulation; do
if [ -d "dotscope/fuzz/artifacts/$t" ] && [ "$(ls -A "dotscope/fuzz/artifacts/$t")" ]; then
echo "Fuzzing found crashes in $t:"
ls -la "dotscope/fuzz/artifacts/$t"
found=1
fi
done
if [ "$found" = "1" ]; then
exit 1
fi
# Security audit on pushes to main or PRs targeting main
security:
name: Security Audit
runs-on: ubuntu-latest
if: |
(github.event_name == 'push' && github.ref == 'refs/heads/main') ||
(github.event_name == 'pull_request' && github.event.pull_request.base.ref == 'main')
steps:
- name: Checkout code
uses: actions/checkout@v7
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Install cargo-audit
run: cargo install cargo-audit
- name: Run security audit
run: cargo audit
# Code coverage
coverage:
name: Code Coverage
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v7
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
components: llvm-tools-preview
- name: Setup .NET SDK
uses: actions/setup-dotnet@v5
with:
dotnet-version: '8.0.x'
- name: Warm up .NET SDK
run: |
dotnet --info
dotnet new console -n warmup -o ${{ runner.temp }}/warmup
dotnet build ${{ runner.temp }}/warmup
- name: Install Mono and Z3
run: |
sudo apt-get update
sudo apt-get install -y mono-utils libz3-dev
- name: Setup Rust cache
uses: Swatinem/rust-cache@v2
with:
key: coverage
- name: Install cargo-llvm-cov
uses: taiki-e/install-action@cargo-llvm-cov
- name: Generate code coverage
run: cargo llvm-cov --workspace --features z3,skip-expensive-tests --lcov --output-path lcov.info --exclude dotscope-cli
- name: Upload to codecov.io
uses: codecov/codecov-action@v7
with:
files: lcov.info
fail_ci_if_error: true
token: ${{ secrets.CODECOV_TOKEN }}