diff --git a/CMakeLists.txt b/CMakeLists.txt index bbcedcec2d6..c5ebd2f04d5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -346,13 +346,28 @@ target_link_libraries(core_interface INTERFACE Threads::Threads ) +# Define sanitize_interface with -fsanitize flags intended to apply to all +# libraries and executables. add_library(sanitize_interface INTERFACE) target_link_libraries(core_interface INTERFACE sanitize_interface) if(SANITIZERS) + # Transform list of sanitizers into -fsanitize flags, replacing "fuzzer" with + # "fuzzer-no-link" in sanitize_interface flags, and moving "fuzzer" to + # fuzzer_interface flags. If -DSANITIZERS=fuzzer is specified, the fuzz test + # binary should be built with -fsanitize=fuzzer (so it can use libFuzzer's + # main function), but libraries should be built with -fsanitize=fuzzer-no-link + # (so they can be linked into other executables that have their own main + # functions). + string(REGEX REPLACE "(^|,)fuzzer($|,)" "\\1fuzzer-no-link\\2" sanitize_opts "${SANITIZERS}") + set(fuzz_flag "") + if(NOT sanitize_opts STREQUAL SANITIZERS) + set(fuzz_flag "-fsanitize=fuzzer") + endif() + # 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 + try_append_cxx_flags("-fsanitize=${sanitize_opts}" TARGET sanitize_interface RESULT_VAR cxx_supports_sanitizers SKIP_LINK ) @@ -365,12 +380,11 @@ if(SANITIZERS) # 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 + try_append_linker_flag("-fsanitize=${sanitize_opts}" 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 @@ -382,8 +396,10 @@ if(SANITIZERS) endif() target_link_options(sanitize_interface INTERFACE ${SANITIZER_LDFLAGS}) +# Define fuzzer_interface with flags intended to apply to the fuzz test binary, +# and perform a test compilation to determine correct value of +# FUZZ_BINARY_LINKS_WITHOUT_MAIN_FUNCTION. if(BUILD_FUZZ_BINARY) - target_link_libraries(core_interface INTERFACE ${FUZZ_LIBS}) include(CheckSourceCompilesWithFlags) check_cxx_source_compiles_with_flags(" #include @@ -391,9 +407,12 @@ if(BUILD_FUZZ_BINARY) extern \"C\" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { return 0; } // No main() function. " FUZZ_BINARY_LINKS_WITHOUT_MAIN_FUNCTION - LDFLAGS ${SANITIZER_LDFLAGS} + LDFLAGS ${SANITIZER_LDFLAGS} ${fuzz_flag} LINK_LIBRARIES ${FUZZ_LIBS} ) + add_library(fuzzer_interface INTERFACE) + target_link_options(fuzzer_interface INTERFACE ${fuzz_flag}) + target_link_libraries(fuzzer_interface INTERFACE ${FUZZ_LIBS}) endif() include(AddBoostIfNeeded) diff --git a/src/test/fuzz/CMakeLists.txt b/src/test/fuzz/CMakeLists.txt index 846afeeb474..64fbe69dc00 100644 --- a/src/test/fuzz/CMakeLists.txt +++ b/src/test/fuzz/CMakeLists.txt @@ -138,6 +138,7 @@ add_executable(fuzz ) target_link_libraries(fuzz core_interface + fuzzer_interface test_fuzz bitcoin_cli bitcoin_common