Commit 6e1d2317 authored by Kenton Varda's avatar Kenton Varda Committed by GitHub

Merge pull request #443 from sandstorm-io/afl

Add AFL test case
parents af7efaaf e583fbbc
...@@ -387,7 +387,13 @@ capnp_test_LDADD = libcapnp.la libkj-test.la libkj.la ...@@ -387,7 +387,13 @@ capnp_test_LDADD = libcapnp.la libkj-test.la libkj.la
else !LITE_MODE else !LITE_MODE
check_PROGRAMS = capnp-test capnp-evolution-test check_LIBRARIES = libcapnp-test.a
libcapnp_test_a_SOURCES = \
src/capnp/test-util.c++ \
src/capnp/test-util.h
nodist_libcapnp_test_a_SOURCES = $(test_capnpc_outputs)
check_PROGRAMS = capnp-test capnp-evolution-test capnp-afl-testcase
heavy_tests = \ heavy_tests = \
src/kj/async-test.c++ \ src/kj/async-test.c++ \
src/kj/async-unix-test.c++ \ src/kj/async-unix-test.c++ \
...@@ -412,7 +418,9 @@ heavy_tests = \ ...@@ -412,7 +418,9 @@ heavy_tests = \
src/capnp/compat/json-test.c++ \ src/capnp/compat/json-test.c++ \
src/capnp/compiler/lexer-test.c++ \ src/capnp/compiler/lexer-test.c++ \
src/capnp/compiler/md5-test.c++ src/capnp/compiler/md5-test.c++
capnp_test_LDADD = libcapnpc.la \ capnp_test_LDADD = \
libcapnp-test.a \
libcapnpc.la \
libcapnp-rpc.la \ libcapnp-rpc.la \
libcapnp-json.la \ libcapnp-json.la \
libcapnp.la \ libcapnp.la \
...@@ -455,14 +463,14 @@ capnp_test_SOURCES = \ ...@@ -455,14 +463,14 @@ capnp_test_SOURCES = \
src/capnp/serialize-test.c++ \ src/capnp/serialize-test.c++ \
src/capnp/serialize-packed-test.c++ \ src/capnp/serialize-packed-test.c++ \
src/capnp/fuzz-test.c++ \ src/capnp/fuzz-test.c++ \
src/capnp/test-util.c++ \
src/capnp/test-util.h \
$(heavy_tests) $(heavy_tests)
nodist_capnp_test_SOURCES = $(test_capnpc_outputs)
if !LITE_MODE if !LITE_MODE
capnp_evolution_test_LDADD = libcapnpc.la libcapnp.la libkj.la capnp_evolution_test_LDADD = libcapnpc.la libcapnp.la libkj.la
capnp_evolution_test_SOURCES = src/capnp/compiler/evolution-test.c++ capnp_evolution_test_SOURCES = src/capnp/compiler/evolution-test.c++
capnp_afl_testcase_LDADD = libcapnp-test.a libcapnp-rpc.la libcapnp.la libkj.la libkj-async.la
capnp_afl_testcase_SOURCES = src/capnp/afl-testcase.c++
endif !LITE_MODE endif !LITE_MODE
if LITE_MODE if LITE_MODE
......
// Copyright (c) 2017 Cloudflare, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "test-util.h"
#include <kj/main.h>
#include "serialize.h"
#include <capnp/test.capnp.h>
#include <unistd.h>
namespace capnp {
namespace _ {
namespace {
class AflTestMain {
public:
explicit AflTestMain(kj::ProcessContext& context)
: context(context) {}
kj::MainFunc getMain() {
return kj::MainBuilder(context, "(unknown version)",
"American Fuzzy Lop test case. Pass input on stdin. Expects a binary "
"message of type TestAllTypes.")
.addOption({"lists"}, KJ_BIND_METHOD(*this, runLists),
"Expect a message of type TestLists instead of TestAllTypes.")
.addOption({"canonicalize"}, KJ_BIND_METHOD(*this, canonicalize),
"Test canonicalization code.")
.callAfterParsing(KJ_BIND_METHOD(*this, run))
.build();
}
kj::MainBuilder::Validity run() {
capnp::StreamFdMessageReader reader(STDIN_FILENO);
KJ_IF_MAYBE(e, kj::runCatchingExceptions([&]() {
checkTestMessage(reader.getRoot<TestAllTypes>());
})) {
KJ_LOG(ERROR, "threw");
}
KJ_IF_MAYBE(e, kj::runCatchingExceptions([&]() {
checkDynamicTestMessage(reader.getRoot<DynamicStruct>(Schema::from<TestAllTypes>()));
})) {
KJ_LOG(ERROR, "dynamic threw");
}
KJ_IF_MAYBE(e, kj::runCatchingExceptions([&]() {
kj::str(reader.getRoot<TestAllTypes>());
})) {
KJ_LOG(ERROR, "str threw");
}
context.exit();
}
kj::MainBuilder::Validity runLists() {
capnp::StreamFdMessageReader reader(STDIN_FILENO);
KJ_IF_MAYBE(e, kj::runCatchingExceptions([&]() {
kj::str(reader.getRoot<test::TestLists>());
})) {
KJ_LOG(ERROR, "threw");
}
context.exit();
}
kj::MainBuilder::Validity canonicalize() {
// (Test case contributed by David Renshaw.)
kj::Array<capnp::word> canonical;
bool equal = false;
KJ_IF_MAYBE(e, kj::runCatchingExceptions([&]() {
capnp::ReaderOptions options;
// The default traversal limit of 8 * 1024 * 1024 causes
// AFL to think that it has found "hang" bugs.
options.traversalLimitInWords = 8 * 1024;
capnp::StreamFdMessageReader message(0, options); // read from stdin
TestAllTypes::Reader myStruct = message.getRoot<TestAllTypes>();
canonical = capnp::canonicalize(myStruct);
kj::ArrayPtr<const capnp::word> segments[1] = {canonical.asPtr()};
capnp::SegmentArrayMessageReader reader(kj::arrayPtr(segments, 1));
auto originalAny = message.getRoot<capnp::AnyPointer>();
// Discard cases where the original message is null.
KJ_ASSERT(!originalAny.isNull());
equal = originalAny == reader.getRoot<capnp::AnyPointer>();
})) {
// Probably some kind of decoding exception.
KJ_LOG(ERROR, "threw");
context.exit();
}
KJ_ASSERT(equal);
kj::ArrayPtr<const capnp::word> segments[1] = {canonical.asPtr()};
capnp::SegmentArrayMessageReader reader(kj::arrayPtr(segments, 1));
KJ_ASSERT(reader.isCanonical());
kj::Array<capnp::word> canonical2;
{
capnp::ReaderOptions options;
options.traversalLimitInWords = 8 * 1024;
TestAllTypes::Reader myStruct = reader.getRoot<TestAllTypes>();
canonical2 = capnp::canonicalize(myStruct);
}
KJ_ASSERT(canonical.size() == canonical2.size());
auto b1 = canonical.asBytes();
auto b2 = canonical2.asBytes();
for (int idx = 0; idx < b1.size(); ++idx) {
KJ_ASSERT(b1[idx] == b2[idx], idx, b1.size());
}
context.exit();
}
private:
kj::ProcessContext& context;
};
} // namespace
} // namespace _
} // namespace capnp
KJ_MAIN(capnp::_::AflTestMain);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment