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:
parent
c7757d7c08
commit
b2cdf2a535
@ -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)
|
||||
|
||||
24
README.md
24
README.md
@ -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">
|
||||
|
||||
|
||||
@ -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
14
fuzz/CMakeLists.txt
Normal 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
24
fuzz/read-metadata.cpp
Normal 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;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user