# libFuzzer targets for CORE parsers. Lane CORE owns tools/fuzz.
#
# Self-guarding: the top-level CMakeLists.txt add_subdirectory()s every tools/* that has a
# CMakeLists, unconditionally, so this file must opt out on its own when fuzzing isn't
# wanted or the compiler can't do libFuzzer.
#
# Each target compiles the parser sources directly (not the whole libveloxcore) so the
# code under test is fully fuzzer-instrumented without a second build of the library.

if(NOT VELOX_BUILD_FUZZ)
    return()
endif()
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang")
    message(STATUS "tools/fuzz: libFuzzer needs Clang (have ${CMAKE_CXX_COMPILER_ID}); "
                   "skipping fuzz targets.")
    return()
endif()

set(_core ${CMAKE_SOURCE_DIR}/core)
set(_fuzz_flags -g -O1 -fsanitize=fuzzer,address,undefined -fno-omit-frame-pointer)

# corpus_dir is the seed set (checked in, small, hand-named). It is passed read-only:
# the CTest smoke run uses -runs so libFuzzer exits, and a real campaign is
# `bin/<name> corpus/<x>/` by hand.
function(vdm_add_fuzzer name corpus_dir)
    add_executable(${name} ${ARGN})
    target_include_directories(${name} PRIVATE ${_core}/include ${_core}/src)
    target_compile_features(${name} PRIVATE cxx_std_23)
    target_compile_options(${name} PRIVATE ${_fuzz_flags})
    target_link_options(${name} PRIVATE ${_fuzz_flags})

    if(VELOX_BUILD_TESTS)
        # Regression tripwire only: replay the checked-in seeds once (-runs=0, no
        # mutation, no corpus writes) so a parser change that breaks a known-good or
        # known-hostile input fails CI in a fraction of a second. The 1M-exec bar
        # (AGENT-CORE M1 DoD) is a separate campaign job: `bin/<name> corpus/<x>/`.
        add_test(NAME ${name}_smoke
                 COMMAND ${name} -runs=0 ${CMAKE_CURRENT_SOURCE_DIR}/${corpus_dir})
        set_tests_properties(${name}_smoke PROPERTIES LABELS "fuzz" TIMEOUT 60)
    endif()
endfunction()

vdm_add_fuzzer(fuzz_content_disposition corpus/content_disposition
    content_disposition_fuzz.cpp
    ${_core}/src/net/content_disposition.cpp
    ${_core}/src/net/text_codec.cpp)

vdm_add_fuzzer(fuzz_url corpus/url
    url_fuzz.cpp
    ${_core}/src/net/url.cpp
    ${_core}/src/net/text_codec.cpp)

vdm_add_fuzzer(fuzz_veloxpart corpus/veloxpart
    veloxpart_fuzz.cpp
    ${_core}/src/meta/veloxpart.cpp
    ${_core}/src/util/error.cpp)
