diff --git a/CMakeLists.txt b/CMakeLists.txt index e200955c955..e63a876925c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -263,6 +263,41 @@ target_link_libraries(core_interface INTERFACE Threads::Threads ) +add_library(sanitize_interface INTERFACE) +target_link_libraries(core_interface INTERFACE sanitize_interface) +if(SANITIZERS) + # First check if the compiler accepts flags. If an incompatible pair like + # -fsanitize=address,thread is used here, this check will fail. This will also + # fail if a bad argument is passed, e.g. -fsanitize=undfeined + try_append_cxx_flags("-fsanitize=${SANITIZERS}" TARGET sanitize_interface + RESULT_VAR cxx_supports_sanitizers + SKIP_LINK + ) + if(NOT cxx_supports_sanitizers) + message(FATAL_ERROR "Compiler did not accept requested flags.") + endif() + + # Some compilers (e.g. GCC) require additional libraries like libasan, + # libtsan, libubsan, etc. Make sure linking still works with the sanitize + # flag. This is a separate check so we can give a better error message when + # the sanitize flags are supported by the compiler but the actual sanitizer + # libs are missing. + try_append_linker_flag("-fsanitize=${SANITIZERS}" VAR SANITIZER_LDFLAGS + SOURCE " + #include + #include + extern \"C\" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { return 0; } + __attribute__((weak)) // allow for libFuzzer linking + int main() { return 0; } + " + RESULT_VAR linker_supports_sanitizers + ) + if(NOT linker_supports_sanitizers) + message(FATAL_ERROR "Linker did not accept requested flags, you are missing required libraries.") + endif() +endif() +target_link_options(sanitize_interface INTERFACE ${SANITIZER_LDFLAGS}) + include(AddBoostIfNeeded) add_boost_if_needed() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 432eb572ba7..40ade71d96b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -44,6 +44,12 @@ set(SECP256K1_BUILD_BENCHMARK OFF CACHE BOOL "" FORCE) set(SECP256K1_BUILD_TESTS ${BUILD_TESTS} CACHE BOOL "" FORCE) set(SECP256K1_BUILD_EXHAUSTIVE_TESTS ${BUILD_TESTS} CACHE BOOL "" FORCE) set(SECP256K1_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) +include(GetTargetInterface) +# -fsanitize and related flags apply to both C++ and C, +# so we can pass them down to libsecp256k1 as CFLAGS. +get_target_interface(core_sanitizer_cxx_flags "" sanitize_interface COMPILE_OPTIONS) +set(SECP256K1_LATE_CFLAGS ${core_sanitizer_cxx_flags} CACHE STRING "" FORCE) +unset(core_sanitizer_cxx_flags) # We want to build libsecp256k1 with the most tested RelWithDebInfo configuration. enable_language(C) foreach(config IN LISTS CMAKE_BUILD_TYPE CMAKE_CONFIGURATION_TYPES)