From 00574ef8b482787d060ca5dfd254e86b7ea85e3c Mon Sep 17 00:00:00 2001 From: Stephan Beyer Date: Sat, 16 May 2020 01:52:29 +0200 Subject: [PATCH] Make sanitizer options more fine-grained The SANITIZE_ADDRESS option of our CMake configuration activates the AddressSanitizer (and UBSan in a non-working way) for the whole project (although, by the way, its documentation pretends that it is only enabled for tests). This commit introduces new options SANITIZE_LEAK, SANITIZE_MEMORY, SANITIZE_UNDEFINED, SANITIZE_THREAD. Each of these options (including SANITIZE_ADDRESS) enables only the corresponding sanitizer. Moreover, we mark all sanitizer options as advanced options, because these options are only interesting for developers. Note that some sanitizers are conflicting, that is, not all options can be enabled simultaneously. Also, not all sanitizers are available for all compilers and versions. We, however, do not check for this, instead we let the compiler throw its errors in such cases. The explicit usage of the Google Linker is removed, because it is not necessary and can lead to problems with clang. The commit can be considered a rewrite of cmake/modules/SanitizerFlags.cmake. Signed-off-by: Stephan Beyer --- CMakeLists.txt | 6 +---- cmake/modules/SanitizerFlags.cmake | 40 ++++++++++++++++++++---------- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 55e846493..5df238838 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -228,11 +228,7 @@ if (APPLE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") endif() -option(SANITIZE_ADDRESS "Enable address sanitizer in tests" OFF) -if (SANITIZE_ADDRESS) - include(SanitizerFlags) - enable_sanitizer() -endif () +include(SanitizerFlags) # Handle Translations, pick all client_* files from trans directory. file( GLOB TRANS_FILES ${CMAKE_SOURCE_DIR}/translations/client_*.ts) diff --git a/cmake/modules/SanitizerFlags.cmake b/cmake/modules/SanitizerFlags.cmake index 9d5c9ebda..433190182 100644 --- a/cmake/modules/SanitizerFlags.cmake +++ b/cmake/modules/SanitizerFlags.cmake @@ -1,17 +1,31 @@ - # Enable address sanitizer (gcc/clang only) -macro(ENABLE_SANITIZER) +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") + set(SANITIZERS) - if (NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") - message(FATAL_ERROR "Sanitizer supported only for gcc/clang") - endif() + macro(add_sanitizer_option variable flag help) + option(${variable} "Enable ${help}" OFF) + if(${variable}) + list(APPEND SANITIZERS ${flag}) + endif() + mark_as_advanced(${variable}) + endmacro() - set(SANITIZER_FLAGS "-fsanitize=address -fsanitize=leak -g") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SANITIZER_FLAGS}") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SANITIZER_FLAGS}") - - set(LINKER_FLAGS "-fsanitize=address,undefined -fuse-ld=gold") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LINKER_FLAGS}") - -endmacro() + add_sanitizer_option(SANITIZE_ADDRESS "address" + "AddressSanitizer (detects memory violations, buffer overflows, memory leaks)") + add_sanitizer_option(SANITIZE_LEAK "leak" + "standalone LeakSanitizer (detects memory leaks only)") + add_sanitizer_option(SANITIZE_MEMORY "memory" + "MemorySanitizer (detects reads in uninitialized memory)") + add_sanitizer_option(SANITIZE_UNDEFINED "undefined" + "UndefinedBehaviorSanitizer (detects undefined behavior)") + add_sanitizer_option(SANITIZE_THREAD "thread" + "ThreadSanitizer (detects data races)") + if(SANITIZERS) + string(REPLACE ";" "," SANITIZER_FLAGS "${SANITIZERS}") + set(SANITIZER_FLAGS "-fsanitize=${SANITIZER_FLAGS}") + string(APPEND CMAKE_CXX_FLAGS " ${SANITIZER_FLAGS}") + string(APPEND CMAKE_C_FLAGS " ${SANITIZER_FLAGS}") + string(APPEND CMAKE_EXE_LINKER_FLAGS " ${SANITIZER_FLAGS}") + endif() +endif()