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()