Skip to content

Commit

Permalink
Fuzztest clean-ups (#2529)
Browse files Browse the repository at this point in the history
  • Loading branch information
vrabaud authored Jan 3, 2025
1 parent 021a110 commit d3388d9
Show file tree
Hide file tree
Showing 8 changed files with 67 additions and 48 deletions.
7 changes: 1 addition & 6 deletions .github/workflows/ci-fuzztest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,6 @@ jobs:
codec-dav1d: "LOCAL"
libxml2: "LOCAL"
libyuv: ${{ matrix.libyuv }}
- name: Build fuzztest
if: steps.setup.outputs.ext-cache-hit != 'true'
working-directory: ./ext
run: bash -e fuzztest.cmd

- name: Prepare libavif (cmake)
run: >
Expand All @@ -52,8 +48,7 @@ jobs:
-DAVIF_ENABLE_EXPERIMENTAL_YCGCO_R=ON
-DAVIF_ENABLE_EXPERIMENTAL_MINI=ON
-DAVIF_ENABLE_EXPERIMENTAL_SAMPLE_TRANSFORM=ON
-DAVIF_ENABLE_FUZZTEST=ON
-DAVIF_LOCAL_FUZZTEST=ON
-DAVIF_FUZZTEST=LOCAL
-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
-DAVIF_ENABLE_WERROR=ON
- name: Build libavif (ninja)
Expand Down
13 changes: 4 additions & 9 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,8 @@ option(
"Build tests that compare encoding outputs to golden files. Needs AVIF_BUILD_APPS=ON and AVIF_BUILD_TESTS=ON, and depends on MP4box which can be built with ext/mp4box.sh"
OFF
)
option(AVIF_ENABLE_FUZZTEST "Build avif fuzztest targets. Requires Google FuzzTest. Has no effect unless AVIF_BUILD_TESTS is ON."
OFF
)
option(
AVIF_LOCAL_FUZZTEST
"Build the Google FuzzTest framework by providing your own copy of the repo in ext/fuzztest (see Local Builds in README). CMake must be at least 3.25."
OFF
set_local_or_system_option(
"AVIF_FUZZTEST" OFF "Build the Google FuzzTest framework. Only OFF and LOCAL are supported. CMake must be at least 3.25."
)

# Whether the libavif library uses c++ indirectly (e.g. through linking to libyuv).
Expand Down Expand Up @@ -556,7 +551,7 @@ if(NOT AVIF_CODEC_AOM_ENABLED
message(WARNING "libavif: No decoding library is enabled.")
endif()

if(AVIF_LIB_USE_CXX OR AVIF_BUILD_APPS OR (AVIF_BUILD_TESTS AND (AVIF_ENABLE_FUZZTEST OR AVIF_GTEST)))
if(AVIF_LIB_USE_CXX OR AVIF_BUILD_APPS OR (AVIF_BUILD_TESTS AND (AVIF_FUZZTEST OR AVIF_GTEST)))
enable_language(CXX)
if(AVIF_ENABLE_NODISCARD)
# [[nodiscard]] requires C++17.
Expand Down Expand Up @@ -633,7 +628,7 @@ if(NOT SKIP_INSTALL_ALL)
include(GNUInstallDirs)
endif()

if(AVIF_BUILD_APPS OR (AVIF_BUILD_TESTS AND (AVIF_ENABLE_FUZZTEST OR AVIF_GTEST)))
if(AVIF_BUILD_APPS OR (AVIF_BUILD_TESTS AND (AVIF_FUZZTEST OR AVIF_GTEST)))
if(AVIF_ZLIBPNG STREQUAL "OFF")
message(FATAL_ERROR "libavif: AVIF_ZLIBPNG cannot be OFF when AVIF_BUILD_APPS or AVIF_BUILD_TESTS is ON")
elseif(AVIF_ZLIBPNG STREQUAL "SYSTEM")
Expand Down
32 changes: 32 additions & 0 deletions cmake/Modules/LocalFuzztest.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
set(AVIF_FUZZTEST_TAG "078ea0871cc96d3a69bad406577f176a4fa14ae9")

set(FUZZTEST_SOURCE_DIR "${AVIF_SOURCE_DIR}/ext/fuzztest")

if(EXISTS "${FUZZTEST_SOURCE_DIR}")
message(STATUS "libavif(AVIF_FUZZTEST=LOCAL): folder found at ${FUZZTEST_SOURCE_DIR}")
set(FUZZTEST_BINARY_DIR "${FUZZTEST_SOURCE_DIR}/build.libavif")
else()
message(STATUS "libavif(AVIF_FUZZTEST=LOCAL): compiled library not found at ${LIB_FILENAME}; using FetchContent")

message(CHECK_START "libavif(AVIF_FUZZTEST=LOCAL): configuring fuzztest")

set(FUZZTEST_SOURCE_DIR "${FETCHCONTENT_BASE_DIR}/fuzztest-src")
set(FUZZTEST_BINARY_DIR "${FETCHCONTENT_BASE_DIR}/fuzztest-build")
FetchContent_Declare(
fuzztest
GIT_REPOSITORY "https://github.com/google/fuzztest.git"
BINARY_DIR "${FUZZTEST_BINARY_DIR}"
GIT_TAG "${AVIF_FUZZTEST_TAG}"
# Fixes for https://github.com/google/fuzztest/issues/1124
PATCH_COMMAND
sed -i.bak -e "s/-fsanitize=address//g" cmake/FuzzTestFlagSetup.cmake && sed -i.bak -e "s/-DADDRESS_SANITIZER//g"
cmake/FuzzTestFlagSetup.cmake &&
# Fixes for https://github.com/google/fuzztest/issues/1125
sed -i.bak -e "s/if (IsEnginePlaceholderInput(data))/if (data.size() == 0)/" fuzztest/internal/compatibility_mode.cc
&& sed -i.bak -e "s/set(GTEST_HAS_ABSL ON)/set(GTEST_HAS_ABSL OFF)/" cmake/BuildDependencies.cmake
)

message(CHECK_PASS "complete")
endif()

avif_fetchcontent_populate_cmake(fuzztest)
4 changes: 2 additions & 2 deletions ext/fuzztest.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ git checkout 078ea0871cc96d3a69bad406577f176a4fa14ae9
sed -i 's/-fsanitize=address//g' ./cmake/FuzzTestFlagSetup.cmake
sed -i 's/-DADDRESS_SANITIZER//g' ./cmake/FuzzTestFlagSetup.cmake
: # Fixes for https://github.com/google/fuzztest/issues/1125
sed -i 's/if (IsEnginePlaceholderInput(data)) return;/if (data.size() == 0) return;/g' ./fuzztest/internal/compatibility_mode.cc
sed -i 's/set(GTEST_HAS_ABSL ON)/set(GTEST_HAS_ABSL OFF)/g' ./cmake/BuildDependencies.cmake
sed -i 's/if (IsEnginePlaceholderInput(data))/if (data.size() == 0)/' ./fuzztest/internal/compatibility_mode.cc
sed -i 's/set(GTEST_HAS_ABSL ON)/set(GTEST_HAS_ABSL OFF)/' ./cmake/BuildDependencies.cmake

: # fuzztest is built by the main CMake project through add_subdirectory as recommended at:
: # https://github.com/google/fuzztest/blob/main/doc/quickstart-cmake.md
51 changes: 24 additions & 27 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ foreach(AVIFYUV_MODE limited rgb) # Modes drift and premultiply take more than 2
add_test(NAME avifyuv_${AVIFYUV_MODE} COMMAND avifyuv -m ${AVIFYUV_MODE})
endforeach()

if(AVIF_ENABLE_FUZZTEST OR AVIF_GTEST OR AVIF_BUILD_APPS)
if(AVIF_FUZZTEST OR AVIF_GTEST OR AVIF_BUILD_APPS)
add_library(aviftest_helpers OBJECT gtest/aviftest_helpers.cc)
target_link_libraries(aviftest_helpers PUBLIC avif_apps avif)
target_link_libraries(aviftest_helpers PRIVATE avif_enable_warnings)
Expand Down Expand Up @@ -170,42 +170,39 @@ endif()
################################################################################
# Experimental FuzzTest support (Linux only)

if(AVIF_ENABLE_FUZZTEST)
if(AVIF_FUZZTEST)
# Adds a fuzztest from file TEST_NAME.cc located in the gtest folder. Extra arguments
# are considered as extra source files.
macro(add_avif_fuzztest TEST_NAME)
add_executable(${TEST_NAME} gtest/${TEST_NAME}.cc ${ARGN})
# FuzzTest bundles GoogleTest so no need to link to gtest librairies.
target_link_libraries(${TEST_NAME} PRIVATE avif_fuzztest_helpers aviftest_helpers_internal avif_enable_warnings)
# avif_enable_warnings is not added because it triggers to many warnings in fuzztest.
target_link_libraries(${TEST_NAME} PRIVATE avif_fuzztest_helpers aviftest_helpers_internal)
link_fuzztest(${TEST_NAME})
add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME} --stack_limit_kb=512)
set_property(TEST ${TEST_NAME} PROPERTY ENVIRONMENT "TEST_DATA_DIRS=${CMAKE_CURRENT_SOURCE_DIR}/data/")
endmacro()

if(AVIF_LOCAL_FUZZTEST)
# Run ext/fuzztest.cmd first.
# Recommended top-level CMake options:
# -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DAVIF_CODEC_DAV1D=ON -DAVIF_ENABLE_WERROR=OFF
# Reproducing a failure can be done by setting the environment variable
# FUZZTEST_REPLAY=/path/to/repro_file.test
# and running one of the targets below.
# See https://github.com/google/fuzztest/blob/main/doc/quickstart-cmake.md
# Note: There are compiler warnings in the FuzzTest headers. Add the
# ext/fuzztest subdirectory with the SYSTEM directory property set to
# true so that warnings in its headers are suppressed.
if(CMAKE_VERSION VERSION_LESS 3.25.0)
message(FATAL_ERROR "CMake must be at least 3.25 to pass the SYSTEM argument to add_subdirectory(), bailing out")
endif()
# Add the fuzztest project. Note this may add some tests which may not be built because of EXCLUDE_FROM_ALL and will
# therefore fail. They can be ignored by adding them to CTestCustom.cmake
# See https://gitlab.kitware.com/cmake/cmake/-/issues/20212
add_subdirectory(${AVIF_SOURCE_DIR}/ext/fuzztest ${AVIF_SOURCE_DIR}/ext/fuzztest/build.libavif EXCLUDE_FROM_ALL SYSTEM)
else()
message(
FATAL_ERROR
"fuzztest: Installed FuzzTest is not supported, please set AVIF_LOCAL_FUZZTEST=ON or AVIF_ENABLE_FUZZTEST=OFF"
)
# Recommended top-level CMake options:
# -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DAVIF_CODEC_DAV1D=ON -DAVIF_ENABLE_WERROR=OFF
# Reproducing a failure can be done by setting the environment variable
# FUZZTEST_REPLAY=/path/to/repro_file.test
# and running one of the targets below.
# See https://github.com/google/fuzztest/blob/main/doc/quickstart-cmake.md
# Note: There are compiler warnings in the FuzzTest headers. Add the
# ext/fuzztest subdirectory with the SYSTEM directory property set to
# true so that warnings in its headers are suppressed.
if(CMAKE_VERSION VERSION_LESS 3.25.0)
message(FATAL_ERROR "CMake must be at least 3.25 to pass the SYSTEM argument to add_subdirectory(), bailing out")
endif()
if(AVIF_FUZZTEST STREQUAL "SYSTEM")
message(FATAL_ERROR "SYSTEM is not supported for AVIF_FUZZTEST")
endif()
# Add the fuzztest project. Note this may add some tests which may not be built because of EXCLUDE_FROM_ALL and will
# therefore fail. They can be ignored by adding them to CTestCustom.cmake
# See https://gitlab.kitware.com/cmake/cmake/-/issues/20212
include(LocalFuzztest)

fuzztest_setup_fuzzing_flags()

# Create a library with avif_fuzztest_helpers.cc to compile it only once.
Expand All @@ -222,7 +219,7 @@ if(AVIF_ENABLE_FUZZTEST)
add_avif_fuzztest(avif_fuzztest_read_image)
add_avif_fuzztest(avif_fuzztest_yuvrgb)
else()
message(STATUS "FuzzTest targets are disabled because AVIF_ENABLE_FUZZTEST is OFF.")
message(STATUS "FuzzTest targets are disabled because AVIF_FUZZTEST is OFF.")
endif()

################################################################################
Expand Down
2 changes: 1 addition & 1 deletion tests/CTestCustom.cmake
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
set(CTEST_CUSTOM_TESTS_IGNORE
# Ignore failing tests brought by `add_subdirectory(${AVIF_SOURCE_DIR}/ext/fuzztest)` when AVIF_ENABLE_FUZZTEST is ON
# Ignore failing tests brought by `add_subdirectory(${AVIF_SOURCE_DIR}/ext/fuzztest)` when AVIF_FUZZTEST is not OFF
antlr4_tests_NOT_BUILT
)
2 changes: 1 addition & 1 deletion tests/oss-fuzz/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ This document provides links and knowledge about fuzzing libavif on oss-fuzz.
You need to build with the following CMake flags:

```sh
-DAVIF_CODEC_AOM=LOCAL -DAVIF_CODEC_AOM_DECODE=ON -DAVIF_CODEC_AOM_ENCODE=ON -DAVIF_CODEC_DAV1D=LOCAL -DAVIF_LIBYUV=LOCAL -DAVIF_LIBSHARPYUV=LOCAL -DAVIF_BUILD_TESTS=ON -DAVIF_ENABLE_GTEST=ON -DAVIF_GTEST=LOCAL -DAVIF_LOCAL_FUZZTEST=ON -DAVIF_ENABLE_FUZZTEST=ON -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DAVIF_ENABLE_WERROR=OFF
-DAVIF_CODEC_AOM=LOCAL -DAVIF_CODEC_AOM_DECODE=ON -DAVIF_CODEC_AOM_ENCODE=ON -DAVIF_CODEC_DAV1D=LOCAL -DAVIF_LIBYUV=LOCAL -DAVIF_LIBSHARPYUV=LOCAL -DAVIF_BUILD_TESTS=ON -DAVIF_ENABLE_GTEST=ON -DAVIF_GTEST=LOCAL -DAVIF_FUZZTEST=LOCAL -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DAVIF_ENABLE_WERROR=OFF
```

You can then run your tests as normal:
Expand Down
4 changes: 2 additions & 2 deletions tests/oss-fuzz/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,11 @@ cd build
EXTRA_CMAKE_FLAGS=""
if [[ "$FUZZING_ENGINE" == "libfuzzer" ]]; then
CXXFLAGS="${CXXFLAGS} -DFUZZTEST_COMPATIBILITY_MODE"
EXTRA_CMAKE_FLAGS="${EXTRA_CMAKE_FLAGS} -DAVIF_ENABLE_FUZZTEST=ON -DFUZZTEST_COMPATIBILITY_MODE=libfuzzer"
EXTRA_CMAKE_FLAGS="${EXTRA_CMAKE_FLAGS} -DFUZZTEST_COMPATIBILITY_MODE=libfuzzer"
fi
cmake .. -G Ninja -DBUILD_SHARED_LIBS=OFF -DAVIF_CODEC_AOM=LOCAL -DAVIF_CODEC_DAV1D=LOCAL \
-DAVIF_CODEC_AOM_DECODE=ON -DAVIF_CODEC_AOM_ENCODE=ON \
-DAVIF_LOCAL_FUZZTEST=ON \
-DAVIF_FUZZTEST=LOCAL \
-DAVIF_JPEG=LOCAL -DAVIF_LIBSHARPYUV=LOCAL \
-DAVIF_LIBYUV=LOCAL -DAVIF_ZLIBPNG=LOCAL \
-DAVIF_BUILD_TESTS=ON -DAVIF_GTEST=OFF -DAVIF_ENABLE_WERROR=ON \
Expand Down

0 comments on commit d3388d9

Please sign in to comment.