Unverified Commit 64138b70 by Patrick Steinhardt Committed by GitHub

Merge pull request #4728 from pks-t/pks/fuzzers

Fuzzers
parents 0cf75467 835d6043
...@@ -31,3 +31,5 @@ msvc/Release/ ...@@ -31,3 +31,5 @@ msvc/Release/
.*.swp .*.swp
tags tags
mkmf.log mkmf.log
*.profdata
*.profraw
...@@ -38,33 +38,36 @@ INCLUDE(EnableWarnings) ...@@ -38,33 +38,36 @@ INCLUDE(EnableWarnings)
# Build options # Build options
# #
OPTION( SONAME "Set the (SO)VERSION of the target" ON ) OPTION(SONAME "Set the (SO)VERSION of the target" ON)
OPTION( BUILD_SHARED_LIBS "Build Shared Library (OFF for Static)" ON ) OPTION(BUILD_SHARED_LIBS "Build Shared Library (OFF for Static)" ON)
OPTION( THREADSAFE "Build libgit2 as threadsafe" ON ) OPTION(THREADSAFE "Build libgit2 as threadsafe" ON)
OPTION( BUILD_CLAR "Build Tests using the Clar suite" ON ) OPTION(BUILD_CLAR "Build Tests using the Clar suite" ON)
OPTION( BUILD_EXAMPLES "Build library usage example apps" OFF ) OPTION(BUILD_EXAMPLES "Build library usage example apps" OFF)
OPTION( TAGS "Generate tags" OFF ) OPTION(BUILD_FUZZERS "Build the fuzz targets" OFF)
OPTION( PROFILE "Generate profiling information" OFF ) OPTION(TAGS "Generate tags" OFF)
OPTION( ENABLE_TRACE "Enables tracing support" OFF ) OPTION(PROFILE "Generate profiling information" OFF)
OPTION( LIBGIT2_FILENAME "Name of the produced binary" OFF ) OPTION(ENABLE_TRACE "Enables tracing support" OFF)
OPTION(LIBGIT2_FILENAME "Name of the produced binary" OFF)
SET(SHA1_BACKEND "CollisionDetection" CACHE STRING "Backend to use for SHA1. One of Generic, OpenSSL, Win32, CommonCrypto, mbedTLS, CollisionDetection. ")
OPTION( USE_SSH "Link with libssh to enable SSH support" ON ) SET(SHA1_BACKEND "CollisionDetection" CACHE STRING
OPTION( USE_HTTPS "Enable HTTPS support. Can be set to a specific backend" ON ) "Backend to use for SHA1. One of Generic, OpenSSL, Win32, CommonCrypto, mbedTLS, CollisionDetection.")
OPTION( USE_GSSAPI "Link with libgssapi for SPNEGO auth" OFF ) OPTION(USE_SSH "Link with libssh to enable SSH support" ON)
OPTION( VALGRIND "Configure build for valgrind" OFF ) OPTION(USE_HTTPS "Enable HTTPS support. Can be set to a specific backend" ON)
OPTION( CURL "Use curl for HTTP if available" ON) OPTION(USE_GSSAPI "Link with libgssapi for SPNEGO auth" OFF)
OPTION( USE_EXT_HTTP_PARSER "Use system HTTP_Parser if available" ON) OPTION(USE_STANDALONE_FUZZERS "Enable standalone fuzzers (compatible with gcc)" OFF)
OPTION( DEBUG_POOL "Enable debug pool allocator" OFF ) OPTION(VALGRIND "Configure build for valgrind" OFF)
OPTION( ENABLE_WERROR "Enable compilation with -Werror" OFF ) OPTION(CURL "Use curl for HTTP if available" ON)
OPTION( USE_BUNDLED_ZLIB "Use the bundled version of zlib" OFF ) OPTION(USE_EXT_HTTP_PARSER "Use system HTTP_Parser if available" ON)
OPTION(DEBUG_POOL "Enable debug pool allocator" OFF)
OPTION(ENABLE_WERROR "Enable compilation with -Werror" OFF)
OPTION(USE_BUNDLED_ZLIB "Use the bundled version of zlib" OFF)
IF (UNIX AND NOT APPLE) IF (UNIX AND NOT APPLE)
OPTION( ENABLE_REPRODUCIBLE_BUILDS "Enable reproducible builds" OFF ) OPTION(ENABLE_REPRODUCIBLE_BUILDS "Enable reproducible builds" OFF)
ENDIF() ENDIF()
IF (APPLE) IF (APPLE)
OPTION( USE_ICONV "Link with and use iconv library" ON ) OPTION(USE_ICONV "Link with and use iconv library" ON)
ENDIF() ENDIF()
IF(MSVC) IF(MSVC)
...@@ -74,22 +77,22 @@ IF(MSVC) ...@@ -74,22 +77,22 @@ IF(MSVC)
# #
# If you are writing a CLR program and want to link to libgit2, you'll want # If you are writing a CLR program and want to link to libgit2, you'll want
# to turn this on by invoking CMake with the "-DSTDCALL=ON" argument. # to turn this on by invoking CMake with the "-DSTDCALL=ON" argument.
OPTION( STDCALL "Build libgit2 with the __stdcall convention" OFF ) OPTION(STDCALL "Build libgit2 with the __stdcall convention" OFF)
# This option must match the settings used in your program, in particular if you # This option must match the settings used in your program, in particular if you
# are linking statically # are linking statically
OPTION( STATIC_CRT "Link the static CRT libraries" ON ) OPTION(STATIC_CRT "Link the static CRT libraries" ON)
# If you want to embed a copy of libssh2 into libgit2, pass a # If you want to embed a copy of libssh2 into libgit2, pass a
# path to libssh2 # path to libssh2
OPTION( EMBED_SSH_PATH "Path to libssh2 to embed (Windows)" OFF ) OPTION(EMBED_SSH_PATH "Path to libssh2 to embed (Windows)" OFF)
ENDIF() ENDIF()
IF(WIN32) IF(WIN32)
# By default, libgit2 is built with WinHTTP. To use the built-in # By default, libgit2 is built with WinHTTP. To use the built-in
# HTTP transport, invoke CMake with the "-DWINHTTP=OFF" argument. # HTTP transport, invoke CMake with the "-DWINHTTP=OFF" argument.
OPTION( WINHTTP "Use Win32 WinHTTP routines" ON ) OPTION(WINHTTP "Use Win32 WinHTTP routines" ON)
ENDIF() ENDIF()
IF(MSVC) IF(MSVC)
...@@ -245,6 +248,14 @@ ELSE() ...@@ -245,6 +248,14 @@ ELSE()
# that uses CMAKE_CONFIGURATION_TYPES and not CMAKE_BUILD_TYPE # that uses CMAKE_CONFIGURATION_TYPES and not CMAKE_BUILD_TYPE
ENDIF() ENDIF()
IF(BUILD_FUZZERS AND NOT USE_STANDALONE_FUZZERS)
# The actual sanitizer link target will be added when linking the fuzz
# targets.
SET(CMAKE_REQUIRED_FLAGS "-fsanitize=fuzzer-no-link")
ADD_C_FLAG(-fsanitize=fuzzer-no-link)
UNSET(CMAKE_REQUIRED_FLAGS)
ENDIF ()
ADD_SUBDIRECTORY(src) ADD_SUBDIRECTORY(src)
# Tests # Tests
...@@ -282,6 +293,18 @@ IF (BUILD_EXAMPLES) ...@@ -282,6 +293,18 @@ IF (BUILD_EXAMPLES)
ADD_SUBDIRECTORY(examples) ADD_SUBDIRECTORY(examples)
ENDIF () ENDIF ()
IF(BUILD_FUZZERS)
IF(NOT USE_STANDALONE_FUZZERS)
IF(BUILD_EXAMPLES)
MESSAGE(FATAL_ERROR "Cannot build the fuzzer targets and the examples together")
ENDIF()
IF(BUILD_CLAR)
MESSAGE(FATAL_ERROR "Cannot build the fuzzer targets and the tests together")
ENDIF()
ENDIF()
ADD_SUBDIRECTORY(fuzzers)
ENDIF()
IF(CMAKE_VERSION VERSION_GREATER 3) IF(CMAKE_VERSION VERSION_GREATER 3)
FEATURE_SUMMARY(WHAT ENABLED_FEATURES DESCRIPTION "Enabled features:") FEATURE_SUMMARY(WHAT ENABLED_FEATURES DESCRIPTION "Enabled features:")
FEATURE_SUMMARY(WHAT DISABLED_FEATURES DESCRIPTION "Disabled features:") FEATURE_SUMMARY(WHAT DISABLED_FEATURES DESCRIPTION "Disabled features:")
......
...@@ -29,7 +29,7 @@ echo "## Configuring build environment" ...@@ -29,7 +29,7 @@ echo "## Configuring build environment"
echo "##############################################################################" echo "##############################################################################"
echo cmake ${SOURCE_DIR} -DBUILD_EXAMPLES=ON ${CMAKE_OPTIONS} echo cmake ${SOURCE_DIR} -DBUILD_EXAMPLES=ON ${CMAKE_OPTIONS}
cmake ${SOURCE_DIR} -DBUILD_EXAMPLES=ON ${CMAKE_OPTIONS} cmake ${SOURCE_DIR} -DBUILD_EXAMPLES=ON -DBUILD_FUZZERS=ON -DUSE_STANDALONE_FUZZERS=ON ${CMAKE_OPTIONS}
echo "" echo ""
echo "##############################################################################" echo "##############################################################################"
......
...@@ -184,6 +184,17 @@ if [ -z "$SKIP_SSH_TESTS" ]; then ...@@ -184,6 +184,17 @@ if [ -z "$SKIP_SSH_TESTS" ]; then
unset GITTEST_REMOTE_SSH_FINGERPRINT unset GITTEST_REMOTE_SSH_FINGERPRINT
fi fi
if [ -z "$SKIP_FUZZERS" ]; then
echo ""
echo "##############################################################################"
echo "## Running fuzzers"
echo "##############################################################################"
for fuzzer in fuzzers/*_fuzzer; do
"${fuzzer}" "${SOURCE_DIR}/fuzzers/corpora/$(basename "${fuzzer%_fuzzer}")" || die $?
done
fi
echo "Success." echo "Success."
cleanup cleanup
exit 0 exit 0
...@@ -5,6 +5,18 @@ ...@@ -5,6 +5,18 @@
INCLUDE(CheckCCompilerFlag) INCLUDE(CheckCCompilerFlag)
MACRO(ADD_C_FLAG _FLAG)
STRING(TOUPPER ${_FLAG} UPCASE)
STRING(REGEX REPLACE "^-" "" UPCASE_PRETTY ${UPCASE})
CHECK_C_COMPILER_FLAG(${_FLAG} IS_${UPCASE_PRETTY}_SUPPORTED)
IF(IS_${UPCASE_PRETTY}_SUPPORTED)
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_FLAG}")
ELSE()
MESSAGE(FATAL_ERROR "Required flag ${_FLAG} is not supported")
ENDIF()
ENDMACRO()
MACRO(ADD_C_FLAG_IF_SUPPORTED _FLAG) MACRO(ADD_C_FLAG_IF_SUPPORTED _FLAG)
STRING(TOUPPER ${_FLAG} UPCASE) STRING(TOUPPER ${_FLAG} UPCASE)
STRING(REGEX REPLACE "^-" "" UPCASE_PRETTY ${UPCASE}) STRING(REGEX REPLACE "^-" "" UPCASE_PRETTY ${UPCASE})
......
# Fuzzing
libgit2 is currently using [libFuzzer](https://libfuzzer.info) to perform
automated fuzz testing. libFuzzer only works with clang.
## Prerequisites** for building fuzz targets:
1. All the prerequisites for [building libgit2](https://github.com/libgit2/libgit2).
2. A recent version of clang. 6.0 is preferred. [pre-build Debian/Ubuntu
packages](https://github.com/libgit2/libgit2)
## Build
1. Create a build directory beneath the libgit2 source directory, and change
into it: `mkdir build && cd build`
2. Choose one sanitizers to add. The currently supported sanitizers are
[`address`](https://clang.llvm.org/docs/AddressSanitizer.html),
[`undefined`](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html),
and [`leak`/`address,leak`](https://clang.llvm.org/docs/LeakSanitizer.html).
3. Create the cmake build environment and configure the build with the
sanitizer chosen: `CC=/usr/bin/clang-6.0 CFLAGS="-fsanitize=address" cmake
-DBUILD_CLAR=OFF -DBUILD_FUZZERS=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo ..`.
Note that building the fuzzer targets is incompatible with the
tests and examples.
4. Build libgit2: `cmake --build .`
5. Exit the cmake build environment: `cd ..`
## Run the fuzz targets
1. `ASAN_SYMBOLIZER_PATH=/usr/bin/llvm-symbolize-6.0
LSAN_OPTIONS=allocator_may_return_null=1
ASAN_OPTIONS=allocator_may_return_null=1 ./build/fuzz/fuzz_packfile_raw
fuzz/corpora/fuzz_packfile_raw/`
The `LSAN_OPTIONS` and `ASAN_OPTIONS` are there to allow `malloc(3)` to return
`NULL`. The `LLVM_PROFILE_FILE` is there to override the path where libFuzzer
will write the coverage report.
## Get coverage
In order to get coverage information, you need to add the "-fcoverage-mapping"
and "-fprofile-instr-generate CFLAGS, and then run the fuzz target with
`-runs=0`. That will produce a file called `default.profraw` (this behavior can
be overridden by setting the `LLVM_PROFILE_FILE="yourfile.profraw"` environment
variable).
1. `llvm-profdata-6.0 merge -sparse default.profraw -o
fuzz_packfile_raw.profdata` transforms the data from a sparse representation
into a format that can be used by the other tools.
2. `llvm-cov-6.0 report ./build/fuzz/fuzz_packfile_raw
-instr-profile=fuzz_packfile_raw.profdata` shows a high-level per-file
coverage report.
3. `llvm-cov-6.0 show ./build/fuzz/fuzz_packfile_raw
-instr-profile=fuzz_packfile_raw.profdata [source file]` shows a line-by-line
coverage analysis of all the codebase (or a single source file).
## Standalone mode
In order to ensure that there are no regresions, each fuzzer target can be run
in a standalone mode. This can be done by passing `-DUSE_STANDALONE_FUZZERS=ON`.
This makes it compatible with gcc. This does not use the fuzzing engine, but
just invokes every file in the chosen corpus.
In order to get full coverage, though, you might want to also enable one of the
sanitizers. You might need a recent version of clang to get full support.
## References
* [libFuzzer](https://llvm.org/docs/LibFuzzer.html) documentation.
* [Source-based Code
Coverage](https://clang.llvm.org/docs/SourceBasedCodeCoverage.html).
LINK_DIRECTORIES(${LIBGIT2_LIBDIRS})
INCLUDE_DIRECTORIES(${LIBGIT2_INCLUDES})
IF(BUILD_FUZZERS AND NOT USE_STANDALONE_FUZZERS)
ADD_C_FLAG(-fsanitize=fuzzer)
ENDIF ()
FILE(GLOB SRC_FUZZ RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *_fuzzer.c)
FOREACH(fuzz_target_src ${SRC_FUZZ})
STRING(REPLACE ".c" "" fuzz_target_name ${fuzz_target_src})
SET(${fuzz_target_name}_SOURCES ${fuzz_target_src} ${LIBGIT2_OBJECTS})
IF(USE_STANDALONE_FUZZERS)
LIST(APPEND ${fuzz_target_name}_SOURCES "standalone_driver.c")
ENDIF()
ADD_EXECUTABLE(${fuzz_target_name} ${${fuzz_target_name}_SOURCES})
SET_TARGET_PROPERTIES(${fuzz_target_name} PROPERTIES C_STANDARD 90)
TARGET_LINK_LIBRARIES(${fuzz_target_name} ${LIBGIT2_LIBS})
ENDFOREACH()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment