ci: add MemorySanitizer CI job

Add build_msan_toolchain.sh to produce a tarball containing an
MSan-instrumented libc++/libc++abi/libunwind toolchain, and add an msan
CI job that downloads the tarball and runs the test suite under MSan.

Also add USE_MSAN CMake option that disables conflicting sanitizers,
switches to lld, and propagates -fsanitize=memory to the shared library
and fuzz_driver targets.
This commit is contained in:
2026-07-22 18:42:10 -04:00
committed by weaselbot
parent 8afe5ec75b
commit 0510f01fe1
3 changed files with 157 additions and 5 deletions
+33 -5
View File
@@ -49,6 +49,18 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
${LLVM_OBJCOPY}
CACHE FILEPATH "path to objcopy binary" FORCE)
endif()
if(USE_MSAN)
find_program(LLD_LINKER lld)
if(LLD_LINKER)
set(CMAKE_LINKER_TYPE
"LLD"
CACHE STRING "Use LLD linker" FORCE)
set(CMAKE_LINKER
${LLD_LINKER}
CACHE FILEPATH "path to linker binary" FORCE)
add_link_options("-fuse-ld=lld")
endif()
endif()
endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
@@ -103,6 +115,8 @@ option(USE_SIMD_FALLBACK
option(DISABLE_TSAN "Disable TSAN" OFF)
option(USE_MSAN "Build with MemorySanitizer (disables ASan/UBSan)" OFF)
# This is encouraged according to
# https://valgrind.org/docs/manual/manual-core-adv.html#manual-core-adv.clientreq
include_directories(SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/third_party/valgrind)
@@ -232,8 +246,10 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR AND BUILD_TESTING)
target_compile_definitions(conflict_set_main PRIVATE ENABLE_MAIN)
target_link_libraries(conflict_set_main PRIVATE nanobench)
if(NOT APPLE)
# libfuzzer target, to generate/manage corpus
if(NOT APPLE AND NOT USE_MSAN)
# libfuzzer target, to generate/manage corpus. MSan requires an instrumented
# libfuzzer runtime, which is not shipped with the compiler, so skip this
# target when building with MSan.
set(FUZZ_FLAGS "-fsanitize=fuzzer-no-link,address,undefined")
include(CheckCXXCompilerFlag)
cmake_push_check_state()
@@ -257,8 +273,13 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR AND BUILD_TESTING)
add_executable(fuzz_driver ConflictSet.cpp FuzzTestDriver.cpp)
target_compile_options(fuzz_driver PRIVATE ${TEST_FLAGS})
if(NOT CMAKE_CROSSCOMPILING)
target_compile_options(fuzz_driver PRIVATE -fsanitize=address,undefined)
target_link_options(fuzz_driver PRIVATE -fsanitize=address,undefined)
if(USE_MSAN)
target_compile_options(fuzz_driver PRIVATE -fsanitize=memory)
target_link_options(fuzz_driver PRIVATE -fsanitize=memory)
else()
target_compile_options(fuzz_driver PRIVATE -fsanitize=address,undefined)
target_link_options(fuzz_driver PRIVATE -fsanitize=address,undefined)
endif()
endif()
target_compile_definitions(fuzz_driver PRIVATE ENABLE_FUZZ)
target_include_directories(fuzz_driver
@@ -269,7 +290,9 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR AND BUILD_TESTING)
endforeach()
# tsan tests
if(NOT CMAKE_CROSSCOMPILING AND NOT DISABLE_TSAN)
if(NOT CMAKE_CROSSCOMPILING
AND NOT DISABLE_TSAN
AND NOT USE_MSAN)
add_executable(tsan_driver ConflictSet.cpp FuzzTestDriver.cpp)
target_compile_options(tsan_driver PRIVATE ${TEST_FLAGS} -fsanitize=thread)
target_link_options(tsan_driver PRIVATE -fsanitize=thread)
@@ -491,6 +514,11 @@ target_include_directories(
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}>)
if(USE_MSAN)
target_compile_options(${PROJECT_NAME} PUBLIC -fsanitize=memory)
target_link_options(${PROJECT_NAME} PUBLIC -fsanitize=memory)
endif()
set_target_properties(
${PROJECT_NAME} PROPERTIES VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR})