🔨 split AFL test in driver and test file
This commit is contained in:
parent
048330b14b
commit
a084e90f39
6 changed files with 91 additions and 63 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -21,3 +21,5 @@ cmake-build-debug
|
|||
|
||||
test/test-*
|
||||
.svn
|
||||
|
||||
test/thirdparty/Fuzzer/libFuzzer.a
|
||||
|
|
10
Makefile
10
Makefile
|
@ -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"
|
||||
|
||||
|
||||
##########################################################################
|
||||
|
|
|
@ -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 $@
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
/*
|
||||
__ _____ _____ _____
|
||||
__| | __| | | | JSON for Modern C++ (fuzz test support)
|
||||
| | |__ | | | | | | version 2.0.9
|
||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
|
||||
Run "make fuzz_testing" and follow the instructions.
|
||||
|
||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
*/
|
||||
|
||||
#include <json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifdef __AFL_HAVE_MANUAL_CONTROL
|
||||
while (__AFL_LOOP(1000))
|
||||
{
|
||||
#endif
|
||||
try
|
||||
{
|
||||
json j(std::cin);
|
||||
std::cout << j << std::endl;
|
||||
}
|
||||
catch (std::invalid_argument& e)
|
||||
{
|
||||
std::cout << "Invalid argument in parsing" << e.what() << '\n';
|
||||
}
|
||||
#ifdef __AFL_HAVE_MANUAL_CONTROL
|
||||
}
|
||||
#endif
|
||||
}
|
33
test/src/fuzzer-driver_afl.cpp
Normal file
33
test/src/fuzzer-driver_afl.cpp
Normal file
|
@ -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
|
||||
}
|
|
@ -1,16 +1,23 @@
|
|||
// 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>
|
||||
|
@ -18,25 +25,41 @@
|
|||
|
||||
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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue