• 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_address_sanitizer)
33    set(known_checks
34        address
35        pointer-compare
36        pointer-subtract
37        )
38
39    check_sanitizer_support("${known_checks}" supported_checks)
40    if(NOT ${supported_checks} STREQUAL "")
41        message(STATUS "Address sanitizer is enabled: ${supported_checks}")
42        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=${supported_checks}")
43    else()
44        message(STATUS "Address sanitizer is not supported")
45    endif()
46
47    if(CMAKE_CROSSCOMPILING_EMULATOR)
48        # Only check for leak sanitizer if not cross-compiling due to qemu crash
49        message(WARNING "Leak sanitizer is not supported when cross compiling")
50    else()
51        # Leak sanitizer requires address sanitizer
52        check_sanitizer_support("leak" supported_checks)
53        if(NOT ${supported_checks} STREQUAL "")
54            message(STATUS "Leak sanitizer is enabled: ${supported_checks}")
55            set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=${supported_checks}")
56        else()
57            message(STATUS "Leak sanitizer is not supported")
58        endif()
59    endif()
60endmacro()
61
62macro(add_memory_sanitizer)
63    check_sanitizer_support("memory" supported_checks)
64    if(NOT ${supported_checks} STREQUAL "")
65        message(STATUS "Memory sanitizer is enabled: ${supported_checks}")
66        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=${supported_checks}")
67    else()
68        message(STATUS "Memory sanitizer is not supported")
69    endif()
70endmacro()
71
72macro(add_undefined_sanitizer)
73    set(known_checks
74        array-bounds
75        bool
76        bounds
77        builtin
78        enum
79        float-cast-overflow
80        float-divide-by-zero
81        function
82        integer-divide-by-zero
83        local-bounds
84        null
85        nonnull-attribute
86        pointer-overflow
87        return
88        returns-nonnull-attribute
89        shift
90        shift-base
91        shift-exponent
92        signed-integer-overflow
93        undefined
94        unsigned-integer-overflow
95        unsigned-shift-base
96        vla-bound
97        vptr
98        )
99
100    # Only check for alignment sanitizer flag if unaligned access is not supported
101    if(NOT UNALIGNED_OK)
102        list(APPEND known_checks alignment)
103    endif()
104    # Object size sanitizer has no effect at -O0 and produces compiler warning if enabled
105    if(NOT CMAKE_C_FLAGS MATCHES "-O0")
106        list(APPEND known_checks object-size)
107    endif()
108
109    check_sanitizer_support("${known_checks}" supported_checks)
110
111    if(NOT ${supported_checks} STREQUAL "")
112        message(STATUS "Undefined behavior sanitizer is enabled: ${supported_checks}")
113        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=${supported_checks}")
114
115        # Group sanitizer flag -fsanitize=undefined will automatically add alignment, even if
116        # it is not in our sanitize flag list, so we need to explicitly disable alignment sanitizing.
117        if(UNALIGNED_OK)
118            set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-sanitize=alignment")
119        endif()
120    else()
121        message(STATUS "UNdefined behavior sanitizer is not supported")
122    endif()
123endmacro()