Commit b32a53bd authored by Kenton Varda's avatar Kenton Varda

Fix bug where capability pointers were corrupted when 'transferred', e.g. using…

Fix bug where capability pointers were corrupted when 'transferred', e.g. using adoptWithCaveats() or truncate().
parent eae03397
......@@ -960,6 +960,30 @@ TEST(Capability, ThisCap) {
EXPECT_EQ(-1, callCount);
}
TEST(Capability, TransferCap) {
kj::EventLoop loop;
kj::WaitScope waitScope(loop);
MallocMessageBuilder message;
auto root = message.initRoot<test::TestTransferCap>();
auto orphan = message.getOrphanage().newOrphan<test::TestTransferCap::Element>();
auto e = orphan.get();
e.setText("foo");
e.setCap(KJ_EXCEPTION(FAILED, "whatever"));
root.initList(1).adoptWithCaveats(0, kj::mv(orphan));
// This line used to throw due to capability pointers being incorrectly transferred.
auto cap = root.getList()[0].getCap();
cap.whenResolved().then([]() {
KJ_FAIL_EXPECT("didn't throw?");
}, [](kj::Exception&&) {
// success
}).wait(waitScope);
}
} // namespace
} // namespace _
} // namespace capnp
......@@ -868,11 +868,11 @@ struct WireHelpers {
if (src->isNull()) {
memset(dst, 0, sizeof(WirePointer));
} else if (src->kind() == WirePointer::FAR) {
// Far pointers are position-independent, so we can just copy.
memcpy(dst, src, sizeof(WirePointer));
} else {
} else if (src->isPositional()) {
transferPointer(dstSegment, dst, srcSegment, src, src->target());
} else {
// Far and other pointers are position-independent, so we can just copy.
memcpy(dst, src, sizeof(WirePointer));
}
}
......@@ -2884,7 +2884,7 @@ bool OrphanBuilder::truncate(ElementCount size, bool isText) {
tag->setKindAndInlineCompositeListElementCount(WirePointer::STRUCT, size);
segment->tryTruncate(oldEndWord, newEndWord);
} else if (newEndWord <= oldEndWord) {
// Apparently the old list was over-allecated? The word count is more than needed to store
// Apparently the old list was over-allocated? The word count is more than needed to store
// the elements. This is "valid" but shouldn't happen in practice unless someone is toying
// with us.
word* expectedEnd = target + oldSize * (elementWordCount / ELEMENTS);
......@@ -2898,7 +2898,6 @@ bool OrphanBuilder::truncate(ElementCount size, bool isText) {
tag->setKindAndInlineCompositeListElementCount(WirePointer::STRUCT, size);
} else {
// Need to re-allocate and transfer.
StructSize structSize(tag->structRef.dataSize.get(), tag->structRef.ptrCount.get());
OrphanBuilder replacement = initStructList(segment->getArena(), size, structSize);
ListBuilder newList = replacement.asStructList(structSize);
......
......@@ -786,6 +786,14 @@ interface TestMoreStuff extends(TestCallOrder) {
# this can be used to test garbage collection.
}
struct TestTransferCap {
list @0 :List(Element);
struct Element {
text @0 :Text;
cap @1 :TestInterface;
}
}
interface TestKeywordMethods {
delete @0 ();
class @1 ();
......
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