diff --git a/actions/cairn-zig-fuzz-afl/action.yml b/actions/cairn-zig-fuzz-afl/action.yml index 12385b0..7c9ae40 100644 --- a/actions/cairn-zig-fuzz-afl/action.yml +++ b/actions/cairn-zig-fuzz-afl/action.yml @@ -27,6 +27,15 @@ inputs: description: 'Binary name in zig-out/bin/ (auto-detected if only one)' required: false default: '' + seed_dir: + description: | + Directory containing per-target seed inputs. Each subdirectory should match + a target name from the targets input. Files are merged with the downloaded corpus. + Example layout: + seeds/lexer/valid-token.txt + seeds/parser/minimal-program.txt + required: false + default: '' duration: description: 'Fuzz duration per target in seconds' required: false @@ -73,6 +82,7 @@ runs: COMMIT: ${{ inputs.commit }} TARGETS: ${{ inputs.targets }} FUZZ_BINARY: ${{ inputs.fuzz_binary }} + SEED_DIR: ${{ inputs.seed_dir }} DURATION: ${{ inputs.duration }} EXTRA_AFL_ARGS: ${{ inputs.afl_args }} TARGET_PLATFORM: ${{ inputs.target }} @@ -130,6 +140,15 @@ runs: rm -rf "${SEEDS}" mkdir -p "${SEEDS}" + # Copy per-target seeds from repo if available. + if [ -n "${SEED_DIR}" ] && [ -d "${SEED_DIR}/${FUZZ_TARGET}" ]; then + REPO_SEED_COUNT=$(find "${SEED_DIR}/${FUZZ_TARGET}" -maxdepth 1 -type f | wc -l) + if [ "${REPO_SEED_COUNT}" -gt 0 ]; then + cp "${SEED_DIR}/${FUZZ_TARGET}"/* "${SEEDS}/" 2>/dev/null || true + echo "Copied ${REPO_SEED_COUNT} repo seeds from ${SEED_DIR}/${FUZZ_TARGET}" + fi + fi + DL_START=$(date +%s) cairn corpus download \ -server "${CAIRN_SERVER}" \ @@ -248,17 +267,32 @@ runs: done fi - # ── Upload new corpus entries ── + # ── Minimize and upload corpus ── QUEUE_DIR="${FINDINGS}/default/queue" if [ -d "${QUEUE_DIR}" ]; then QUEUE_COUNT=$(find "${QUEUE_DIR}" -maxdepth 1 -type f -name 'id:*' | wc -l) if [ "${QUEUE_COUNT}" -gt 0 ]; then - echo "Uploading corpus (${QUEUE_COUNT} entries)..." + UPLOAD_DIR="corpus-upload-${TARGET_NUM}" + rm -rf "${UPLOAD_DIR}" + mkdir -p "${UPLOAD_DIR}" + CMIN_START=$(date +%s) + if afl-cmin -i "${QUEUE_DIR}" -o "${UPLOAD_DIR}" -- "${FUZZ_BIN}" >/dev/null 2>&1; then + CMIN_ELAPSED=$(( $(date +%s) - CMIN_START )) + UPLOAD_COUNT=$(find "${UPLOAD_DIR}" -maxdepth 1 -type f | wc -l) + echo "Corpus for upload minimized: ${QUEUE_COUNT} -> ${UPLOAD_COUNT} entries (${CMIN_ELAPSED}s)" + else + echo "afl-cmin failed, uploading full queue" + rm -rf "${UPLOAD_DIR}" + UPLOAD_DIR="${QUEUE_DIR}" + UPLOAD_COUNT="${QUEUE_COUNT}" + fi + echo "Uploading corpus (${UPLOAD_COUNT} entries)..." cairn corpus upload \ -server "${CAIRN_SERVER}" \ -target-id "${CAIRN_TARGET_ID}" \ -run-id "${RUN_ID}" \ - -dir "${QUEUE_DIR}" + -dir "${UPLOAD_DIR}" + rm -rf "corpus-upload-${TARGET_NUM}" fi fi