Skip to content

Harden the cmake Address Sanitizer detection code.#960

Merged
nmoinvaz merged 4 commits into
zlib-ng:developfrom
pmqs:sanitizer
Apr 23, 2026
Merged

Harden the cmake Address Sanitizer detection code.#960
nmoinvaz merged 4 commits into
zlib-ng:developfrom
pmqs:sanitizer

Conversation

@pmqs
Copy link
Copy Markdown
Contributor

@pmqs pmqs commented Feb 10, 2026

Currently the sanitizer detection code will silently ignore error cases -- like when given an unknown option or when it is asked for a valid sanitizer that isn't available for the platform. This one has stung me a few times.

This change makes it a fatal error to

  1. ask for an address sanitizer option that doesn't exist
  2. asks for a valid option that the current platform doesn't support.

One thng that dropped out with this change is the use of the Memory Sanitizer in build.yml, Turns out that it is not available on Ubuntu, so has been adding nothing to our test coverage. I think that may be a limitation of virtualisation. I've just disabled it for now.

This is what build.yml had when (not) detecting the memory Sanitizer:

-- Checking for Address Sanitizer Option
-- Performing Test HAVE_SANITIZER_memory
-- Performing Test HAVE_SANITIZER_memory - Failed
-- Memory sanitizer is not supported

@nmoinvaz
Copy link
Copy Markdown
Member

The sanitizer CMake is too borrowed from zlib-ng, so I'm uncomfortable changing it.

Comment thread CMakeLists.txt Outdated
endif()
if(NOT MZ_STATUS)
set(MZ_SANITIZER_ENABLED OFF)
message(FATAL_ERROR "Cannot enable the Address Sanitizer '${MZ_SANITIZER}' option")
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's just log "Sanitizer" without "Address", as it can be any of them.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment thread CMakeLists.txt Outdated
endif()
elseif(MZ_SANITIZER_LOWER STREQUAL "none")
set(MZ_SANITIZER_ENABLED OFF)
message(STATUS " Address Sanitizer not enabled")
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's just log "Sanitizer" without "Address", as it can be any of them.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment thread CMakeLists.txt Outdated
add_feature_info(MZ_BUILD_UNIT_TESTS MZ_BUILD_UNIT_TESTS "Builds minizip unit test project")
add_feature_info(MZ_BUILD_FUZZ_TESTS MZ_BUILD_FUZZ_TESTS "Builds minizip fuzzer executables")
add_feature_info(MZ_CODE_COVERAGE MZ_CODE_COVERAGE "Builds with code coverage flags")
add_feature_info(MZ_SANITIZER MZ_SANITIZER_ENABLED "Builds with Address Sanitizer")
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's just log "Sanitizer Support" instead of "Address Sanitizer", as it can be any of them.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@Coeur
Copy link
Copy Markdown
Collaborator

Coeur commented Feb 14, 2026

The sanitizer CMake is too borrowed from zlib-ng, so I'm uncomfortable changing it.

The change looks good to me.

@pmqs can you also offer a PR for the zlib-ng repository eventually?

@pmqs
Copy link
Copy Markdown
Contributor Author

pmqs commented Feb 14, 2026

The sanitizer CMake is too borrowed from zlib-ng, so I'm uncomfortable changing it.

The change looks good to me.

@pmqs can you also offer a PR for the zlib-ng repository eventually?

@Coeur, as it happens I'm ahead of you. Already looking at the equivalent change in zlib-ng because there is a knock-on impact with it for Sanitizer support with the Microsoft C compiler. Will write up the details in the zlib-ng PR.

I'll park this change for now & get the same fix done in the much simpler zlib-ng use case sorted first.

Comment thread CMakeLists.txt Outdated
add_thread_sanitizer()
elseif(MZ_SANITIZER STREQUAL "Undefined")
add_undefined_sanitizer()
message(STATUS "Checking for Address Sanitizer Option")
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe remove "Address" here?

@pmqs pmqs force-pushed the sanitizer branch 2 times, most recently from 53fc513 to 5bede13 Compare March 10, 2026 16:36
Comment thread .github/workflows/build.yml Outdated
cxx-compiler: g++
cmake-args: -D MZ_SANITIZER=Memory
codecov: ubuntu_gcc_msan
# Memory Sanitizer not currenly supported on GitHub
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://stackoverflow.com/questions/71675493/how-use-memory-sanitizer-with-use-gcc
From what I have seen, MSAN is not supported with GCC, so I think this can be removed.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, that's my understanding as well -- clang only

@nmoinvaz
Copy link
Copy Markdown
Member

nmoinvaz commented Apr 8, 2026

Has this been updated with the latest changes from zlib-ng?

@pmqs
Copy link
Copy Markdown
Contributor Author

pmqs commented Apr 9, 2026

Has this been updated with the latest changes from zlib-ng?

Yes, it has.

@nmoinvaz
Copy link
Copy Markdown
Member

@pmqs can you please rebase this and see if those Windows builds are fixed? I would do it myself, but last time it messed it up for you.

@pmqs
Copy link
Copy Markdown
Contributor Author

pmqs commented Apr 21, 2026

@pmqs can you please rebase this and see if those Windows builds are fixed? I would do it myself, but last time it messed it up for you.

@nmoinvaz try that now

@nmoinvaz
Copy link
Copy Markdown
Member

