fuzz: improve iteration scaling, add minimization and summary table
What changed, and why it matters
This commit changes how the project's automated fuzz testing is run in CI. It replaces a fixed 30-second fuzzing run with a scaled iteration count, adds an optional corpus minimization step, prints a summary table, and tweaks runtime flags. There is no change to production code, user-facing behavior, or cryptographic logic. It is purely a testing infrastructure improvement.
No security action needed. Review as normal CI tooling change if desired.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch modifies .github/workflows/build.yml and fuzz/ci-fuzz.sh. It switches honggfuzz from a 30-second run_time to N = 8x corpus size + 1000 iterations capped at 600 seconds, adds a -t 3 per-input timeout, suppresses per-iteration output with -q, and adds crash checking after minimization. On main or when the PR has the fuzz-minimize label, it runs honggfuzz in minimization mode (-M) after fuzzing and prints a per-target summary table. No application code is touched.
Changed components
fuzz/ci-fuzz.sh.github/workflows/build.ymlInspect captured patch +71 / −7
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index f50c9b8..b68d545 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -255,6 +255,8 @@ jobs:
fuzz-corpus-refs/heads/main-
- name: Run fuzzers
run: cd fuzz && ./ci-fuzz.sh && cd ..
+ env:
+ FUZZ_MINIMIZE: ${{ contains(github.event.pull_request.labels.*.name, 'fuzz-minimize') }}
- name: Upload honggfuzz corpus
uses: actions/upload-artifact@v4
with:
diff --git a/fuzz/ci-fuzz.sh b/fuzz/ci-fuzz.sh
index d57a5ad..47bf41b 100755
--- a/fuzz/ci-fuzz.sh
+++ b/fuzz/ci-fuzz.sh
@@ -30,20 +30,82 @@ sed -i 's/lto = true//' Cargo.toml
export HFUZZ_BUILD_ARGS="--features honggfuzz_fuzz"
cargo --color always hfuzz build -j8
+
+SUMMARY=""
+
+check_crash() {
+ local FILE=$1
+ if [ -f "hfuzz_workspace/$FILE/HONGGFUZZ.REPORT.TXT" ]; then
+ cat "hfuzz_workspace/$FILE/HONGGFUZZ.REPORT.TXT"
+ for CASE in "hfuzz_workspace/$FILE"/SIG*; do
+ cat "$CASE" | xxd -p
+ done
+ exit 1
+ fi
+}
+
for TARGET in src/bin/*.rs; do
FILENAME=$(basename $TARGET)
FILE="${FILENAME%.*}"
- HFUZZ_RUN_ARGS="--exit_upon_crash -v -n8 --run_time 30"
+ CORPUS_DIR="hfuzz_workspace/$FILE/input"
+ CORPUS_COUNT=$(find "$CORPUS_DIR" -type f 2>/dev/null | wc -l)
+ # Run 8x the corpus size plus a baseline, ensuring full corpus replay
+ # with room for new mutations. The 10-minute hard cap (--run_time 600)
+ # prevents slow-per-iteration targets from running too long.
+ ITERATIONS=$((CORPUS_COUNT * 8 + 1000))
+ HFUZZ_RUN_ARGS="--exit_upon_crash -q -n8 -t 3 -N $ITERATIONS --run_time 600"
if [ "$FILE" = "chanmon_consistency_target" -o "$FILE" = "fs_store_target" ]; then
HFUZZ_RUN_ARGS="$HFUZZ_RUN_ARGS -F 64"
fi
export HFUZZ_RUN_ARGS
+ FUZZ_START=$(date +%s)
cargo --color always hfuzz run $FILE
- if [ -f hfuzz_workspace/$FILE/HONGGFUZZ.REPORT.TXT ]; then
- cat hfuzz_workspace/$FILE/HONGGFUZZ.REPORT.TXT
- for CASE in hfuzz_workspace/$FILE/SIG*; do
- cat $CASE | xxd -p
- done
- exit 1
+ FUZZ_END=$(date +%s)
+ FUZZ_TIME=$((FUZZ_END - FUZZ_START))
+ FUZZ_CORPUS_COUNT=$(find "$CORPUS_DIR" -type f 2>/dev/null | wc -l)
+ check_crash "$FILE"
+ if [ "$GITHUB_REF" = "refs/heads/main" ] || [ "$FUZZ_MINIMIZE" = "true" ]; then
+ HFUZZ_RUN_ARGS="-M -q -n8 -t 3"
+ export HFUZZ_RUN_ARGS
+ MIN_START=$(date +%s)
+ cargo --color always hfuzz run $FILE
+ MIN_END=$(date +%s)
+ MIN_TIME=$((MIN_END - MIN_START))
+ MIN_CORPUS_COUNT=$(find "$CORPUS_DIR" -type f 2>/dev/null | wc -l)
+ check_crash "$FILE"
+ SUMMARY="${SUMMARY}${FILE}|${ITERATIONS}|${CORPUS_COUNT}|${FUZZ_CORPUS_COUNT}|${FUZZ_TIME}|${MIN_CORPUS_COUNT}|${MIN_TIME}\n"
+ else
+ SUMMARY="${SUMMARY}${FILE}|${ITERATIONS}|${CORPUS_COUNT}|${FUZZ_CORPUS_COUNT}|${FUZZ_TIME}|-|-\n"
+ fi
+done
+
+fmt_time() {
+ local secs=$1
+ local m=$((secs / 60))
+ local s=$((secs % 60))
+ if [ "$m" -gt 0 ]; then
+ printf "%dm %ds" "$m" "$s"
+ else
+ printf "%ds" "$s"
+ fi
+}
+
+# Print summary table
+set +x
+echo ""
+echo "==== Fuzz Summary ===="
+HDR="%-40s %7s %7s %-15s %9s %-15s %9s\n"
+FMT="%-40s %7s %7s %6s %-9s %9s %6s %-9s %9s\n"
+printf "$HDR" "Target" "Iters" "Corpus" " Fuzzed" "Fuzz time" " Minimized" "Min. time"
+printf "$HDR" "------" "-----" "------" "---------------" "---------" "---------------" "---------"
+echo -e "$SUMMARY" | while IFS='|' read -r name iters orig fuzzed ftime minimized mtime; do
+ [ -z "$name" ] && continue
+ fuzz_delta=$((fuzzed - orig))
+ if [ "$minimized" = "-" ]; then
+ printf "$FMT" "$name" "$iters" "$orig" "$fuzzed" "(+$fuzz_delta)" "$(fmt_time "$ftime")" "-" "" "-"
+ else
+ min_delta=$((minimized - fuzzed))
+ printf "$FMT" "$name" "$iters" "$orig" "$fuzzed" "(+$fuzz_delta)" "$(fmt_time "$ftime")" "$minimized" "($min_delta)" "$(fmt_time "$mtime")"
fi
done
+echo "======================"
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.