Skip to content

Commit

Permalink
Merge pull request #610 from ssbr/master
Browse files Browse the repository at this point in the history
Add a simple fuzz test for jsoncpp. Only in cmake.
  • Loading branch information
cdunn2001 authored Sep 13, 2017
2 parents 586e7a8 + edd093c commit 8ba25e0
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 0 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ datadiode <jochen.neubeck@vodafone.de>
David Seifert <soap@gentoo.org>
David West <david-west@idexx.com>
dawesc <chris.dawes@eftlab.co.uk>
Devin Jeanpierre <jeanpierreda@google.com>
Dmitry Marakasov <amdmi3@amdmi3.ru>
dominicpezzuto <dom@dompezzuto.com>
Don Milham <dmilham@gmail.com>
Expand Down
2 changes: 2 additions & 0 deletions src/test_lib_json/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
ADD_EXECUTABLE( jsoncpp_test
jsontest.cpp
jsontest.h
fuzz.cpp
fuzz.h
main.cpp
)

Expand Down
57 changes: 57 additions & 0 deletions src/test_lib_json/fuzz.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// 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 <json/config.h>
#include <json/json.h>
#include <memory>
#include <string>
#include <stdint.h>

namespace {
// https://en.wikipedia.org/wiki/Jenkins_hash_function#one-at-a-time
uint32_t JenkinsOneAtATimeHash(const uint8_t* data, size_t size) {
uint32_t hash = 0;
for (size_t i = 0; i < size; i++) {
hash += data[i];
hash += hash << 10;
hash ^= hash >> 6;
}
hash += hash << 3;
hash ^= hash >> 11;
hash += hash << 15;
return hash;
}
} // namespace

namespace Json {
class Exception;
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
Json::CharReaderBuilder builder;

uint32_t hash_settings = JenkinsOneAtATimeHash(data, size);
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<Json::CharReader> reader(builder.newCharReader());

Json::Value root;
const char* data_str = reinterpret_cast<const char*>(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;
}
14 changes: 14 additions & 0 deletions src/test_lib_json/fuzz.h
Original file line number Diff line number Diff line change
@@ -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 <stddef.h>
#include <stdint.h>

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);

#endif // ifndef FUZZ_H_INCLUDED
16 changes: 16 additions & 0 deletions src/test_lib_json/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"

#include "jsontest.h"
#include "fuzz.h"
#include <json/config.h>
#include <json/json.h>
#include <cstring>
Expand Down Expand Up @@ -2513,6 +2514,19 @@ JSONTEST_FIXTURE(RValueTest, moveConstruction) {
#endif
}

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<const uint8_t*>(example.c_str()),
example.size()));
}

int main(int argc, const char* argv[]) {
JsonTest::Runner runner;
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, checkNormalizeFloatingPointStr);
Expand Down Expand Up @@ -2588,6 +2602,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);
}

Expand Down

0 comments on commit 8ba25e0

Please sign in to comment.