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) { ...@@ -107,19 +107,19 @@ void traverseCatchingExceptions(kj::ArrayPtr<const word> data) {
// Try traversing through Checker. // Try traversing through Checker.
kj::runCatchingExceptions([&]() { kj::runCatchingExceptions([&]() {
FlatArrayMessageReader reader(data); FlatArrayMessageReader reader(data);
KJ_ASSERT(Checker::check(reader) != 0); KJ_ASSERT(Checker::check(reader) != 0) { break; }
}); });
// Try traversing through AnyPointer. // Try traversing through AnyPointer.
kj::runCatchingExceptions([&]() { kj::runCatchingExceptions([&]() {
FlatArrayMessageReader reader(data); FlatArrayMessageReader reader(data);
KJ_ASSERT(traverse(reader.getRoot<AnyPointer>()) != 0); KJ_ASSERT(traverse(reader.getRoot<AnyPointer>()) != 0) { break; }
}); });
// Try counting the size.. // Try counting the size..
kj::runCatchingExceptions([&]() { kj::runCatchingExceptions([&]() {
FlatArrayMessageReader reader(data); 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. // Try copying into a builder, and if that works, traversing it with Checker.
...@@ -128,7 +128,7 @@ void traverseCatchingExceptions(kj::ArrayPtr<const word> data) { ...@@ -128,7 +128,7 @@ void traverseCatchingExceptions(kj::ArrayPtr<const word> data) {
FlatArrayMessageReader reader(data); FlatArrayMessageReader reader(data);
MallocMessageBuilder copyBuilder(buffer); MallocMessageBuilder copyBuilder(buffer);
copyBuilder.setRoot(reader.getRoot<AnyPointer>()); copyBuilder.setRoot(reader.getRoot<AnyPointer>());
KJ_ASSERT(Checker::check(copyBuilder) != 0); KJ_ASSERT(Checker::check(copyBuilder) != 0) { break; }
}); });
} }
......
...@@ -555,11 +555,17 @@ struct WireHelpers { ...@@ -555,11 +555,17 @@ struct WireHelpers {
// object. // object.
ref = pad + 1; ref = pad + 1;
segment = segment->getArena()->tryGetSegment(pad->farRef.segmentId.get()); SegmentReader* newSegment = segment->getArena()->tryGetSegment(pad->farRef.segmentId.get());
KJ_REQUIRE(segment != nullptr, "Message contains double-far pointer to unknown segment.") { 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; return nullptr;
} }
segment = newSegment;
return segment->getStartPtr() + pad->farPositionInSegment(); return segment->getStartPtr() + pad->farPositionInSegment();
} else { } else {
return refTarget; return refTarget;
...@@ -1614,9 +1620,13 @@ struct WireHelpers { ...@@ -1614,9 +1620,13 @@ struct WireHelpers {
char* cptr = reinterpret_cast<char*>(ptr); char* cptr = reinterpret_cast<char*>(ptr);
KJ_REQUIRE(ref->kind() == WirePointer::LIST, 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, 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, size_t size = unbound(subtractChecked(ref->listRef.elementCount() / ELEMENTS, ONE,
[]() { KJ_FAIL_REQUIRE("zero-size blob can't be text (need NUL terminator)"); })); []() { KJ_FAIL_REQUIRE("zero-size blob can't be text (need NUL terminator)"); }));
...@@ -1663,6 +1673,7 @@ struct WireHelpers { ...@@ -1663,6 +1673,7 @@ struct WireHelpers {
WirePointer* ref, word* refTarget, SegmentBuilder* segment, CapTableBuilder* capTable, WirePointer* ref, word* refTarget, SegmentBuilder* segment, CapTableBuilder* capTable,
const void* defaultValue, BlobSize defaultSize)) { const void* defaultValue, BlobSize defaultSize)) {
if (ref->isNull()) { if (ref->isNull()) {
useDefault:
if (defaultSize == ZERO * BYTES) { if (defaultSize == ZERO * BYTES) {
return nullptr; return nullptr;
} else { } else {
...@@ -1674,9 +1685,13 @@ struct WireHelpers { ...@@ -1674,9 +1685,13 @@ struct WireHelpers {
word* ptr = followFars(ref, refTarget, segment); word* ptr = followFars(ref, refTarget, segment);
KJ_REQUIRE(ref->kind() == WirePointer::LIST, 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, 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), return Data::Builder(reinterpret_cast<byte*>(ptr),
unbound(ref->listRef.elementCount() / ELEMENTS)); unbound(ref->listRef.elementCount() / ELEMENTS));
...@@ -2653,13 +2668,13 @@ PointerType PointerReader::getPointerType() const { ...@@ -2653,13 +2668,13 @@ PointerType PointerReader::getPointerType() const {
WireHelpers::followFars(ptr, refTarget, sgmt); WireHelpers::followFars(ptr, refTarget, sgmt);
switch(ptr->kind()) { switch(ptr->kind()) {
case WirePointer::FAR: case WirePointer::FAR:
KJ_FAIL_ASSERT("far pointer not followed?"); KJ_FAIL_ASSERT("far pointer not followed?") { return PointerType::NULL_; }
case WirePointer::STRUCT: case WirePointer::STRUCT:
return PointerType::STRUCT; return PointerType::STRUCT;
case WirePointer::LIST: case WirePointer::LIST:
return PointerType::LIST; return PointerType::LIST;
case WirePointer::OTHER: case WirePointer::OTHER:
KJ_REQUIRE(ptr->isCapability(), "unknown pointer type"); KJ_REQUIRE(ptr->isCapability(), "unknown pointer type") { return PointerType::NULL_; }
return PointerType::CAPABILITY; return PointerType::CAPABILITY;
} }
KJ_UNREACHABLE; 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