Commit e583fbbc authored by Kenton Varda's avatar Kenton Varda

Add @dwrensha's canonicalization AFL test case.

I changed it to use TestAllTypes instead of a trivial struct, which will probably get more coverage quicker.
parent 6544785f
......@@ -40,6 +40,8 @@ public:
"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();
}
......@@ -74,6 +76,62 @@ public:
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;
};
......
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