Merge pull request #78 from bshastry:libfuzzer-harness

PiperOrigin-RevId: 264241380
This commit is contained in:
Victor Costan 2019-08-19 14:30:12 -07:00
commit fd79e6f9b2
4 changed files with 163 additions and 1 deletions

View file

@ -53,6 +53,12 @@ install:
- if [ "$TRAVIS_OS_NAME" == "osx" ]; then
export PATH="$(brew --prefix llvm)/bin:$PATH";
fi
# Fuzzing is only supported on Clang. Perform fuzzing on Debug builds.
- if [ "$CXX" = "clang++" ] && [ "$BUILD_TYPE" = "Debug" ]; then
export FUZZING=1;
else
export FUZZING=0;
fi
# /usr/bin/gcc points to an older compiler on both Linux and macOS.
- if [ "$CXX" = "g++" ]; then export CXX="g++-9" CC="gcc-9"; fi
# /usr/bin/clang points to an older compiler on both Linux and macOS.
@ -71,9 +77,15 @@ install:
before_script:
- mkdir -p build && cd build
- cmake .. -G Ninja -DCMAKE_BUILD_TYPE=$BUILD_TYPE
-DSNAPPY_REQUIRE_${CPU_LEVEL}=ON
-DSNAPPY_REQUIRE_${CPU_LEVEL}=ON -DSNAPPY_FUZZING_BUILD=${FUZZING}
- cmake --build .
- cd ..
script:
- build/snappy_unittest
- if [ -f build/snappy_compress_fuzzer ]; then
build/snappy_compress_fuzzer -runs=1000 -close_fd_mask=3;
fi
- if [ -f build/snappy_uncompress_fuzzer ]; then
build/snappy_uncompress_fuzzer -runs=1000 -close_fd_mask=3;
fi

View file

@ -12,6 +12,8 @@ option(BUILD_SHARED_LIBS "Build shared libraries(DLLs)." OFF)
option(SNAPPY_BUILD_TESTS "Build Snappy's own tests." ON)
option(SNAPPY_FUZZING_BUILD "Build Snappy for fuzzing." OFF)
option(SNAPPY_REQUIRE_AVX "Target processors with AVX support." OFF)
option(SNAPPY_REQUIRE_AVX2 "Target processors with AVX2 support." OFF)
@ -113,6 +115,20 @@ if(NOT HAVE_SYS_UIO_H_01)
set(HAVE_SYS_UIO_H_01 0)
endif(NOT HAVE_SYS_UIO_H_01)
if (SNAPPY_FUZZING_BUILD)
if (NOT "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
message(WARNING "Fuzzing builds are only supported with Clang")
endif (NOT "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
if(NOT CMAKE_CXX_FLAGS MATCHES "-fsanitize=address")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
endif(NOT CMAKE_CXX_FLAGS MATCHES "-fsanitize=address")
if(NOT CMAKE_CXX_FLAGS MATCHES "-fsanitize-coverage=trace-pc-guard")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize-coverage=trace-pc-guard")
endif(NOT CMAKE_CXX_FLAGS MATCHES "-fsanitize-coverage=trace-pc-guard")
endif (SNAPPY_FUZZING_BUILD)
configure_file(
"${PROJECT_SOURCE_DIR}/snappy-stubs-public.h.in"
"${PROJECT_BINARY_DIR}/snappy-stubs-public.h")
@ -185,6 +201,26 @@ if(SNAPPY_BUILD_TESTS)
COMMAND "${PROJECT_BINARY_DIR}/snappy_unittest")
endif(SNAPPY_BUILD_TESTS)
if(SNAPPY_FUZZING_BUILD)
add_executable(snappy_compress_fuzzer "")
target_sources(snappy_compress_fuzzer
PRIVATE "${PROJECT_SOURCE_DIR}/snappy_compress_fuzzer.cc"
)
target_link_libraries(snappy_compress_fuzzer snappy)
set_target_properties(snappy_compress_fuzzer
PROPERTIES LINK_FLAGS "-fsanitize=fuzzer"
)
add_executable(snappy_uncompress_fuzzer "")
target_sources(snappy_uncompress_fuzzer
PRIVATE "${PROJECT_SOURCE_DIR}/snappy_uncompress_fuzzer.cc"
)
target_link_libraries(snappy_uncompress_fuzzer snappy)
set_target_properties(snappy_uncompress_fuzzer
PROPERTIES LINK_FLAGS "-fsanitize=fuzzer"
)
endif(SNAPPY_FUZZING_BUILD)
include(GNUInstallDirs)
install(TARGETS snappy
EXPORT SnappyTargets

57
zippy_compress_fuzzer.cc Normal file
View file

@ -0,0 +1,57 @@
// Copyright 2019 Google Inc. All Rights Reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// libFuzzer harness for fuzzing snappy compression code.
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <string>
#include "snappy.h"
// Entry point for LibFuzzer.
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
std::string input(reinterpret_cast<const char*>(data), size);
std::string compressed;
size_t compressed_size =
snappy::Compress(input.data(), input.size(), &compressed);
assert(compressed_size == compressed.size());
assert(compressed.size() <= snappy::MaxCompressedLength(input.size()));
assert(snappy::IsValidCompressedBuffer(compressed.data(), compressed.size()));
std::string uncompressed_after_compress;
bool uncompress_succeeded = snappy::Uncompress(
compressed.data(), compressed.size(), &uncompressed_after_compress);
assert(uncompress_succeeded);
assert(input == uncompressed_after_compress);
return 0;
}

View file

@ -0,0 +1,57 @@
// Copyright 2019 Google Inc. All Rights Reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// libFuzzer harness for fuzzing snappy's decompression code.
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <string>
#include "snappy.h"
// Entry point for LibFuzzer.
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
std::string input(reinterpret_cast<const char*>(data), size);
// Avoid self-crafted decompression bombs.
size_t uncompressed_size;
constexpr size_t kMaxUncompressedSize = 1 << 20;
bool get_uncompressed_length_succeeded = snappy::GetUncompressedLength(
input.data(), input.size(), &uncompressed_size);
if (!get_uncompressed_length_succeeded ||
(uncompressed_size > kMaxUncompressedSize)) {
return 0;
}
std::string uncompressed;
// The return value of snappy::Uncompress() is ignored because decompression
// will fail on invalid inputs.
snappy::Uncompress(input.data(), input.size(), &uncompressed);
return 0;
}