Underflow fix v4 #32
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: fuzz | |
| # Short libFuzzer smoke run against the fast CSV scan engine. Compiles the | |
| # parser unity TU together with the libFuzzer harness from app/test/sec/ | |
| # under ASan+UBSan and runs for a fixed wall-clock budget on each PR / | |
| # push to main. Linux only — libFuzzer's runtime ships with clang on Linux | |
| # but is not part of Apple Clang. Skipped when cross-compiling. | |
| on: | |
| push: | |
| branches: [main] | |
| paths-ignore: | |
| - '**.md' | |
| - 'docs/**' | |
| pull_request: | |
| branches: [main] | |
| paths-ignore: | |
| - '**.md' | |
| - 'docs/**' | |
| workflow_dispatch: | |
| inputs: | |
| max_total_time: | |
| description: 'libFuzzer wall-clock budget, seconds' | |
| required: false | |
| default: '60' | |
| permissions: | |
| contents: read | |
| defaults: | |
| run: | |
| shell: bash | |
| jobs: | |
| libfuzzer: | |
| # Linux x86_64 only — Apple Clang ships without libFuzzer; cross-builds | |
| # use a different toolchain and would not produce a runnable binary. | |
| runs-on: ubuntu-latest | |
| env: | |
| MAX_TOTAL_TIME: ${{ inputs.max_total_time || '60' }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Generate include/zsv.h from include/zsv.h.in | |
| # `include/zsv.h` is .gitignored — `make -C src build` normally | |
| # generates it from `include/zsv.h.in` via a sed substitution. We | |
| # don't want to run the full library build here (drags in jq / | |
| # ncurses); the sed below is the no-ZSV_EXTRAS branch of the rule | |
| # at src/Makefile, which matches our build flags (we don't set | |
| # -DZSV_EXTRAS). | |
| run: | | |
| set -eux | |
| sed 's/__ZSV_EXTRAS__DEFINE__//' < include/zsv.h.in > include/zsv.h | |
| - name: Build libFuzzer harness | |
| run: | | |
| set -eux | |
| mkdir -p build/fuzz | |
| # Compile parser unity TU + libFuzzer harness in one invocation. | |
| # No ./configure needed — the parser is dependency-free. | |
| clang \ | |
| -fsanitize=fuzzer,address,undefined \ | |
| -fno-omit-frame-pointer \ | |
| -O1 -g -std=gnu11 -fsigned-char \ | |
| -DZSV_VERSION=\"ci-fuzz\" \ | |
| -DHAVE_MEMMEM -DHAVE___BUILTIN_EXPECT \ | |
| -I include -I src -I app/external/sqlite3 \ | |
| src/zsv.c app/test/sec/libfuzzer.c \ | |
| -o build/fuzz/zsv_parse_bytes_fuzzer | |
| - name: Run libFuzzer | |
| run: | | |
| set -eux | |
| mkdir -p fuzz-corpus | |
| cp app/test/sec/poc/*.bin fuzz-corpus/ || true | |
| # -max_total_time bounds wall-clock; -timeout aborts hung iterations; | |
| # -error_exitcode=77 lets the workflow distinguish a corpus-found | |
| # crash (77) from libFuzzer's own internal failures (non-zero, non-77). | |
| ./build/fuzz/zsv_parse_bytes_fuzzer \ | |
| -max_total_time="${MAX_TOTAL_TIME}" \ | |
| -timeout=30 \ | |
| -error_exitcode=77 \ | |
| -print_final_stats=1 \ | |
| fuzz-corpus | |
| - name: Upload crash artifacts on failure | |
| if: failure() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: libfuzzer-findings | |
| path: | | |
| crash-* | |
| leak-* | |
| timeout-* | |
| if-no-files-found: ignore | |
| retention-days: 14 |