• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# detect-sanitizer.cmake -- Detect supported compiler sanitizer flags
2# Licensed under the Zlib license, see LICENSE.md for details
3
4macro(check_sanitizer_support known_checks supported_checks)
5    set(available_checks "")
6
7    # Build list of supported sanitizer flags by incrementally trying compilation with
8    # known sanitizer checks
9
10    foreach(check ${known_checks})
11        if(available_checks STREQUAL "")
12            set(compile_checks "${check}")
13        else()
14            set(compile_checks "${available_checks},${check}")
15        endif()
16
17        set(CMAKE_REQUIRED_FLAGS "-fsanitize=${compile_checks}")
18
19        check_c_source_compiles("int main() { return 0; }" HAS_SANITIZER_${check}
20            FAIL_REGEX "not supported|unrecognized command|unknown option")
21
22        set(CMAKE_REQUIRED_FLAGS)
23
24        if(HAS_SANITIZER_${check})
25            set(available_checks ${compile_checks})
26        endif()
27    endforeach()
28
29    set(${supported_checks} ${available_checks})
30endmacro()
31
32macro(add_memory_sanitizer_check)
33    check_sanitizer_support("memory" supported_checks)
34    if(NOT ${supported_checks} STREQUAL "")
35        message(STATUS "Memory sanitizer is enabled")
36        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=${supported_checks}")
37    else()
38        message(STATUS "Memory sanitizer is not supported")
39    endif()
40endmacro()
41
42macro(add_sanitizer_checks)
43    set(known_checks
44        address
45        array-bounds
46        bool
47        bounds
48        builtin
49        enum
50        float-divide-by-zero
51        function
52        integer-divide-by-zero
53        null
54        nonnull-attribute
55        object-size
56        pointer-compare             # Depends on 'address'
57        pointer-overflow
58        pointer-subtract            # Depends on 'address'
59        return
60        returns-nonnull-attribute
61        shift
62        shift-base
63        shift-exponent
64        signed-integer-overflow
65        undefined
66        unsigned-integer-overflow
67        vla-bound
68        vptr
69        )
70
71    # Only check for leak sanitizer if not cross-compiling due to qemu crash
72    if(NOT CMAKE_CROSSCOMPILING_EMULATOR)
73        list(APPEND known_checks leak)
74    endif()
75    # Only check for alignment sanitizer flag if unaligned access is not supported
76    if(NOT UNALIGNED_OK)
77        list(APPEND known_checks alignment)
78    endif()
79
80    check_sanitizer_support("${known_checks}" supported_checks)
81
82    if(NOT ${supported_checks} STREQUAL "")
83        message(STATUS "Supported sanitizers checks are enabled: ${supported_checks}")
84        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=${supported_checks}")
85
86        # Group sanitizer flag -fsanitize=undefined will automatically add alignment, even if
87        # it is not in our sanitize flag list, so we need to explicitly disable alignment sanitizing.
88        if(UNALIGNED_OK)
89            set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-sanitize=alignment")
90        endif()
91    else()
92        message(STATUS "Sanitizer checks are not supported")
93    endif()
94endmacro()