From 0133da24b5d8a9fdfd37b25ceb6a096a7303d34e Mon Sep 17 00:00:00 2001 From: Xavier Roche Date: Fri, 26 Jun 2026 22:13:37 +0200 Subject: [PATCH] ci: add a MemorySanitizer job for the offline engine self-tests MSan is the only sanitizer that catches a read of uninitialized memory -- the class of #143, where the size filter tested an uninitialized stack LLint and forbade files at random. ASan and UBSan let that through. MSan reports any byte produced by an uninstrumented library as uninitialized, so the job stays inside our own code: clang, a static link (the MSan runtime is not injected into shared objects), --disable-https to drop openssl, and only the offline 01_engine-* self-tests minus the zlib-backed cache trio. Those self-tests drive the hostile-input parsers (charset, mime, html, entities, idna, filters) straight through MSan. Co-Authored-By: Claude Opus 4.8 Signed-off-by: Xavier Roche --- .github/workflows/ci.yml | 45 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f4501268..ff8ace8f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -188,6 +188,51 @@ jobs: if: failure() run: cat tests/test-suite.log 2>/dev/null || true + # MemorySanitizer catches reads of uninitialized memory (#143's stack-garbage + # size filter) that ASan/UBSan miss. It flags any byte an uninstrumented lib + # wrote, so the job stays in our own code: offline self-tests only, no openssl + # (--disable-https), no zlib cache tests, static (the runtime is not in .so's). + msan: + name: msan (MemorySanitizer, clang) + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v6 + with: + submodules: recursive + + - name: Install build dependencies + run: | + set -euo pipefail + sudo apt-get update + sudo apt-get install -y --no-install-recommends \ + build-essential clang autoconf automake libtool autoconf-archive \ + zlib1g-dev + + - name: Configure (MSan, static, no https) + run: | + set -euo pipefail + autoreconf -fi + ./configure CC=clang \ + CFLAGS="-fsanitize=memory -fsanitize-memory-track-origins=2 -fno-sanitize-recover=all -g -O1 -fno-omit-frame-pointer" \ + LDFLAGS="-fsanitize=memory" \ + --disable-https --disable-shared --enable-static + + - name: Build + run: make -j"$(nproc)" + + - name: Test (offline self-tests under MSan) + env: + MSAN_OPTIONS: abort_on_error=1:halt_on_error=1 + run: | + set -euo pipefail + # Engine self-tests only; the cache trio pulls in uninstrumented zlib. + tests="$(cd tests && ls 01_engine-*.test | grep -v -- '-cache' | tr '\n' ' ')" + make check TESTS="$tests" + + - name: Print the test log on failure + if: failure() + run: cat tests/test-suite.log 2>/dev/null || true + # Optional-dependency build: compile and test with HTTPS/OpenSSL disabled -- # the configuration users on minimal systems build, and one libssl is not even # installed here so configure cannot silently re-enable it. The matrix above