From 786851819efe52c14114a857faf30b508e537c1b Mon Sep 17 00:00:00 2001 From: Autofuzz team Date: Wed, 12 Jun 2019 16:02:05 +0200 Subject: [PATCH] Add a simple fuzz test for jsoncpp. --- AUTHORS | 1 + src/test_lib_json/CMakeLists.txt | 2 ++ src/test_lib_json/fuzz.cpp | 49 ++++++++++++++++++++++++++++++++ src/test_lib_json/fuzz.h | 14 +++++++++ src/test_lib_json/main.cpp | 15 ++++++++++ 5 files changed, 81 insertions(+) create mode 100644 src/test_lib_json/fuzz.cpp create mode 100644 src/test_lib_json/fuzz.h diff --git a/AUTHORS b/AUTHORS index 77c1d2d..3723d54 100644 --- a/AUTHORS +++ b/AUTHORS @@ -37,6 +37,7 @@ datadiode David Seifert David West dawesc +Devin Jeanpierre Dmitry Marakasov dominicpezzuto Don Milham diff --git a/src/test_lib_json/CMakeLists.txt b/src/test_lib_json/CMakeLists.txt index a8740da..abb1813 100644 --- a/src/test_lib_json/CMakeLists.txt +++ b/src/test_lib_json/CMakeLists.txt @@ -3,6 +3,8 @@ add_executable( jsoncpp_test jsontest.cpp jsontest.h + fuzz.cpp + fuzz.h main.cpp ) diff --git a/src/test_lib_json/fuzz.cpp b/src/test_lib_json/fuzz.cpp new file mode 100644 index 0000000..8265a17 --- /dev/null +++ b/src/test_lib_json/fuzz.cpp @@ -0,0 +1,49 @@ +// Copyright 2007-2010 The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#include "fuzz.h" + +#include +#include +#include +#include +#include +#include + +namespace Json { +class Exception; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + Json::CharReaderBuilder builder; + + if (size < sizeof(uint32_t)) { + return 0; + } + + uint32_t hash_settings = *(const uint32_t*)data; + data += sizeof(uint32_t); + + builder.settings_["failIfExtra"] = hash_settings & (1 << 0); + builder.settings_["allowComments_"] = hash_settings & (1 << 1); + builder.settings_["strictRoot_"] = hash_settings & (1 << 2); + builder.settings_["allowDroppedNullPlaceholders_"] = hash_settings & (1 << 3); + builder.settings_["allowNumericKeys_"] = hash_settings & (1 << 4); + builder.settings_["allowSingleQuotes_"] = hash_settings & (1 << 5); + builder.settings_["failIfExtra_"] = hash_settings & (1 << 6); + builder.settings_["rejectDupKeys_"] = hash_settings & (1 << 7); + builder.settings_["allowSpecialFloats_"] = hash_settings & (1 << 8); + + std::unique_ptr reader(builder.newCharReader()); + + Json::Value root; + const char* data_str = reinterpret_cast(data); + try { + reader->parse(data_str, data_str + size, &root, nullptr); + } catch (Json::Exception const&) { + } + // Whether it succeeded or not doesn't matter. + return 0; +} diff --git a/src/test_lib_json/fuzz.h b/src/test_lib_json/fuzz.h new file mode 100644 index 0000000..f650437 --- /dev/null +++ b/src/test_lib_json/fuzz.h @@ -0,0 +1,14 @@ +// Copyright 2007-2010 The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef FUZZ_H_INCLUDED +#define FUZZ_H_INCLUDED + +#include +#include + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size); + +#endif // ifndef FUZZ_H_INCLUDED diff --git a/src/test_lib_json/main.cpp b/src/test_lib_json/main.cpp index 550b9c7..3fe7c01 100644 --- a/src/test_lib_json/main.cpp +++ b/src/test_lib_json/main.cpp @@ -10,6 +10,7 @@ #pragma warning(disable : 4996) #endif +#include "fuzz.h" #include "jsontest.h" #include #include @@ -2555,6 +2556,18 @@ JSONTEST_FIXTURE(RValueTest, moveConstruction) { JSONTEST_ASSERT_EQUAL(Json::stringValue, moved["key"].type()); } +struct FuzzTest : JsonTest::TestCase {}; + +// Build and run the fuzz test without any fuzzer, so that it's guaranteed not +// go out of date, even if it's never run as an actual fuzz test. +JSONTEST_FIXTURE(FuzzTest, fuzzDoesntCrash) { + const std::string example = "{}"; + JSONTEST_ASSERT_EQUAL( + 0, + LLVMFuzzerTestOneInput(reinterpret_cast(example.c_str()), + example.size())); +} + int main(int argc, const char* argv[]) { JsonTest::Runner runner; JSONTEST_REGISTER_FIXTURE(runner, ValueTest, checkNormalizeFloatingPointStr); @@ -2635,6 +2648,8 @@ int main(int argc, const char* argv[]) { JSONTEST_REGISTER_FIXTURE(runner, RValueTest, moveConstruction); + JSONTEST_REGISTER_FIXTURE(runner, FuzzTest, fuzzDoesntCrash); + return runner.runCommandLine(argc, argv); }