Commit 68990bb3 authored by Kenton Varda's avatar Kenton Varda

list.setWithCaveats(i, list[i]) shouldn't corrupt data. Fixes #729.

parent cad2304f
...@@ -1955,6 +1955,19 @@ TEST(Encoding, ListSize) { ...@@ -1955,6 +1955,19 @@ TEST(Encoding, ListSize) {
EXPECT_EQ(structSize.wordCount - shallowSize, listSizes.wordCount); EXPECT_EQ(structSize.wordCount - shallowSize, listSizes.wordCount);
} }
KJ_TEST("list.setWithCaveats(i, list[i]) doesn't corrupt contents") {
MallocMessageBuilder builder;
auto root = builder.initRoot<TestAllTypes>();
auto list = root.initStructList(2);
initTestMessage(list[0]);
list.setWithCaveats(0, list[0]);
checkTestMessage(list[0]);
checkTestMessageAllZero(list[1]);
list.setWithCaveats(1, list[0]);
checkTestMessage(list[0]);
checkTestMessage(list[1]);
}
} // namespace } // namespace
} // namespace _ (private) } // namespace _ (private)
} // namespace capnp } // namespace capnp
...@@ -2853,6 +2853,17 @@ void StructBuilder::transferContentFrom(StructBuilder other) { ...@@ -2853,6 +2853,17 @@ void StructBuilder::transferContentFrom(StructBuilder other) {
void StructBuilder::copyContentFrom(StructReader other) { void StructBuilder::copyContentFrom(StructReader other) {
// Determine the amount of data the builders have in common. // Determine the amount of data the builders have in common.
auto sharedDataSize = kj::min(dataSize, other.dataSize); auto sharedDataSize = kj::min(dataSize, other.dataSize);
auto sharedPointerCount = kj::min(pointerCount, other.pointerCount);
if ((sharedDataSize > ZERO * BITS && other.data == data) ||
(sharedPointerCount > ZERO * POINTERS && other.pointers == pointers)) {
// At least one of the section pointers is pointing to ourself. Verify that the other is two
// (but ignore empty sections).
KJ_ASSERT((sharedDataSize == ZERO * BITS || other.data == data) &&
(sharedPointerCount == ZERO * POINTERS || other.pointers == pointers));
// So `other` appears to be a reader for this same struct. No coping is needed.
return;
}
if (dataSize > sharedDataSize) { if (dataSize > sharedDataSize) {
// Since the target is larger than the source, make sure to zero out the extra bits that the // Since the target is larger than the source, make sure to zero out the extra bits that the
...@@ -2882,7 +2893,6 @@ void StructBuilder::copyContentFrom(StructReader other) { ...@@ -2882,7 +2893,6 @@ void StructBuilder::copyContentFrom(StructReader other) {
WireHelpers::zeroMemory(pointers, pointerCount); WireHelpers::zeroMemory(pointers, pointerCount);
// Copy the pointers. // Copy the pointers.
auto sharedPointerCount = kj::min(pointerCount, other.pointerCount);
for (auto i: kj::zeroTo(sharedPointerCount)) { for (auto i: kj::zeroTo(sharedPointerCount)) {
WireHelpers::copyPointer(segment, capTable, pointers + i, WireHelpers::copyPointer(segment, capTable, pointers + i,
other.segment, other.capTable, other.pointers + i, other.nestingLimit); other.segment, other.capTable, other.pointers + i, other.nestingLimit);
......
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