CMake modules to help use sanitizers

Overview

sanitizers-cmake

MIT

CMake module to enable sanitizers for binary targets.

Include into your project

To use FindSanitizers.cmake, simply add this repository as git submodule into your own repository

mkdir externals
git submodule add git://github.com/arsenm/sanitizers-cmake.git externals/sanitizers-cmake

and adding externals/sanitizers-cmake/cmake to your CMAKE_MODULE_PATH

set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/externals/sanitizers-cmake/cmake" ${CMAKE_MODULE_PATH})

If you don't use git or dislike submodules you can copy the files in cmake directory into your repository. Be careful and keep updates in mind!

Now you can simply run find_package in your CMake files:

find_package(Sanitizers)

Usage

You can enable the sanitizers with SANITIZE_ADDRESS, SANITIZE_MEMORY, SANITIZE_THREAD or SANITIZE_UNDEFINED options in your CMake configuration. You can do this by passing e.g. -DSANITIZE_ADDRESS=On on your command line or with your graphical interface.

If sanitizers are supported by your compiler, the specified targets will be build with sanitizer support. If your compiler has no sanitizing capabilities (I asume intel compiler doesn't) you'll get a warning but CMake will continue processing and sanitizing will simply just be ignored.

Compiler issues

Different compilers may be using different implementations for sanitizers. If you'll try to sanitize targets with C and Fortran code but don't use gcc & gfortran but clang & gfortran, this will cause linking problems. To avoid this, such problems will be detected and sanitizing will be disabled for these targets.

Even C only targets may cause problems in certain situations. Some problems have been seen with AddressSanitizer for preloading or dynamic linking. In such cases you may try the SANITIZE_LINK_STATIC to link sanitizers for gcc static.

Build targets with sanitizer support

To enable sanitizer support you simply have to add add_sanitizers(<TARGET>) after defining your target. To provide a sanitizer blacklist file you can use the sanitizer_add_blacklist_file(<FILE>) function:

find_package(Sanitizers)

sanitizer_add_blacklist_file("blacklist.txt")

add_executable(some_exe foo.c bar.c)
add_sanitizers(some_exe)

add_library(some_lib foo.c bar.c)
add_sanitizers(some_lib)

Run your application

The sanitizers check your program, while it's running. In some situations (e.g. LD_PRELOAD your target) it might be required to preload the used AddressSanitizer library first. In this case you may use the asan-wrapper script defined in ASan_WRAPPER variable to execute your application with ${ASan_WRAPPER} myexe arg1 ....

Contribute

Anyone is welcome to contribute. Simply fork this repository, make your changes in an own branch and create a pull-request for your change. Please do only one change per pull-request.

You found a bug? Please fill out an issue and include any data to reproduce the bug.

Contributors

Comments
  • How do I check the sanitizer is available?

    How do I check the sanitizer is available?

    There doesn't seem to be any way to tell whether the requested sanitizer will actually be used. Like, suppose you ask for the memory sanitizer, but it isn't available.

    CMake Warning at submodules/sanitizers-cmake/cmake/FindMSan.cmake:36 (message):
      MemorySanitizer disabled for target because MemorySanitizer is supported
      for Linux systems only.
    Call Stack (most recent call first):
      submodules/sanitizers-cmake/cmake/FindSanitizers.cmake:39 (find_package)
      CMakeLists.txt:18 (find_package)
    

    How can you tell when this happens? I want to be able to check with an if so the build can stop when the sanitizer isn't available.

    I'm hoping I've missed something but if not then I can (try to) add this functionality it.

    Thanks,

    --Tom

    opened by tom-seddon 5
  • Syntax error when running set

    Syntax error when running set

    I'm running the set command as root but I'm getting an error

    $ set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/externals/sanitizers-cmake/cmake" ${CMAKE_MODULE_PATH})
    syntax error near unexpected token `CMAKE_MODULE_PATH'
    

    I also just tried this but the error still happened when I'm building goestools

    export CMAKE_MODULE_PATH=/root/repos/goestools/cmake
    

    Then in goestools/build directory, I executed cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local. The error I'm getting is

    CMake Warning at CMakeLists.txt:36 (find_package):
      By not providing "FindSanitizers.cmake" in CMAKE_MODULE_PATH this project
      has asked CMake to find a package configuration file provided by
      "Sanitizers", but CMake did not find one.
    
      Could not find a package configuration file provided by "Sanitizers" with
      any of the following names:
    
        SanitizersConfig.cmake
        sanitizers-config.cmake
    
      Add the installation prefix of "Sanitizers" to CMAKE_PREFIX_PATH or set
      "Sanitizers_DIR" to a directory containing one of the above files.  If
      "Sanitizers" provides a separate development package or SDK, be sure it has
      been installed.
    
    
    CMake Error at CMakeLists.txt:59 (add_subdirectory):
      The source directory
    
        /root/repos/goestools/vendor/libcorrect
    
      does not contain a CMakeLists.txt file.
    
    
    CMake Error at CMakeLists.txt:60 (add_subdirectory):
      The source directory
    
        /root/repos/goestools/vendor/libaec
    
      does not contain a CMakeLists.txt file.
    
    
    CMake Error at CMakeLists.txt:68 (add_subdirectory):
      The source directory
    
        /root/repos/goestools/vendor/nanomsg
    
      does not contain a CMakeLists.txt file.
    
    
    CMake Error at src/lrit/CMakeLists.txt:4 (add_sanitizers):
      Unknown CMake command "add_sanitizers".
    
    
    -- Configuring incomplete, errors occurred!
    See also "/root/repos/goestools/build/CMakeFiles/CMakeOutput.log".
    See also "/root/repos/goestools/build/CMakeFiles/CMakeError.log".
    
    opened by c0debreaker 4
  • Set CMP0051 to new.

    Set CMP0051 to new.

    To avoid error messages about CMP0051, this policy will be set to new.

    This will throw a warning about CMP0011, but this has to be set only once for the whole project:

     CMake Warning (dev) in externals/CMake-sanitizers/cmake/FindSanitizers.cmake:
      Policy CMP0011 is not set: Included scripts do automatic cmake_policy PUSH
      and POP.  Run "cmake --help-policy CMP0011" for policy details.  Use the
      cmake_policy command to set the policy and suppress this warning.
    
      The included script
    
       [...]/externals/CMake-sanitizers/cmake/FindSanitizers.cmake
    
      affects policy settings.  CMake is implying the NO_POLICY_SCOPE option for
      compatibility, so the effects are applied to the including context.
    Call Stack (most recent call first):
      [...]
    This warning is for project developers.  Use -Wno-dev to suppress it.
    
    opened by alehaa 1
  • README.md: update sanitizers-cmake submodule repo link

    README.md: update sanitizers-cmake submodule repo link

    When I clone sanitizers-cmake repo into my project according to Include into your project , it seems fail until type ctrl + c, the result in my terminal as follows:

    ➜  /Users/junbozheng/san git:(master) time git submodule add git://github.com/arsenm/sanitizers-cmake.git externals/sanitizers-cmake
    Cloning into '/Users/junbozheng/san/externals/sanitizers-cmake'...
    ^C
    git submodule add git://github.com/arsenm/sanitizers-cmake.git   0.18s user 0.20s system 0% cpu 49.989 total
    

    Then, I checked the sanitizers-cmake submodule repo link and update it, I try again, and it seems fine to me.

    ➜  /Users/junbozheng/san git:(master) time git submodule add [email protected]:arsenm/sanitizers-cmake.git externals/sanitizers-cmake
    Cloning into '/Users/junbozheng/san/externals/sanitizers-cmake'...
    remote: Enumerating objects: 214, done.
    remote: Total 214 (delta 0), reused 0 (delta 0), pack-reused 214
    Receiving objects: 100% (214/214), 47.66 KiB | 208.00 KiB/s, done.
    Resolving deltas: 100% (137/137), done.
    git submodule add [email protected]:arsenm/sanitizers-cmake.git   0.26s user 0.32s system 10% cpu 5.320 total
    ➜  /Users/junbozheng/san git:(master) ✗ ..
    

    Signed-off-by: Junbo Zheng [email protected]

    opened by Junbo-Zheng 0
  • Update cmake api calls for Ubuntu Focal proper operation.

    Update cmake api calls for Ubuntu Focal proper operation.

    The first commit introduces the changes required for proper works on CMake 3.11 distributed via apt in Ubuntu Focal. The second commit introduces the Sanitizers_FOUND variable mandatory on CMake modules. This variable can be used to include sanitizer function calls only if the Sanitizer module is present as:

      if(Sanitizers_FOUND)
        add_sanitize_thread(<target name>)
      endif()
    
    opened by MiguelBarro 0
  • Fix unclear error while accidentally sanitizing interface library

    Fix unclear error while accidentally sanitizing interface library

    Interface libraries added since CMake 3.0 version have INTERFACE_SOURCES property instead of SOURCES so it leads to error which is unclear and prevents project from compiling. Warning would be enough it this case.

    opened by 9fcc 0
  • Fix language detection with file names containing more than one dot

    Fix language detection with file names containing more than one dot

    Some files can have multiple dots in their names but CMake always returns the longest extensions including all dots. For example generated files can have .gen.c longest extension.

    opened by 9fcc 0
  • Fix a couple of spelling typos

    Fix a couple of spelling typos

    While reading the code of the macros I encountered some typo in the name of one macro and some in comments.

    No functionnal change. Thanks for this set of macros they are very helpful.

    opened by TheErk 0
  • Show fewer warnings for targets.

    Show fewer warnings for targets.

    This is a fix for #9.

    Instead of printing the same message over and over again, if a target can't use a specific sanitizer, the message will be printed only once for the first affected target now.

    opened by alehaa 0
  • Print warnings only once

    Print warnings only once

    If a Sanitizer is unavailable for a specific compiler, this warning should only be printed once instead of for every target. An internal cache variable could solve this issue.

    opened by alehaa 0
  • Restructuring and new features

    Restructuring and new features

    I rewrote most of the code, due I had multiple issues with the modules.

    The major problem was, that the old modules didn't cover targets which are build by two compilers which will crash in an unresolved symbols error by the linker. So I wrote helper function to detect the used compilers per target and add specific flags per target or abort sanitizing a target, if the compilers are not compatible (e.g. clang and gcc).

    The second problem was, that I liked to use AddressSanitizer for a preloaded library which resulted in an abort by AddressSanitizer, because AddressSanitizer want's to be the first library to be loaded. So I've added a wrapper script to preload the used AddressSanitizer library first. This script should be compatible if you check your build with different compilers / linkage systems, e.g. gcc has a shared library for AddressSanitizer, clang has not, ...

    Last I've added a new README file for documentation.

    opened by alehaa 0
  • Missing warnings on subsequent CMake runs

    Missing warnings on subsequent CMake runs

    When building with GCC and enabling SANITIZE_MEMORY there are only warnings on missing compiler support on the very first run of CMake. There's no warning nor error on missing compiler support once CMake cache is in place. This is bad, because it leads to the false impression everything is fine and the sanitizer is in place. This might lead to thinking code has no flaws.

    You can simply reproduce this by building the example from https://github.com/google/sanitizers/wiki/MemorySanitizer with GCC and enable SANITIZE_MEMORY, and run cmake again on the same build folder. Everythings builds fine, no warning at buildtime nor runtime, although the code is clearly buggy and MemorySanitizer with Clang finds it.

    The documentation in README.md states:

    If your compiler has no sanitizing capabilities (I asume intel compiler doesn't) you'll get a warning but CMake will continue processing and sanitizing will simply just be ignored.

    However this is only the case on the first CMake run, there is no warning on subsequent runs when cache is populated. But there should be!

    opened by LeSpocky 5
  • Build fails

    Build fails

    In file included from /usr/ports/devel/cli11/work/CLI11-1.8.0/extern/googletest/googletest/include/gtest/gtest-param-test.h:180:
    /usr/ports/devel/cli11/work/CLI11-1.8.0/extern/googletest/googletest/include/gtest/internal/gtest-param-util.h:382:3: error: static_assert failed due to requirement 'sizeof(int) == 0' "Empty arguments are not allowed."
      static_assert(sizeof(T) == 0, "Empty arguments are not allowed.");
      ^             ~~~~~~~~~~~~~~
    /usr/ports/devel/cli11/work/CLI11-1.8.0/tests/TrueFalseTest.cpp:16:1: note: in instantiation of function template specialization 'testing::internal::TestNotEmpty<int>' requested here
    INSTANTIATE_TEST_CASE_P(TrueBoolOptions, TApp_TBO, ::testing::Values("true", "on", "True", "ON"), );
    ^
    /usr/ports/devel/cli11/work/CLI11-1.8.0/extern/googletest/googletest/include/gtest/gtest-param-test.h:498:3: note: expanded from macro 'INSTANTIATE_TEST_CASE_P'
      INSTANTIATE_TEST_SUITE_P
      ^
    /usr/ports/devel/cli11/work/CLI11-1.8.0/extern/googletest/googletest/include/gtest/gtest-param-test.h:468:28: note: expanded from macro 'INSTANTIATE_TEST_SUITE_P'
          ::testing::internal::TestNotEmpty(GTEST_EXPAND_(GTEST_GET_SECOND_(      \
                               ^
    2 warnings and 5 errors generated.
    
    opened by yurivict 0
  • Define ASan_SHARED_LIB that may be used without ASan_WRAPPER

    Define ASan_SHARED_LIB that may be used without ASan_WRAPPER

    In some cases I'd like to be able to use ASan without the ASan wrapper, in this case I need to have access to ASan_SHARED_LIB in order to properly LD_PRELOAD it as the asan-wrapper does.

    opened by TheErk 0
  • asan lib should be transitive

    asan lib should be transitive

    Build fails at link time if a static library is compiled with address sanitizer, but the executable using the library is not. Example:

    add_library(foo STATIC foo.cpp)
    add_sanitizers(foo)
    
    add_executable(main main.cpp)
    target_link_libraries(main foo)
    

    Link-time error:

    [ 75%] Linking CXX static library libfoo.a
    [ 75%] Built target foo
    [ 87%] Linking CXX executable main
    libfoo.a(foo.cpp.o): In function `foo()':
    sanitizers-cmake/tests/foo.cpp:2: undefined reference to `__asan_option_detect_stack_use_after_return'
    

    The link succeed using SHARED library type, but fails at runtime. The asan wrapper script is mandatory in that situation.

    ./tests/main 
    ==72769==ASan runtime does not come first in initial library list; you should either link runtime to your application or manually preload it with LD_PRELOAD.
    
    ../cmake/asan-wrapper ./tests/main
    ==72780==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffef9eff968 at pc 0x7fdd7696791c bp 0x7ffef9eff910 sp 0x7ffef9eff900
    

    However, when the final executable is itself sanitizer-enabled, then this situation does not occur and everything works just fine, both with static and shared library.

    Maybe one solution would be to import asan library and add it to the INTERFACE_LINK_LIBRARIES of targets using a sanitizer.

    opened by giraldeau 0
  • Targets using only target_sources don't get sanitizer flags

    Targets using only target_sources don't get sanitizer flags

    With CMake 3.13, I've been writing a bunch of targets like this, where the SOURCES property of a target can be added by subdirectories and its evaluation is deferred to "generation time."

    add_executable(myexecutable)
    target_sources(myexecutable PRIVATE main.cc)
    

    Unfortunately, this makes these targets incompatible with add_sanitizers(...) because the scripts are not able to find any source files in the target:

    CMake Warning at third_party/sanitizers-cmake/cmake/FindSanitizers.cmake:82 (message):
      Sanitizers for target myexecutable may not be usable, because it uses no or an
      unknown compiler.  This is a false warning for targets using only object
      lib(s) as input.
    Call Stack (most recent call first):
      CMakeLists.txt:35 (add_sanitizers)
    

    I'm pretty new to "modern" CMake and I don't know how to get around this. Maybe the compiler flags added by sanitizer_add_flags need to be generator expressions that get evaluated at generation time?

    opened by GHF 0
Owner
Matt Arsenault
Matt Arsenault
CMake and other scripts to help build process of FlyEM software

The BuildEM System The buildem repo is a modular CMake-based system that leverages CMake's ExternalProject to simplify and automate a complex build pr

null 27 Jun 9, 2022
CMake Community Modules

CMake Community Modules The CMake Community Modules are CMake modules created and maintained by the community. This repository's main product is the C

Edgar 2 Dec 14, 2022
Extra CMake Modules for YARP and friends

YCM Extra CMake Modules for YARP and friends Documentation Online documentation is available

Robotology 43 Dec 27, 2022
Extra modules and scripts for CMake.

Extra CMake Modules Introduction The Extra CMake Modules package, or ECM, adds to the modules provided by CMake, including ones used by find_package()

KDE GitHub Mirror 104 Nov 16, 2022
CMake modules for some scientific libraries

A collection of CMake modules, which can mostly be used independently. The utilities for writing robust Find* modules might be useful until CMake take

Jed Brown 83 Dec 4, 2022
Common CMake modules

CMake Modules This repository contains common CMake modules and a collection of find scripts to locate non-CMake dependencies. The recommended way to

Eyescale Software GmbH 144 Dec 27, 2022
Additional CMake functionality. Most of the modules are from Ryan Pavlik

Additional CMake functionality. Most of the modules are from Ryan Pavlik

Lars Bilke 452 Dec 28, 2022
Ryan's CMake Modules Collection

This is a collection of CMake modules that I've produced during the course of a variety of software development.

Ryan A. Pavlik 891 Jan 9, 2023
A set of cmake modules to assist in building code

CMake 3 Tools Warning: These tools are being replaced by the Modern CMake. Some of the tools are still being maintained for now, but new projects shou

null 201 Dec 21, 2022
📦 CMake's missing package manager. A small CMake script for setup-free, cross-platform, reproducible dependency management.

Setup-free CMake dependency management CPM.cmake is a CMake script that adds dependency management capabilities to CMake. It's built as a thin wrapper

CPM.cmake 1.6k Jan 9, 2023
CMake scripts for painless usage of SuiteSparse+METIS from Visual Studio and the rest of Windows/Linux/OSX IDEs supported by CMake

CMake scripts for painless usage of Tim Davis' SuiteSparse (CHOLMOD,UMFPACK,AMD,LDL,SPQR,...) and METIS from Visual Studio and the rest of Windows/Lin

Jose Luis Blanco-Claraco 395 Dec 24, 2022
cmake-font-lock - Advanced, type aware, highlight support for CMake

cmake-font-lock - Advanced, type aware, highlight support for CMake

Anders Lindgren 39 Oct 2, 2022
cmake-avr - a cmake toolchain for AVR projects

cmake-avr - a cmake toolchain for AVR projects Testing the example provided The toolchain was created and tested within the following environment: Lin

Matthias Kleemann 163 Dec 5, 2022
Make CMake less painful when trying to write Modern Flexible CMake

Izzy's eXtension Modules IXM is a CMake library for writing Modern flexible CMake. This means: Reducing the amount of CMake written Selecting reasonab

IXM 107 Sep 1, 2022
CMake module to enable code coverage easily and generate coverage reports with CMake targets.

CMake-codecov CMake module to enable code coverage easily and generate coverage reports with CMake targets. Include into your project To use Findcodec

HPC 82 Nov 30, 2022
unmaintained - CMake module to activate certain C++ standard, feature checks and appropriate automated workarounds - basically an improved version of cmake-compile-features

Compatibility This library provides an advanced target_compile_features() and write_compiler_detection_header(). The problem with those is that they a

Jonathan Müller 74 Dec 26, 2022
[CMake] [BSD-2] CMake module to find ICU

FindICU.cmake A CMake module to find International Components for Unicode (ICU) Library Note that CMake, since its version 3.7.0, includes a FindICU m

julp 29 Nov 2, 2022
CMake integration for include-what-you-use

Include-What-You-Use CMake Targets CMake macro to add per-source level checks on individual targets for include-what-you-use violations Status Travis

ポリ平方 POLYSQUARE 8 Apr 10, 2021
A fast build system that encourages the creation of small, reusable modules over a variety of platforms and languages.

Buck Buck is a build tool. To see what Buck can do for you, check out the documentation at http://buck.build/. Installation Since Buck is used to buil

Facebook 8.5k Jan 7, 2023