Commit 41c15b12 authored by Kenton Varda's avatar Kenton Varda

Fix fuzz-test with -fno-exceptions.

This includes making builders a little more tolerant of corrupt data. Note that our threat model generally does not expect this tolerance -- we expect that builders always contain either structures created locally or copied in from a reader, which does a certain amount of validation in itself.
parent 9aabfdbe
......@@ -107,19 +107,19 @@ void traverseCatchingExceptions(kj::ArrayPtr<const word> data) {
// Try traversing through Checker.
kj::runCatchingExceptions([&]() {
FlatArrayMessageReader reader(data);
KJ_ASSERT(Checker::check(reader) != 0);
KJ_ASSERT(Checker::check(reader) != 0) { break; }
});
// Try traversing through AnyPointer.
kj::runCatchingExceptions([&]() {
FlatArrayMessageReader reader(data);
KJ_ASSERT(traverse(reader.getRoot<AnyPointer>()) != 0);
KJ_ASSERT(traverse(reader.getRoot<AnyPointer>()) != 0) { break; }
});
// Try counting the size..
kj::runCatchingExceptions([&]() {
FlatArrayMessageReader reader(data);
KJ_ASSERT(reader.getRoot<AnyPointer>().targetSize().wordCount != 0);
KJ_ASSERT(reader.getRoot<AnyPointer>().targetSize().wordCount != 0) { break; }
});
// Try copying into a builder, and if that works, traversing it with Checker.
......@@ -128,7 +128,7 @@ void traverseCatchingExceptions(kj::ArrayPtr<const word> data) {
FlatArrayMessageReader reader(data);
MallocMessageBuilder copyBuilder(buffer);
copyBuilder.setRoot(reader.getRoot<AnyPointer>());
KJ_ASSERT(Checker::check(copyBuilder) != 0);
KJ_ASSERT(Checker::check(copyBuilder) != 0) { break; }
});
}
......
......@@ -555,11 +555,17 @@ struct WireHelpers {
// object.
ref = pad + 1;
segment = segment->getArena()->tryGetSegment(pad->farRef.segmentId.get());
KJ_REQUIRE(segment != nullptr, "Message contains double-far pointer to unknown segment.") {
SegmentReader* newSegment = segment->getArena()->tryGetSegment(pad->farRef.segmentId.get());
KJ_REQUIRE(newSegment != nullptr,
"Message contains double-far pointer to unknown segment.") {
return nullptr;
}
KJ_REQUIRE(pad->kind() == WirePointer::FAR,
"Second word of double-far pad must be far pointer.") {
return nullptr;
}
segment = newSegment;
return segment->getStartPtr() + pad->farPositionInSegment();
} else {
return refTarget;
......@@ -1614,9 +1620,13 @@ struct WireHelpers {
char* cptr = reinterpret_cast<char*>(ptr);
KJ_REQUIRE(ref->kind() == WirePointer::LIST,
"Called getText{Field,Element}() but existing pointer is not a list.");
"Called getText{Field,Element}() but existing pointer is not a list.") {
goto useDefault;
}
KJ_REQUIRE(ref->listRef.elementSize() == ElementSize::BYTE,
"Called getText{Field,Element}() but existing list pointer is not byte-sized.");
"Called getText{Field,Element}() but existing list pointer is not byte-sized.") {
goto useDefault;
}
size_t size = unbound(subtractChecked(ref->listRef.elementCount() / ELEMENTS, ONE,
[]() { KJ_FAIL_REQUIRE("zero-size blob can't be text (need NUL terminator)"); }));
......@@ -1663,6 +1673,7 @@ struct WireHelpers {
WirePointer* ref, word* refTarget, SegmentBuilder* segment, CapTableBuilder* capTable,
const void* defaultValue, BlobSize defaultSize)) {
if (ref->isNull()) {
useDefault:
if (defaultSize == ZERO * BYTES) {
return nullptr;
} else {
......@@ -1674,9 +1685,13 @@ struct WireHelpers {
word* ptr = followFars(ref, refTarget, segment);
KJ_REQUIRE(ref->kind() == WirePointer::LIST,
"Called getData{Field,Element}() but existing pointer is not a list.");
"Called getData{Field,Element}() but existing pointer is not a list.") {
goto useDefault;
}
KJ_REQUIRE(ref->listRef.elementSize() == ElementSize::BYTE,
"Called getData{Field,Element}() but existing list pointer is not byte-sized.");
"Called getData{Field,Element}() but existing list pointer is not byte-sized.") {
goto useDefault;
}
return Data::Builder(reinterpret_cast<byte*>(ptr),
unbound(ref->listRef.elementCount() / ELEMENTS));
......@@ -2653,13 +2668,13 @@ PointerType PointerReader::getPointerType() const {
WireHelpers::followFars(ptr, refTarget, sgmt);
switch(ptr->kind()) {
case WirePointer::FAR:
KJ_FAIL_ASSERT("far pointer not followed?");
KJ_FAIL_ASSERT("far pointer not followed?") { return PointerType::NULL_; }
case WirePointer::STRUCT:
return PointerType::STRUCT;
case WirePointer::LIST:
return PointerType::LIST;
case WirePointer::OTHER:
KJ_REQUIRE(ptr->isCapability(), "unknown pointer type");
KJ_REQUIRE(ptr->isCapability(), "unknown pointer type") { return PointerType::NULL_; }
return PointerType::CAPABILITY;
}
KJ_UNREACHABLE;
......
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