Skip to content

Commit

Permalink
🔨 split AFL test in driver and test file
Browse files Browse the repository at this point in the history
  • Loading branch information
nlohmann committed Dec 22, 2016
1 parent 048330b commit a084e90
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 63 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -21,3 +21,5 @@ cmake-build-debug

test/test-*
.svn

test/thirdparty/Fuzzer/libFuzzer.a
10 changes: 3 additions & 7 deletions Makefile
Expand Up @@ -49,14 +49,10 @@ doctest:
fuzz_testing:
rm -fr fuzz-testing
mkdir -p fuzz-testing fuzz-testing/testcases fuzz-testing/out
$(MAKE) fuzz CXX=afl-clang++
mv fuzz fuzz-testing
$(MAKE) parse_afl_fuzzer -C test CXX=afl-clang++
mv test/fuzzer parse_afl_fuzzer
find test/data/json_tests -size -5k -name *json | xargs -I{} cp "{}" fuzz-testing/testcases
@echo "Execute: afl-fuzz -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzz"

# the fuzzer binary
fuzz: test/src/fuzz.cpp src/json.hpp
$(CXX) -std=c++11 $(CXXFLAGS) $(FLAGS) $(CPPFLAGS) -I src $< $(LDFLAGS) -o $@
@echo "Execute: afl-fuzz -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer"


##########################################################################
Expand Down
8 changes: 8 additions & 0 deletions test/Makefile
Expand Up @@ -78,3 +78,11 @@ TEST_PATTERN = "*"
TEST_PREFIX = ""
check: $(TESTCASES)
@cd .. ; for testcase in $(TESTCASES); do echo "Executing $$testcase..."; $(TEST_PREFIX)test/$$testcase $(TEST_PATTERN) || exit 1; done


##############################################################################
# fuzzer
##############################################################################

parse_afl_fuzzer:
$(CXX) $(CXXFLAGS) $(CPPFLAGS) src/fuzzer-driver_afl.cpp src/fuzzer-parse_json.cpp -o $@
34 changes: 0 additions & 34 deletions test/src/fuzz.cpp

This file was deleted.

33 changes: 33 additions & 0 deletions test/src/fuzzer-driver_afl.cpp
@@ -0,0 +1,33 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (fuzz test support)
| | |__ | | | | | | version 2.0.9
|_____|_____|_____|_|___| https://github.com/nlohmann/json
This file implements a driver for American Fuzzy Lop (afl-fuzz). It relies on
an implementation of the `LLVMFuzzerTestOneInput` function which processes a
passed byte array.
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
*/

#include <sstream>
#include <cstdint>
#include <iostream>

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

int main()
{
#ifdef __AFL_HAVE_MANUAL_CONTROL
while (__AFL_LOOP(1000))
{
#endif
// copy stdin to stringstream to pass it to fuzzer as byte array
std::stringstream ss;
ss << std::cin.rdbuf();
LLVMFuzzerTestOneInput(reinterpret_cast<const uint8_t*>(ss.str().c_str()), ss.str().size());
#ifdef __AFL_HAVE_MANUAL_CONTROL
}
#endif
}
67 changes: 45 additions & 22 deletions test/src/fuzzer-parse_json.cpp
@@ -1,42 +1,65 @@
// Copyright 2016 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (fuzz test support)
| | |__ | | | | | | version 2.0.9
|_____|_____|_____|_|___| https://github.com/nlohmann/json
This file implements a parser test suitable for fuzz testing. Given a byte
array data, it performs the following steps:
- j1 = parse(data)
- s1 = serialize(j1)
- j2 = parse(s1)
- s2 = serialize(j2)
- assert(s1 == s2)
The provided function `LLVMFuzzerTestOneInput` can be used in different fuzzer
drivers.
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
*/

#include <iostream>
#include <sstream>
#include <json.hpp>

using json = nlohmann::json;

// see http://llvm.org/docs/LibFuzzer.html
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{
try
{
std::stringstream s;
s << json::parse(data, data + size);
// step 1: parse input
json j1 = json::parse(data, data + size);

try
{
auto j = json::parse(s.str());
std::stringstream s2;
s2 << j;
assert(s.str() == s2.str());
assert(j == json::parse(s.str()));
// step 2: round trip

// first serialization
std::string s1 = j1.dump();

// parse serialization
json j2 = json::parse(s1);

// second serialization
std::string s2 = j2.dump();

// serializations must match
assert(s1 == s2);
}
catch (const std::invalid_argument&)
{
assert(0);
// parsing a JSON serialization must not fail
assert(false);
}
}
catch (const std::invalid_argument&) { }
catch (const std::invalid_argument&)
{
// parse errors are ok, because input may be random bytes
}

// return 0 - non-zero return values are reserved for future use
return 0;
}

0 comments on commit a084e90

Please sign in to comment.