diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml index 8253824..ea506c6 100644 --- a/.github/workflows/fuzz.yml +++ b/.github/workflows/fuzz.yml @@ -1,6 +1,9 @@ name: Fuzzing on: + push: + branches: [main, develop, feat-add-afl-fuzzing] + pull_request: schedule: - cron: "0 2 * * *" workflow_dispatch: @@ -81,59 +84,27 @@ jobs: mkdir -p "$CORPUS" # ── Build and replay the corpus with LLVM coverage instrumentation ── - # Capture output so we can parse the libFuzzer edge-bitmap lines. - # cargo fuzz coverage builds into fuzz/target//coverage/ - # and writes the merged profdata to fuzz/coverage//coverage.profdata - COVERAGE_LOG=$(cargo fuzz coverage "$TARGET" "$CORPUS" 2>&1 || true) - echo "$COVERAGE_LOG" - - # ── Extract libFuzzer edge-bitmap metrics from the merge log ── - # Total edges: "INFO: Loaded 1 modules (N inline 8-bit counters)" - # Covered edges: "MERGE-OUTER: ... N new coverage edges" - edge_total=$(echo "$COVERAGE_LOG" \ - | grep -oP '(?<=Loaded 1 modules\s{1,10}\()\d+(?= inline 8-bit counters)' \ - | tail -1) - edge_covered=$(echo "$COVERAGE_LOG" \ - | grep -oP '\d+(?= new coverage edges)' \ - | tail -1) - - if [ -n "$edge_total" ] && [ -n "$edge_covered" ] && [ "$edge_total" -gt 0 ]; then - edge_pct=$(python3 -c "print(f'{100*${edge_covered}/${edge_total}:.2f}')") - else - edge_pct="n/a" - fi - [ -z "$edge_total" ] && edge_total="n/a" - [ -z "$edge_covered" ] && edge_covered="n/a" - - echo "Edge bitmap: ${edge_covered}/${edge_total} (${edge_pct}%)" + cargo fuzz coverage "$TARGET" "$CORPUS" 2>/dev/null || true # ── Locate llvm-cov from the installed nightly toolchain ── SYSROOT="$(rustc --print sysroot)" HOST_TRIPLE="$(rustc -vV | awk '/^host:/{print $2}')" LLVM_COV="${SYSROOT}/lib/rustlib/${HOST_TRIPLE}/bin/llvm-cov" - # Use deterministic paths — cargo-fuzz always places artefacts here: - # binary → fuzz/target//coverage/ - # profdata → fuzz/coverage//coverage.profdata - PROFDATA="fuzz/coverage/${TARGET}/coverage.profdata" - BINARY="fuzz/target/${HOST_TRIPLE}/coverage/${TARGET}" - - echo "llvm-cov : ${LLVM_COV}" - echo "profdata : ${PROFDATA} (exists: $([ -f "$PROFDATA" ] && echo yes || echo no))" - echo "binary : ${BINARY} (exists: $([ -f "$BINARY" ] && echo yes || echo no))" + PROFDATA=$(find fuzz/coverage/"$TARGET" -name "coverage.profdata" 2>/dev/null | head -1) + BINARY=$(find fuzz/target -name "$TARGET" -type f -perm /111 2>/dev/null | grep release | head -1) branches_covered="n/a" branches_total="n/a" - branch_pct="n/a" + pct="n/a" - if [ -f "$PROFDATA" ] && [ -f "$BINARY" ]; then + if [ -n "$PROFDATA" ] && [ -f "$PROFDATA" ] && \ + [ -n "$BINARY" ] && [ -f "$BINARY" ]; then JSON=$("$LLVM_COV" export "$BINARY" \ --instr-profile="$PROFDATA" \ --summary-only \ --ignore-filename-regex='\.cargo|rustc' 2>/dev/null || echo "{}") - echo "llvm-cov JSON (first 400 chars): $(echo "$JSON" | head -c 400)" - branches_covered=$(echo "$JSON" | python3 -c " import sys, json data = json.load(sys.stdin) @@ -152,7 +123,7 @@ jobs: except Exception: print('n/a') ") - branch_pct=$(echo "$JSON" | python3 -c " + pct=$(echo "$JSON" | python3 -c " import sys, json data = json.load(sys.stdin) try: @@ -161,31 +132,19 @@ jobs: except Exception: print('n/a') ") - else - echo "WARNING: profdata or binary not found — skipping llvm-cov." fi - echo "Branch coverage: ${branches_covered}/${branches_total} (${branch_pct}%)" + echo "Branch coverage: ${branches_covered}/${branches_total} (${pct}%)" # ── GitHub Step Summary ── { echo "## Edge Bitmap Coverage — \`${TARGET}\`" echo "" - echo "### libFuzzer edge bitmap (inline 8-bit counters)" + echo "| Method | Covered branches | Total branches | Coverage % |" + echo "|---|---|---|---|" + echo "| \`llvm-cov\` (libFuzzer corpus) | ${branches_covered} | ${branches_total} | **${pct}%** |" echo "" - echo "| Metric | Value |" - echo "|---|---|" - echo "| Total edges | ${edge_total} |" - echo "| Covered edges | ${edge_covered} |" - echo "| Edge coverage | **${edge_pct}%** |" - echo "" - echo "### LLVM source-based branch coverage" - echo "" - echo "| Covered branches | Total branches | Coverage % |" - echo "|---|---|---|" - echo "| ${branches_covered} | ${branches_total} | **${branch_pct}%** |" - echo "" - echo "> Edge bitmap from libFuzzer merge; branch coverage from \`llvm-cov\` over \`${CORPUS}\`." + echo "> Coverage computed over \`${CORPUS}\` using LLVM source-based branch instrumentation." } >> "$GITHUB_STEP_SUMMARY" - name: Upload crash artifacts