From 32afda20787728d278c289552facdcc1691221a4 Mon Sep 17 00:00:00 2001 From: roshan-ku Date: Wed, 3 Jun 2026 14:43:10 +0530 Subject: [PATCH 1/4] ci: consolidate fuzz and coverity workflows --- .github/actions/analysis/afl-fuzz/action.yml | 80 +++++++ .github/actions/analysis/coverity/action.yml | 156 +++++++++++++ .github/actions/analysis/libfuzzer/action.yml | 66 ++++++ .github/workflows/ci.yml | 3 +- .github/workflows/coverity.yml | 207 ------------------ .github/workflows/daily_build.yml | 108 ++++++++- .github/workflows/fuzz.yml | 107 --------- .github/workflows/libfuzzer.yml | 94 -------- .github/workflows/pull_request.yml | 13 +- 9 files changed, 410 insertions(+), 424 deletions(-) create mode 100644 .github/actions/analysis/afl-fuzz/action.yml create mode 100644 .github/actions/analysis/coverity/action.yml create mode 100644 .github/actions/analysis/libfuzzer/action.yml delete mode 100644 .github/workflows/coverity.yml delete mode 100644 .github/workflows/fuzz.yml delete mode 100644 .github/workflows/libfuzzer.yml diff --git a/.github/actions/analysis/afl-fuzz/action.yml b/.github/actions/analysis/afl-fuzz/action.yml new file mode 100644 index 0000000..e16e38d --- /dev/null +++ b/.github/actions/analysis/afl-fuzz/action.yml @@ -0,0 +1,80 @@ +# +# BSD 3-Clause License +# Copyright (C) 2026 Intel Corporation +# SPDX-License-Identifier: BSD-3-Clause +# +name: 'AFL Fuzz' +description: 'Build and run AFL++ fuzzing for config parser harness' + +inputs: + max-seconds: + description: 'Maximum AFL fuzzing run time in seconds' + required: false + default: '300' + +runs: + using: composite + steps: + - name: Install AFL dependencies + shell: bash + run: | + sudo apt-get update -qq + sudo apt-get install -y -qq afl++ libavutil-dev libavformat-dev libavcodec-dev libswscale-dev pkg-config + + - name: Verify AFL environment + shell: bash + run: | + echo "=== AFL++ ===" + afl-clang-fast --version || { echo "ERROR: afl-clang-fast not found"; exit 1; } + echo "" + echo "=== libavutil ===" + dpkg -l libavutil-dev | grep -q ii || { echo "ERROR: libavutil-dev not installed"; exit 1; } + echo " Header: $(find /usr/include -name 'avutil.h' | head -1)" + echo " Library: $(find /usr/lib -name 'libavutil.so*' | head -1)" + echo "" + echo "=== Compiler ===" + gcc --version | head -1 + echo "" + echo "Environment OK" + + - name: Build AFL fuzz harness + shell: bash + run: | + cd fuzz + export CC=afl-clang-fast + $CC -g -O1 -fno-omit-frame-pointer -I../include -c fuzz_config_reader.c -o fuzz_config_reader.o + $CC -g -O1 -fno-omit-frame-pointer -I../include -c ../src/util/config_reader.c -o config_reader.o + $CC -g -O1 -fno-omit-frame-pointer -I../include -c ../src/util/logger.c -o logger.o + $CC -o fuzz_config_reader fuzz_config_reader.o config_reader.o logger.o -lavutil -lm + echo "Build successful: $(file fuzz_config_reader)" + + - name: Run AFL fuzzer + shell: bash + run: | + cd fuzz + mkdir -p findings + export AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 + export AFL_SKIP_CPUFREQ=1 + timeout "${{ inputs.max-seconds }}" afl-fuzz -i corpus/ -o findings/ -V "${{ inputs.max-seconds }}" -- ./fuzz_config_reader @@ || true + + - name: Check AFL crashes + shell: bash + run: | + cd fuzz + CRASH_COUNT=$(find findings/default/crashes -type f ! -name "README.txt" 2>/dev/null | wc -l) + echo "Crashes found: $CRASH_COUNT" + if [ "$CRASH_COUNT" -gt 0 ]; then + echo "::error::AFL found $CRASH_COUNT crash(es)!" + ls -la findings/default/crashes/ + exit 1 + fi + echo "No crashes found - fuzzing passed." + + - name: Sanitize AFL filenames + if: always() + shell: bash + run: | + cd fuzz/findings + find . -name '*:*' | while read -r f; do + mv "$f" "$(echo "$f" | tr ':' '_')" + done diff --git a/.github/actions/analysis/coverity/action.yml b/.github/actions/analysis/coverity/action.yml new file mode 100644 index 0000000..0ca35c3 --- /dev/null +++ b/.github/actions/analysis/coverity/action.yml @@ -0,0 +1,156 @@ +# +# BSD 3-Clause License +# Copyright (C) 2026 Intel Corporation +# SPDX-License-Identifier: BSD-3-Clause +# +name: 'Coverity Scan' +description: 'Install Coverity, run static analysis, and emit JSON + SARIF reports' + +runs: + using: composite + steps: + - name: Install Coverity + shell: bash + env: + COVERITY_URL: ${{ env.COVERITY_URL }} + COVERITY_USER: ${{ env.COVERITY_USER }} + COVERITY_PASSWORD: ${{ env.COVERITY_PASSWORD }} + run: | + echo "===== Coverity Setup =====" + COVERITY_DIR="$HOME/coverity" + if [ -x "$COVERITY_DIR/bin/cov-build" ]; then + echo " [OK] Coverity already installed at $COVERITY_DIR" + "$COVERITY_DIR/bin/cov-build" --ident | head -1 || true + exit 0 + fi + mkdir -p "$COVERITY_DIR" + wget --no-proxy -q --user="$COVERITY_USER" --password="$COVERITY_PASSWORD" \ + -O /tmp/coverity.tar.gz "$COVERITY_URL" + tar xzf /tmp/coverity.tar.gz --strip-components=1 -C "$COVERITY_DIR" + rm -f /tmp/coverity.tar.gz + "$COVERITY_DIR/bin/cov-build" --ident | head -1 || true + + - name: Run Coverity analysis + shell: bash + run: | + export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:/usr/local/lib/x86_64-linux-gnu/pkgconfig:${PKG_CONFIG_PATH:-} + if ! pkg-config --exists mtl 2>/dev/null; then + MTL_PC=$(find /usr /home /opt -name "mtl.pc" 2>/dev/null | head -1) + if [ -z "$MTL_PC" ]; then + echo "ERROR: MTL pkg-config file not found." + exit 1 + fi + MTL_PC_DIR=$(dirname "$MTL_PC") + echo "Found MTL pkgconfig at: $MTL_PC_DIR" + export PKG_CONFIG_PATH="${MTL_PC_DIR}:${PKG_CONFIG_PATH}" + fi + + REPORT_DIR="$GITHUB_WORKSPACE/reports" + mkdir -p "$REPORT_DIR" + + $HOME/coverity/bin/cov-configure --compiler cc --comptype gcc --template + rm -rf build coverity_output + meson setup build + $HOME/coverity/bin/cov-build --dir coverity_output/ ninja -C build + + $HOME/coverity/bin/cov-analyze --dir coverity_output/ \ + --concurrency --enable-constraint-fpp --enable-fnptr --enable-virtual \ + --disable ASSERT_SIDE_EFFECT \ + --disable AUTO_CAUSES_COPY \ + --disable BAD_CHECK_OF_WAIT_COND \ + --disable BAD_SHIFT \ + --disable COPY_INSTEAD_OF_MOVE \ + --disable CUDA.COLLECTIVE_WARP_SHUFFLE_WIDTH \ + --disable CUDA.CUDEVICE_HANDLES \ + --disable CUDA.DEVICE_DEPENDENT \ + --disable CUDA.DEVICE_DEPENDENT_CALLBACKS \ + --disable CUDA.DIVERGENCE_AT_COLLECTIVE_OPERATION \ + --disable CUDA.ERROR_INTERFACE \ + --disable CUDA.ERROR_KERNEL_LAUNCH \ + --disable CUDA.FORK \ + --disable CUDA.INACTIVE_THREAD_AT_COLLECTIVE_WARP \ + --disable CUDA.INITIATION_OBJECT_DEVICE_THREAD_BLOCK \ + --disable CUDA.INVALID_MEMORY_ACCESS \ + --disable CUDA.SHARE_FUNCTION \ + --disable CUDA.SHARE_OBJECT_STREAM_ASSOCIATED \ + --disable CUDA.SPECIFIERS_INCONSISTENCY \ + --disable CUDA.SYNCHRONIZE_TERMINATION \ + --disable INEFFICIENT_RESERVE \ + --disable MISSING_COMMA \ + --disable MISSING_MOVE_ASSIGNMENT \ + --disable OVERLAPPING_COPY \ + --disable STREAM_FORMAT_STATE \ + --disable UNINTENDED_INTEGER_DIVISION + + $HOME/coverity/bin/cov-format-errors --dir coverity_output/ \ + --json-output-v8 "$REPORT_DIR/coverity-report.json" + + - name: Convert Coverity JSON to SARIF + shell: bash + run: | + REPORT_DIR="$GITHUB_WORKSPACE/reports" + python3 - <<'EOF' + import json, sys + + sarif = { + "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/main/sarif-2.1/schema/sarif-schema-2.1.0.json", + "version": "2.1.0", + "runs": [{ + "tool": { + "driver": { + "name": "Coverity", + "informationUri": "https://www.synopsys.com/software-integrity/security-testing/static-analysis-sast.html", + "rules": [] + } + }, + "results": [] + }] + } + + try: + with open("reports/coverity-report.json") as f: + cov = json.load(f) + except (FileNotFoundError, json.JSONDecodeError): + with open("reports/coverity-results.sarif", "w") as f: + json.dump(sarif, f, indent=2) + sys.exit(0) + + rules_map = {} + results = [] + + for issue in cov.get("issues", []): + checker = issue.get("checkerName", "unknown") + if checker not in rules_map: + rule_idx = len(rules_map) + rules_map[checker] = rule_idx + sarif["runs"][0]["tool"]["driver"]["rules"].append({ + "id": checker, + "shortDescription": {"text": issue.get("checkerProperties", {}).get("subcategoryShortDescription", checker)}, + "helpUri": f"https://community.synopsys.com/s/article/{checker}" + }) + + events = issue.get("events", []) + main_event = events[0] if events else {} + file_path = main_event.get("strippedFilePathname", main_event.get("filePathname", "unknown")) + line = main_event.get("lineNumber", 1) + + results.append({ + "ruleId": checker, + "ruleIndex": rules_map[checker], + "level": "warning", + "message": {"text": issue.get("checkerProperties", {}).get("subcategoryLongDescription", checker)}, + "locations": [{ + "physicalLocation": { + "artifactLocation": {"uri": file_path, "uriBaseId": "%SRCROOT%"}, + "region": {"startLine": line} + } + }] + }) + + sarif["runs"][0]["results"] = results + + with open("reports/coverity-results.sarif", "w") as f: + json.dump(sarif, f, indent=2) + + print(f"Converted {len(results)} Coverity issues to SARIF") + EOF diff --git a/.github/actions/analysis/libfuzzer/action.yml b/.github/actions/analysis/libfuzzer/action.yml new file mode 100644 index 0000000..b400b05 --- /dev/null +++ b/.github/actions/analysis/libfuzzer/action.yml @@ -0,0 +1,66 @@ +# +# BSD 3-Clause License +# Copyright (C) 2026 Intel Corporation +# SPDX-License-Identifier: BSD-3-Clause +# +name: 'libFuzzer' +description: 'Build and run libFuzzer with ASan and UBSan for config parser harness' + +inputs: + max-seconds: + description: 'Maximum libFuzzer run time in seconds per sanitizer mode' + required: false + default: '300' + +runs: + using: composite + steps: + - name: Install libFuzzer dependencies + shell: bash + run: | + sudo apt-get update -qq + sudo apt-get install -y -qq clang libavutil-dev libavformat-dev libavcodec-dev libswscale-dev pkg-config + + - name: Build and run libFuzzer (ASan) + shell: bash + run: | + cd fuzz + export CC=clang + $CC -fsanitize=fuzzer,address -g -O1 -fno-omit-frame-pointer -I../include \ + fuzz_config_reader_libfuzzer.c \ + ../src/util/config_reader.c \ + ../src/util/logger.c \ + -o fuzz_config_reader_libfuzzer \ + $(pkg-config --cflags --libs libavutil) -lm + + mkdir -p libfuzzer_corpus + ./fuzz_config_reader_libfuzzer \ + libfuzzer_corpus/ corpus/ \ + -max_total_time=${{ inputs.max-seconds }} \ + -print_final_stats=1 || FUZZ_EXIT=$? + if [ "${FUZZ_EXIT:-0}" -ne 0 ]; then + echo "::error::libFuzzer found a crash (exit code $FUZZ_EXIT)!" + exit 1 + fi + + - name: Build and run libFuzzer (UBSan) + shell: bash + run: | + cd fuzz + export CC=clang + $CC -fsanitize=fuzzer,undefined -g -O1 -fno-omit-frame-pointer -I../include \ + fuzz_config_reader_libfuzzer.c \ + ../src/util/config_reader.c \ + ../src/util/logger.c \ + -o fuzz_config_reader_ubsan \ + $(pkg-config --cflags --libs libavutil) -lm + + mkdir -p ubsan_corpus + ./fuzz_config_reader_ubsan \ + ubsan_corpus/ corpus/ \ + -max_total_time=${{ inputs.max-seconds }} \ + -print_final_stats=1 || FUZZ_EXIT=$? + if [ "${FUZZ_EXIT:-0}" -ne 0 ]; then + echo "::error::libFuzzer+UBSan found an issue (exit code $FUZZ_EXIT)!" + exit 1 + fi diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7531b56..2f54d67 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,8 +21,9 @@ concurrency: jobs: ci: - name: Continuous Integration + name: CI Full Validation runs-on: ubuntu-latest + timeout-minutes: 45 permissions: contents: read steps: diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml deleted file mode 100644 index f853158..0000000 --- a/.github/workflows/coverity.yml +++ /dev/null @@ -1,207 +0,0 @@ -# -# BSD 3-Clause License -# Copyright (C) 2026 Intel Corporation -# SPDX-License-Identifier: BSD-3-Clause -# -name: Coverity Scan - -on: - push: - branches: - - main - schedule: - # Weekly on Tuesday at 05:00 UTC - - cron: '0 5 * * 2' - workflow_dispatch: - -permissions: {} - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - coverity: - name: Coverity Static Analysis - runs-on: ubuntu-latest - permissions: - contents: read # checkout repository - security-events: write # upload SARIF results - - steps: - - name: Checkout repository - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: false - - - name: Environment check - uses: ./.github/actions/environment-check - - - name: Install Coverity - env: - COVERITY_URL: ${{ secrets.COVERITY_URL }} - COVERITY_USER: ${{ secrets.COVERITY_ARTIFACTORY_USER }} - COVERITY_PASSWORD: ${{ secrets.COVERITY_ARTIFACTORY_PASSWORD }} - run: | - echo "===== Coverity Setup =====" - COVERITY_DIR="$HOME/coverity" - if [ -x "$COVERITY_DIR/bin/cov-build" ]; then - echo " [OK] Coverity already installed at $COVERITY_DIR" - "$COVERITY_DIR/bin/cov-build" --ident | head -1 || true - exit 0 - fi - echo " Downloading Coverity..." - mkdir -p "$COVERITY_DIR" - wget --no-proxy -q --user="$COVERITY_USER" --password="$COVERITY_PASSWORD" \ - -O /tmp/coverity.tar.gz "$COVERITY_URL" - echo " Extracting Coverity..." - tar xzf /tmp/coverity.tar.gz --strip-components=1 -C "$COVERITY_DIR" - rm -f /tmp/coverity.tar.gz - echo " Coverity installed:" - "$COVERITY_DIR/bin/cov-build" --ident | head -1 || true - - - name: Run Coverity Analysis - run: | - # Resolve MTL pkg-config path - export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:/usr/local/lib/x86_64-linux-gnu/pkgconfig:${PKG_CONFIG_PATH:-} - if ! pkg-config --exists mtl 2>/dev/null; then - MTL_PC=$(find /usr /home /opt -name "mtl.pc" 2>/dev/null | head -1) - if [ -z "$MTL_PC" ]; then - echo "ERROR: MTL pkg-config file not found." - exit 1 - fi - MTL_PC_DIR=$(dirname "$MTL_PC") - echo "Found MTL pkgconfig at: $MTL_PC_DIR" - export PKG_CONFIG_PATH="${MTL_PC_DIR}:${PKG_CONFIG_PATH}" - fi - - REPORT_DIR="$GITHUB_WORKSPACE/reports" - mkdir -p "$REPORT_DIR" - - # Configure Coverity for cc (meson uses cc which is gcc) - $HOME/coverity/bin/cov-configure --compiler cc --comptype gcc --template - - # Clean and setup meson build directory - rm -rf build coverity_output - meson setup build - - # Run cov-build wrapping the ninja compilation - $HOME/coverity/bin/cov-build --dir coverity_output/ ninja -C build - - # Analyze captured build - $HOME/coverity/bin/cov-analyze --dir coverity_output/ \ - --concurrency --enable-constraint-fpp --enable-fnptr --enable-virtual \ - --disable ASSERT_SIDE_EFFECT \ - --disable AUTO_CAUSES_COPY \ - --disable BAD_CHECK_OF_WAIT_COND \ - --disable BAD_SHIFT \ - --disable COPY_INSTEAD_OF_MOVE \ - --disable CUDA.COLLECTIVE_WARP_SHUFFLE_WIDTH \ - --disable CUDA.CUDEVICE_HANDLES \ - --disable CUDA.DEVICE_DEPENDENT \ - --disable CUDA.DEVICE_DEPENDENT_CALLBACKS \ - --disable CUDA.DIVERGENCE_AT_COLLECTIVE_OPERATION \ - --disable CUDA.ERROR_INTERFACE \ - --disable CUDA.ERROR_KERNEL_LAUNCH \ - --disable CUDA.FORK \ - --disable CUDA.INACTIVE_THREAD_AT_COLLECTIVE_WARP \ - --disable CUDA.INITIATION_OBJECT_DEVICE_THREAD_BLOCK \ - --disable CUDA.INVALID_MEMORY_ACCESS \ - --disable CUDA.SHARE_FUNCTION \ - --disable CUDA.SHARE_OBJECT_STREAM_ASSOCIATED \ - --disable CUDA.SPECIFIERS_INCONSISTENCY \ - --disable CUDA.SYNCHRONIZE_TERMINATION \ - --disable INEFFICIENT_RESERVE \ - --disable MISSING_COMMA \ - --disable MISSING_MOVE_ASSIGNMENT \ - --disable OVERLAPPING_COPY \ - --disable STREAM_FORMAT_STATE \ - --disable UNINTENDED_INTEGER_DIVISION - - # Generate JSON report - $HOME/coverity/bin/cov-format-errors --dir coverity_output/ \ - --json-output-v8 "$REPORT_DIR/coverity-report.json" - - - name: Convert Coverity JSON to SARIF - run: | - REPORT_DIR="$GITHUB_WORKSPACE/reports" - python3 - <<'EOF' - import json, sys - - sarif = { - "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/main/sarif-2.1/schema/sarif-schema-2.1.0.json", - "version": "2.1.0", - "runs": [{ - "tool": { - "driver": { - "name": "Coverity", - "informationUri": "https://www.synopsys.com/software-integrity/security-testing/static-analysis-sast.html", - "rules": [] - } - }, - "results": [] - }] - } - - try: - with open("reports/coverity-report.json") as f: - cov = json.load(f) - except (FileNotFoundError, json.JSONDecodeError): - with open("reports/coverity-results.sarif", "w") as f: - json.dump(sarif, f, indent=2) - sys.exit(0) - - rules_map = {} - results = [] - - for issue in cov.get("issues", []): - checker = issue.get("checkerName", "unknown") - if checker not in rules_map: - rule_idx = len(rules_map) - rules_map[checker] = rule_idx - sarif["runs"][0]["tool"]["driver"]["rules"].append({ - "id": checker, - "shortDescription": {"text": issue.get("checkerProperties", {}).get("subcategoryShortDescription", checker)}, - "helpUri": f"https://community.synopsys.com/s/article/{checker}" - }) - - events = issue.get("events", []) - main_event = events[0] if events else {} - file_path = main_event.get("strippedFilePathname", main_event.get("filePathname", "unknown")) - line = main_event.get("lineNumber", 1) - - results.append({ - "ruleId": checker, - "ruleIndex": rules_map[checker], - "level": "warning", - "message": {"text": issue.get("checkerProperties", {}).get("subcategoryLongDescription", checker)}, - "locations": [{ - "physicalLocation": { - "artifactLocation": {"uri": file_path, "uriBaseId": "%SRCROOT%"}, - "region": {"startLine": line} - } - }] - }) - - sarif["runs"][0]["results"] = results - - with open("reports/coverity-results.sarif", "w") as f: - json.dump(sarif, f, indent=2) - - print(f"Converted {len(results)} Coverity issues to SARIF") - EOF - - - name: Upload SARIF to Security tab - uses: github/codeql-action/upload-sarif@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 - if: always() - with: - sarif_file: reports/coverity-results.sarif - category: coverity - - - name: Upload reports - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 - if: always() - with: - name: coverity-report-${{ github.run_id }} - path: reports/ - retention-days: 30 diff --git a/.github/workflows/daily_build.yml b/.github/workflows/daily_build.yml index 682d748..32f46f0 100644 --- a/.github/workflows/daily_build.yml +++ b/.github/workflows/daily_build.yml @@ -9,10 +9,6 @@ on: schedule: # Run at 10:00 PM UTC, Monday through Friday - cron: '0 22 * * 1-5' - - push: - branches: - - main workflow_dispatch: permissions: {} @@ -25,6 +21,7 @@ jobs: build: name: Daily Build runs-on: ubuntu-latest + timeout-minutes: 60 permissions: contents: read @@ -67,6 +64,9 @@ jobs: - name: Trivy Scan uses: ./.github/actions/analysis/trivy + - name: checksec Analysis + uses: ./.github/actions/analysis/checksec + - name: Upload daily build reports uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 if: always() @@ -74,3 +74,103 @@ jobs: name: DVLED-SW-TK-DailyBuild-${{ github.run_id }} path: ${{ github.workspace }}/reports/ retention-days: 30 + + afl-fuzz: + name: Daily AFL Fuzz + runs-on: ubuntu-latest + timeout-minutes: 25 + permissions: + contents: read + + steps: + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + ref: ${{ github.sha }} + fetch-depth: 0 + persist-credentials: false + + - name: AFL Fuzz + uses: ./.github/actions/analysis/afl-fuzz + with: + max-seconds: '300' + + - name: Upload AFL fuzzing results + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + if: always() + with: + name: afl-fuzz-results-${{ github.run_id }} + path: fuzz/findings/ + retention-days: 14 + + libfuzzer: + name: Daily libFuzzer + runs-on: ubuntu-latest + timeout-minutes: 30 + permissions: + contents: read + + steps: + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + ref: ${{ github.sha }} + fetch-depth: 0 + persist-credentials: false + + - name: libFuzzer + uses: ./.github/actions/analysis/libfuzzer + with: + max-seconds: '300' + + - name: Upload libFuzzer corpora + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + if: always() + with: + name: libfuzzer-results-${{ github.run_id }} + path: | + fuzz/libfuzzer_corpus/ + fuzz/ubsan_corpus/ + retention-days: 14 + + coverity: + name: Daily Coverity Static Analysis + runs-on: ubuntu-latest + timeout-minutes: 90 + permissions: + contents: read + security-events: write + + steps: + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + ref: ${{ github.sha }} + fetch-depth: 0 + persist-credentials: false + + - name: Environment check + uses: ./.github/actions/environment-check + + - name: Coverity Scan + uses: ./.github/actions/analysis/coverity + env: + COVERITY_URL: ${{ secrets.COVERITY_URL }} + COVERITY_USER: ${{ secrets.COVERITY_ARTIFACTORY_USER }} + COVERITY_PASSWORD: ${{ secrets.COVERITY_ARTIFACTORY_PASSWORD }} + + - name: Upload SARIF to Security tab + uses: github/codeql-action/upload-sarif@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 + if: always() + with: + sarif_file: reports/coverity-results.sarif + category: coverity + + - name: Upload Coverity reports + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + if: always() + with: + name: coverity-report-${{ github.run_id }} + path: reports/ + retention-days: 30 + diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml deleted file mode 100644 index 93c6b30..0000000 --- a/.github/workflows/fuzz.yml +++ /dev/null @@ -1,107 +0,0 @@ -# -# BSD 3-Clause License -# Copyright (C) 2026 Intel Corporation -# SPDX-License-Identifier: BSD-3-Clause -# -name: Fuzz Testing (AFL) - -on: - push: - branches: - - main - pull_request: - branches: - - main - schedule: - # Weekly on Wednesday at 04:00 UTC - - cron: '0 4 * * 3' - workflow_dispatch: - -permissions: {} - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - fuzz: - name: AFL Fuzz - Config Parser - runs-on: ubuntu-latest - permissions: - contents: read - - steps: - - name: Checkout repository - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: false - - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get install -y afl++ libavutil-dev libavformat-dev libavcodec-dev libswscale-dev pkg-config - - - name: Verify environment - run: | - echo "=== AFL++ ===" - afl-clang-fast --version || { echo "ERROR: afl-clang-fast not found"; exit 1; } - echo "" - echo "=== libavutil ===" - dpkg -l libavutil-dev | grep -q ii || { echo "ERROR: libavutil-dev not installed"; exit 1; } - echo " Header: $(find /usr/include -name 'avutil.h' | head -1)" - echo " Library: $(find /usr/lib -name 'libavutil.so*' | head -1)" - echo "" - echo "=== Compiler ===" - gcc --version | head -1 - echo "" - echo "Environment OK" - - - name: Build fuzz harness - run: | - cd fuzz - export CC=afl-clang-fast - # Compile each file separately with minimal flags to avoid AFL MAX_PARAMS_NUM - $CC -g -O1 -fno-omit-frame-pointer -I../include -c fuzz_config_reader.c -o fuzz_config_reader.o - $CC -g -O1 -fno-omit-frame-pointer -I../include -c ../src/util/config_reader.c -o config_reader.o - $CC -g -O1 -fno-omit-frame-pointer -I../include -c ../src/util/logger.c -o logger.o - # Link with afl-clang-fast (needs AFL runtime), pass only linker libs directly - $CC -o fuzz_config_reader fuzz_config_reader.o config_reader.o logger.o -lavutil -lm - echo "Build successful: $(file fuzz_config_reader)" - - - name: Run AFL fuzzer (timed) - run: | - cd fuzz - mkdir -p findings - export AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 - export AFL_SKIP_CPUFREQ=1 - # Run AFL for 5 minutes (CI time-boxed) - timeout 300 afl-fuzz -i corpus/ -o findings/ -V 300 -- ./fuzz_config_reader @@ || true - - - name: Check for crashes - run: | - cd fuzz - CRASH_COUNT=$(find findings/default/crashes -type f ! -name "README.txt" 2>/dev/null | wc -l) - echo "Crashes found: $CRASH_COUNT" - if [ "$CRASH_COUNT" -gt 0 ]; then - echo "::error::AFL found $CRASH_COUNT crash(es)!" - ls -la findings/default/crashes/ - exit 1 - fi - echo "No crashes found — fuzzing passed." - - - name: Sanitize AFL filenames for upload - if: always() - run: | - cd fuzz/findings - # Rename files with colons (AFL naming) to use underscores - find . -name '*:*' | while read f; do - mv "$f" "$(echo "$f" | tr ':' '_')" - done - - - name: Upload fuzzing results - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 - if: always() - with: - name: afl-fuzz-results-${{ github.run_id }} - path: fuzz/findings/ - retention-days: 14 diff --git a/.github/workflows/libfuzzer.yml b/.github/workflows/libfuzzer.yml deleted file mode 100644 index aaea7ec..0000000 --- a/.github/workflows/libfuzzer.yml +++ /dev/null @@ -1,94 +0,0 @@ -# -# BSD 3-Clause License -# Copyright (C) 2026 Intel Corporation -# SPDX-License-Identifier: BSD-3-Clause -# -name: Fuzz Testing (libFuzzer) - -on: - push: - branches: - - main - pull_request: - branches: - - main - schedule: - # Weekly on Thursday at 03:00 UTC - - cron: '0 3 * * 4' - workflow_dispatch: - -permissions: {} - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - libfuzzer: - name: libFuzzer - Config Parser - runs-on: ubuntu-latest - permissions: - contents: read # checkout repository - - steps: - - name: Checkout repository - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: false - - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get install -y clang libavutil-dev libavformat-dev libavcodec-dev libswscale-dev pkg-config - - - name: Build fuzz harness (AddressSanitizer + libFuzzer) - run: | - cd fuzz - export CC=clang - $CC -fsanitize=fuzzer,address -g -O1 -fno-omit-frame-pointer -I../include \ - fuzz_config_reader_libfuzzer.c \ - ../src/util/config_reader.c \ - ../src/util/logger.c \ - -o fuzz_config_reader_libfuzzer \ - $(pkg-config --cflags --libs libavutil) -lm - echo "Build successful: $(file fuzz_config_reader_libfuzzer)" - - - name: Run libFuzzer (timed) - run: | - cd fuzz - mkdir -p libfuzzer_corpus - # Seed from existing corpus, run for 5 minutes - ./fuzz_config_reader_libfuzzer \ - libfuzzer_corpus/ corpus/ \ - -max_total_time=300 \ - -print_final_stats=1 || FUZZ_EXIT=$? - if [ "${FUZZ_EXIT:-0}" -ne 0 ]; then - echo "::error::libFuzzer found a crash (exit code $FUZZ_EXIT)!" - exit 1 - fi - echo "No crashes found — libFuzzer passed." - - - name: Build fuzz harness (UndefinedBehaviorSanitizer + libFuzzer) - run: | - cd fuzz - export CC=clang - $CC -fsanitize=fuzzer,undefined -g -O1 -fno-omit-frame-pointer -I../include \ - fuzz_config_reader_libfuzzer.c \ - ../src/util/config_reader.c \ - ../src/util/logger.c \ - -o fuzz_config_reader_ubsan \ - $(pkg-config --cflags --libs libavutil) -lm - - - name: Run libFuzzer with UBSan (timed) - run: | - cd fuzz - mkdir -p ubsan_corpus - ./fuzz_config_reader_ubsan \ - ubsan_corpus/ corpus/ \ - -max_total_time=300 \ - -print_final_stats=1 || FUZZ_EXIT=$? - if [ "${FUZZ_EXIT:-0}" -ne 0 ]; then - echo "::error::libFuzzer+UBSan found an issue (exit code $FUZZ_EXIT)!" - exit 1 - fi - echo "No issues found — UBSan fuzzing passed." diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 56da48c..426435a 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -7,14 +7,10 @@ name: Pull Request on: pull_request: - types: [assigned, opened, synchronize, reopened] + types: [opened, synchronize, reopened, ready_for_review] branches: - main - push: - branches-ignore: - - main - workflow_dispatch: permissions: {} @@ -27,6 +23,7 @@ jobs: pull-request: name: Pull Request runs-on: ubuntu-latest + timeout-minutes: 25 permissions: contents: read @@ -65,12 +62,6 @@ jobs: - name: cppcheck uses: ./.github/actions/analysis/cppcheck - - name: Trivy Scan - uses: ./.github/actions/analysis/trivy - - - name: checksec Analysis - uses: ./.github/actions/analysis/checksec - - name: Upload PR reports uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 if: always() From c58341b3a70d499aa6c15753fa0ab4a72a9b7d01 Mon Sep 17 00:00:00 2001 From: roshan-ku Date: Wed, 3 Jun 2026 14:55:25 +0530 Subject: [PATCH 2/4] ci: fix zizmor template-injection findings --- .github/actions/analysis/afl-fuzz/action.yml | 8 +++++++- .github/actions/analysis/libfuzzer/action.yml | 16 ++++++++++++++-- .github/workflows/daily_build.yml | 2 +- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/.github/actions/analysis/afl-fuzz/action.yml b/.github/actions/analysis/afl-fuzz/action.yml index e16e38d..e36c34e 100644 --- a/.github/actions/analysis/afl-fuzz/action.yml +++ b/.github/actions/analysis/afl-fuzz/action.yml @@ -50,12 +50,18 @@ runs: - name: Run AFL fuzzer shell: bash + env: + MAX_SECONDS: ${{ inputs.max-seconds }} run: | cd fuzz + if ! [[ "$MAX_SECONDS" =~ ^[0-9]+$ ]]; then + echo "ERROR: max-seconds must be a positive integer" + exit 1 + fi mkdir -p findings export AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 export AFL_SKIP_CPUFREQ=1 - timeout "${{ inputs.max-seconds }}" afl-fuzz -i corpus/ -o findings/ -V "${{ inputs.max-seconds }}" -- ./fuzz_config_reader @@ || true + timeout "$MAX_SECONDS" afl-fuzz -i corpus/ -o findings/ -V "$MAX_SECONDS" -- ./fuzz_config_reader @@ || true - name: Check AFL crashes shell: bash diff --git a/.github/actions/analysis/libfuzzer/action.yml b/.github/actions/analysis/libfuzzer/action.yml index b400b05..7f27c06 100644 --- a/.github/actions/analysis/libfuzzer/action.yml +++ b/.github/actions/analysis/libfuzzer/action.yml @@ -23,7 +23,13 @@ runs: - name: Build and run libFuzzer (ASan) shell: bash + env: + MAX_SECONDS: ${{ inputs.max-seconds }} run: | + if ! [[ "$MAX_SECONDS" =~ ^[0-9]+$ ]]; then + echo "ERROR: max-seconds must be a positive integer" + exit 1 + fi cd fuzz export CC=clang $CC -fsanitize=fuzzer,address -g -O1 -fno-omit-frame-pointer -I../include \ @@ -36,7 +42,7 @@ runs: mkdir -p libfuzzer_corpus ./fuzz_config_reader_libfuzzer \ libfuzzer_corpus/ corpus/ \ - -max_total_time=${{ inputs.max-seconds }} \ + -max_total_time="$MAX_SECONDS" \ -print_final_stats=1 || FUZZ_EXIT=$? if [ "${FUZZ_EXIT:-0}" -ne 0 ]; then echo "::error::libFuzzer found a crash (exit code $FUZZ_EXIT)!" @@ -45,7 +51,13 @@ runs: - name: Build and run libFuzzer (UBSan) shell: bash + env: + MAX_SECONDS: ${{ inputs.max-seconds }} run: | + if ! [[ "$MAX_SECONDS" =~ ^[0-9]+$ ]]; then + echo "ERROR: max-seconds must be a positive integer" + exit 1 + fi cd fuzz export CC=clang $CC -fsanitize=fuzzer,undefined -g -O1 -fno-omit-frame-pointer -I../include \ @@ -58,7 +70,7 @@ runs: mkdir -p ubsan_corpus ./fuzz_config_reader_ubsan \ ubsan_corpus/ corpus/ \ - -max_total_time=${{ inputs.max-seconds }} \ + -max_total_time="$MAX_SECONDS" \ -print_final_stats=1 || FUZZ_EXIT=$? if [ "${FUZZ_EXIT:-0}" -ne 0 ]; then echo "::error::libFuzzer+UBSan found an issue (exit code $FUZZ_EXIT)!" diff --git a/.github/workflows/daily_build.yml b/.github/workflows/daily_build.yml index 32f46f0..c30ad47 100644 --- a/.github/workflows/daily_build.yml +++ b/.github/workflows/daily_build.yml @@ -139,7 +139,7 @@ jobs: timeout-minutes: 90 permissions: contents: read - security-events: write + security-events: write # Needed to upload Coverity SARIF to the Security tab. steps: - name: Checkout repository From 69020ee6b2202e6136bceafca7a256ccaa25f1f7 Mon Sep 17 00:00:00 2001 From: roshan-ku Date: Wed, 3 Jun 2026 14:58:11 +0530 Subject: [PATCH 3/4] ci: update workflow configuration --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2f54d67..f22c9e5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ concurrency: jobs: ci: - name: CI Full Validation + name: Continuous Integration runs-on: ubuntu-latest timeout-minutes: 45 permissions: From 37b50b1d6ad6f62052702541ff181894832299a3 Mon Sep 17 00:00:00 2001 From: roshan-ku Date: Thu, 4 Jun 2026 14:10:25 +0530 Subject: [PATCH 4/4] commented coverity section --- .github/actions/environment-check/action.yml | 2 +- .github/workflows/daily_build.yml | 80 ++++++++++---------- 2 files changed, 41 insertions(+), 41 deletions(-) diff --git a/.github/actions/environment-check/action.yml b/.github/actions/environment-check/action.yml index a05d2f5..4b10977 100644 --- a/.github/actions/environment-check/action.yml +++ b/.github/actions/environment-check/action.yml @@ -14,7 +14,7 @@ inputs: mtl-version: description: 'MTL release tag to build' required: false - default: 'v26.01' + default: 'ffmpeg-plugin-extra-pixel-format' ffmpeg-version: description: 'FFmpeg release branch to build' required: false diff --git a/.github/workflows/daily_build.yml b/.github/workflows/daily_build.yml index c30ad47..f08a2da 100644 --- a/.github/workflows/daily_build.yml +++ b/.github/workflows/daily_build.yml @@ -133,44 +133,44 @@ jobs: fuzz/ubsan_corpus/ retention-days: 14 - coverity: - name: Daily Coverity Static Analysis - runs-on: ubuntu-latest - timeout-minutes: 90 - permissions: - contents: read - security-events: write # Needed to upload Coverity SARIF to the Security tab. - - steps: - - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - ref: ${{ github.sha }} - fetch-depth: 0 - persist-credentials: false - - - name: Environment check - uses: ./.github/actions/environment-check - - - name: Coverity Scan - uses: ./.github/actions/analysis/coverity - env: - COVERITY_URL: ${{ secrets.COVERITY_URL }} - COVERITY_USER: ${{ secrets.COVERITY_ARTIFACTORY_USER }} - COVERITY_PASSWORD: ${{ secrets.COVERITY_ARTIFACTORY_PASSWORD }} - - - name: Upload SARIF to Security tab - uses: github/codeql-action/upload-sarif@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 - if: always() - with: - sarif_file: reports/coverity-results.sarif - category: coverity - - - name: Upload Coverity reports - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - if: always() - with: - name: coverity-report-${{ github.run_id }} - path: reports/ - retention-days: 30 + # coverity: + # name: Daily Coverity Static Analysis + # runs-on: ubuntu-latest + # timeout-minutes: 90 + # permissions: + # contents: read + # security-events: write # Needed to upload Coverity SARIF to the Security tab. + # + # steps: + # - name: Checkout repository + # uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + # with: + # ref: ${{ github.sha }} + # fetch-depth: 0 + # persist-credentials: false + # + # - name: Environment check + # uses: ./.github/actions/environment-check + # + # - name: Coverity Scan + # uses: ./.github/actions/analysis/coverity + # env: + # COVERITY_URL: ${{ secrets.COVERITY_URL }} + # COVERITY_USER: ${{ secrets.COVERITY_ARTIFACTORY_USER }} + # COVERITY_PASSWORD: ${{ secrets.COVERITY_ARTIFACTORY_PASSWORD }} + # + # - name: Upload SARIF to Security tab + # uses: github/codeql-action/upload-sarif@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 + # if: always() + # with: + # sarif_file: reports/coverity-results.sarif + # category: coverity + # + # - name: Upload Coverity reports + # uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + # if: always() + # with: + # name: coverity-report-${{ github.run_id }} + # path: reports/ + # retention-days: 30