Add libFuzzer integration + report bug

This commit places the basics for libFuzzer integration with one
fuzzer which fuzzes the readMetadata function. The fuzzer is
located at fuzz/read-metadata.

To add more fuzzers please add them to ./fuzz directory as
described in the README.

Also a memory corruption bug is found using this fuzzer which
might lead to additional bugs after fix is pushed.
This commit is contained in:
Jeka Pats 2019-07-03 14:17:59 +03:00 committed by Kevin Backhouse
parent c7757d7c08
commit b2cdf2a535
No known key found for this signature in database
GPG Key ID: 9DD01852EE40366E
5 changed files with 72 additions and 0 deletions

View File

@ -35,6 +35,7 @@ option( EXIV2_ENABLE_BMFF "Build with BMFF support"
option( EXIV2_BUILD_SAMPLES "Build sample applications" ON )
option( EXIV2_BUILD_EXIV2_COMMAND "Build exiv2 command-line executable" ON )
option( EXIV2_BUILD_UNIT_TESTS "Build unit tests" OFF )
option( EXIV2_BUILD_FUZZ_TESTS "Build fuzz tests (libFuzzer)" OFF )
option( EXIV2_BUILD_DOC "Add 'doc' target to generate documentation" OFF )
# Only intended to be used by Exiv2 developers/contributors
@ -91,6 +92,14 @@ if( EXIV2_BUILD_UNIT_TESTS )
add_subdirectory ( unitTests )
endif()
if( EXIV2_BUILD_FUZZ_TESTS)
if ((NOT COMPILER_IS_CLANG) OR (NOT EXIV2_TEAM_USE_SANITIZERS))
message(FATAL_ERROR "You need to build with Clang and sanitizers for the fuzzers to work. "
"Use Clang and -DEXIV2_TEAM_USE_SANITIZERS=ON")
endif()
add_subdirectory ( fuzz )
endif()
if( EXIV2_BUILD_SAMPLES )
add_subdirectory( samples )
get_directory_property(SAMPLES DIRECTORY samples DEFINITION APPLICATIONS)

View File

@ -64,6 +64,7 @@ The file ReadMe.txt in a build bundle describes how to install the library on th
3. [Unit tests](#4-3)
4. [Python tests](#4-4)
5. [Test Summary](#4-5)
6. [Fuzzing](#4-6)
5. [Platform Notes](#5)
1. [Linux](#5-1)
2. [macOS](#5-2)
@ -1039,6 +1040,29 @@ $ cd <exiv2dir>/build
$ make python_tests 2>&1 | grep FAIL
```
### 4.6 Fuzzing
The code for the fuzzers is in `exiv2dir/fuzz`
To build the fuzzers, use the *cmake* option `-DEXIV2_BUILD_FUZZ_TESTS=ON` and `-DEXIV2_TEAM_USE_SANITIZERS=ON`.
Note that it only works with clang compiler as libFuzzer is integrate with clang > 6.0
To build the fuzzers:
```bash
$ cd <exiv2dir>
$ rm -rf build-fuzz ; mkdir build-fuzz ; cd build-fuzz
$ cmake .. -DCMAKE_CXX_COMPILER=$(which clang++) -DEXIV2_BUILD_FUZZ_TESTS=ON -DEXIV2_TEAM_USE_SANITIZERS=ON
$ cmake --build .
```
To execute the fuzzers:
```bash
cd <exiv2dir>/build-fuzz
bin/<fuzzer_name> # for example ./bin/read-metadata.cpp
```
[TOC](#TOC)
<div id="4-5">

View File

@ -66,6 +66,7 @@ endif()
OptionOutput( "Building exiv2 command: " EXIV2_BUILD_EXIV2_COMMAND )
OptionOutput( "Building samples: " EXIV2_BUILD_SAMPLES )
OptionOutput( "Building unit tests: " EXIV2_BUILD_UNIT_TESTS )
OptionOutput( "Building fuzz tests: " EXIV2_BUILD_FUZZ_TESTS )
OptionOutput( "Building doc: " EXIV2_BUILD_DOC )
OptionOutput( "Building with coverage flags: " BUILD_WITH_COVERAGE )
OptionOutput( "Using ccache: " BUILD_WITH_CCACHE )

14
fuzz/CMakeLists.txt Normal file
View File

@ -0,0 +1,14 @@
macro(fuzzer name)
add_executable(${name} ${name}.cpp)
set_target_properties(${name}
PROPERTIES
COMPILE_FLAGS "-fsanitize=fuzzer"
LINK_FLAGS "-fsanitize=fuzzer")
target_link_libraries(${name}
PRIVATE
exiv2lib
)
endmacro()
fuzzer(read-metadata)

24
fuzz/read-metadata.cpp Normal file
View File

@ -0,0 +1,24 @@
#include <exiv2/exiv2.hpp>
#include <iostream>
#include <iomanip>
#include <cassert>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t * Data, size_t Size)
try {
Exiv2::Image::UniquePtr image = Exiv2::ImageFactory::open(Data, Size);
assert(image.get() != 0);
image->readMetadata();
Exiv2::ExifData &exifData = image->exifData();
if (exifData.empty()) {
return -1;
}
return 0;
}
catch (Exiv2::Error& e) {
return -1;
}