Rather than deleting the MSAN job, change it to use clang, matching zlib-ng's approach:

  • rename to "Ubuntu Clang MSAN"
  • set compiler: clang-20 / cxx-compiler: clang++-20
  • in the apt install step, add libclang-rt-20-dev (provides the MSAN runtime) — without it, link fails even though compile succeeds

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 22, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c3716845-4379-454d-abe8-06a42695783d

📥 Commits

Reviewing files that changed from the base of the PR and between 57792a1 and 8ec0b09.

📒 Files selected for processing (1)
  • .github/workflows/build.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/build.yml

Walkthrough

This PR switches the CI MSAN job from GCC to Clang, updates MSAN-related CI tooling and build flags, normalizes and lowercases CMake sanitizer option handling, and turns several sanitizer detection failures (Memory/Thread/UB) into fatal CMake errors while adjusting ASan handling on MSVC.

Changes

Cohort / File(s) Summary
CI Workflow Configuration
.github/workflows/build.yml
Replaced Ubuntu GCC MSAN matrix entry with an Ubuntu Clang MSAN entry (clang-20/clang++-20), added ninja-build, llvm-20, libclang-rt-20-dev, set CMake to Ninja and Debug (-GNinja -DMZ_SANITIZER=Memory, build-config: Debug), set gcov-exec: llvm-cov-20 gcov, added msan-options: use_sigaltstack=0, and removed previous codecov matrix flag.
CMake sanitizer options & detection
CMakeLists.txt, cmake/detect-sanitizer.cmake
Changed MZ_SANITIZER cache default from AUTO to OFF, expanded/normalized allowed values to lowercase, added string(TOLOWER ...) normalization and explicit empty/unknown handling, added add_feature_info(MZ_SANITIZER ...), made Memory/Thread/Undefined sanitizer support checks fatal errors (previously STATUS), and adjusted ASan handling on MSVC to use add_compile_options("/fsanitize=...","/Zi") while avoiding link-time /fsanitize.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Harden the cmake Address Sanitizer detection code.' accurately describes the main change: making CMake sanitizer detection stricter by treating unknown or unsupported options as fatal errors.
Description check ✅ Passed The description clearly explains the change: making sanitizer detection fail fast for unknown or unsupported options, and documents the resulting adjustment to build.yml (switching from GCC MSAN to Clang MSAN due to platform limitations).
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b074582b-6336-49c5-9a24-b172582c5a7d

📥 Commits

Reviewing files that changed from the base of the PR and between 2f074dc and 57792a1.

📒 Files selected for processing (3)
  • .github/workflows/build.yml
  • CMakeLists.txt
  • cmake/detect-sanitizer.cmake

Comment thread .github/workflows/build.yml Outdated
Comment on lines +35 to +37
build-config: Debug
# https://github.com/llvm/llvm-project/issues/55785
msan-options: use_sigaltstack=0
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

build-config: Debug and msan-options are both effectively no-ops here.

Two problems in the same matrix entry:

  1. build-config: Debug is consumed at build/test time (--config ${{ matrix.build-config || 'Release' }} on lines 260 and 263), but the configure step on line 252 hardcodes -D CMAKE_BUILD_TYPE=Release, and this job uses -GNinja (a single-config generator) so --config is ignored. Net result: the MSAN job compiles and runs a Release binary, which is exactly the configuration you don't want for triaging sanitizer reports (inlining/opt noise, poor origin tracking).
  2. msan-options: use_sigaltstack=0 is defined but never exported. There is no reference to matrix.msan-options anywhere in the env: blocks of the Compile source code or Run test cases steps, so MSAN_OPTIONS is never set and the sigaltstack workaround (the reason the llvm issue is even linked on line 36) won't take effect at runtime.

Suggested wiring:

🔧 Proposed fix
     - name: Generate project files
       shell: bash
       run: |
         cmake -S . -B ${{ matrix.build-dir || '.' }} ${{ matrix.cmake-args }} \
           -D MZ_BUILD_TESTS=ON \
           -D MZ_BUILD_UNIT_TESTS=ON \
           -D BUILD_SHARED_LIBS=OFF \
-          -D CMAKE_BUILD_TYPE=Release
+          -D CMAKE_BUILD_TYPE=${{ matrix.build-config || 'Release' }}
       env:
         CC: ${{ matrix.compiler }}
         CXX: ${{ matrix.cxx-compiler }}
         CFLAGS: ${{ matrix.cflags }}
         LDFLAGS: ${{ matrix.ldflags }}

     - name: Compile source code
       run: cmake --build ${{ matrix.build-dir || '.' }} --config ${{ matrix.build-config || 'Release' }}

     - name: Run test cases
       run: ctest --output-on-failure -C ${{ matrix.build-config || 'Release' }}
       working-directory: ${{ matrix.build-dir }}
+      env:
+        MSAN_OPTIONS: ${{ matrix.msan-options }}

Comment thread cmake/detect-sanitizer.cmake
@nmoinvaz nmoinvaz merged commit 3e10f4d into zlib-ng:develop Apr 23, 2026
29 of 30 checks passed
@nmoinvaz
Copy link
Copy Markdown
Member

@pmqs thanks for your help! I will fix the MSAN issues from here.

@pmqs
Copy link
Copy Markdown
Contributor Author

pmqs commented Apr 23, 2026

@pmqs thanks for your help! I will fix the MSAN issues from here.

No worries @nmoinvaz . My fix was a work-on-progress that I didn't get a chance to look at yesterday. Thanks for finishing it off.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants