Commit 26af52ab authored by Kenton Varda's avatar Kenton Varda

Fix memory corruption bug caused by an overrun when zeroing empty struct lists.

parent b8d76f57
......@@ -444,6 +444,7 @@ struct WireHelpers {
for (uint i = 0; i < count; i++) {
zeroObject(segment, reinterpret_cast<WirePointer*>(ptr) + i);
}
memset(ptr, 0, POINTER_SIZE_IN_WORDS * count * BYTES_PER_WORD / BYTES);
break;
}
case FieldSize::INLINE_COMPOSITE: {
......@@ -465,7 +466,7 @@ struct WireHelpers {
}
}
memset(ptr, 0, (elementTag->structRef.wordSize() + POINTER_SIZE_IN_WORDS)
memset(ptr, 0, (elementTag->structRef.wordSize() * count + POINTER_SIZE_IN_WORDS)
* BYTES_PER_WORD / BYTES);
break;
}
......
......@@ -474,6 +474,151 @@ TEST(Orphans, OrphanageFromBuilder) {
}
}
static bool allZero(const word* begin, const word* end) {
for (const byte* pos = reinterpret_cast<const byte*>(begin);
pos < reinterpret_cast<const byte*>(end); ++pos) {
if (*pos != 0) return false;
}
return true;
}
TEST(Orphans, StructsZerodAfterUse) {
MallocMessageBuilder builder;
auto root = builder.initRoot<TestAllTypes>();
const word* zerosStart = builder.getSegmentsForOutput()[0].end();
initTestMessage(root.initStructField());
const word* zerosEnd = builder.getSegmentsForOutput()[0].end();
root.setTextField("foo"); // guard against overruns
EXPECT_EQ(1u, builder.getSegmentsForOutput().size()); // otherwise test is invalid
root.disownStructField();
EXPECT_TRUE(allZero(zerosStart, zerosEnd));
EXPECT_EQ("foo", root.getTextField());
}
TEST(Orphans, ListsZerodAfterUse) {
MallocMessageBuilder builder;
auto root = builder.initRoot<TestAllTypes>();
const word* zerosStart = builder.getSegmentsForOutput()[0].end();
root.setUInt32List({12, 34, 56});
const word* zerosEnd = builder.getSegmentsForOutput()[0].end();
root.setTextField("foo"); // guard against overruns
EXPECT_EQ(1u, builder.getSegmentsForOutput().size()); // otherwise test is invalid
root.disownUInt32List();
EXPECT_TRUE(allZero(zerosStart, zerosEnd));
EXPECT_EQ("foo", root.getTextField());
}
TEST(Orphans, EmptyListsZerodAfterUse) {
MallocMessageBuilder builder;
auto root = builder.initRoot<TestAllTypes>();
const word* zerosStart = builder.getSegmentsForOutput()[0].end();
root.initUInt32List(0);
const word* zerosEnd = builder.getSegmentsForOutput()[0].end();
root.setTextField("foo"); // guard against overruns
EXPECT_EQ(1u, builder.getSegmentsForOutput().size()); // otherwise test is invalid
root.disownUInt32List();
EXPECT_TRUE(allZero(zerosStart, zerosEnd));
EXPECT_EQ("foo", root.getTextField());
}
TEST(Orphans, StructListsZerodAfterUse) {
MallocMessageBuilder builder;
auto root = builder.initRoot<TestAllTypes>();
const word* zerosStart = builder.getSegmentsForOutput()[0].end();
{
auto list = root.initStructList(2);
initTestMessage(list[0]);
initTestMessage(list[1]);
}
const word* zerosEnd = builder.getSegmentsForOutput()[0].end();
root.setTextField("foo"); // guard against overruns
EXPECT_EQ(1u, builder.getSegmentsForOutput().size()); // otherwise test is invalid
root.disownStructList();
EXPECT_TRUE(allZero(zerosStart, zerosEnd));
EXPECT_EQ("foo", root.getTextField());
}
TEST(Orphans, EmptyStructListsZerodAfterUse) {
MallocMessageBuilder builder;
auto root = builder.initRoot<TestAllTypes>();
const word* zerosStart = builder.getSegmentsForOutput()[0].end();
root.initStructList(0);
const word* zerosEnd = builder.getSegmentsForOutput()[0].end();
root.setTextField("foo"); // guard against overruns
EXPECT_EQ(1u, builder.getSegmentsForOutput().size()); // otherwise test is invalid
root.disownStructList();
EXPECT_TRUE(allZero(zerosStart, zerosEnd));
EXPECT_EQ("foo", root.getTextField());
}
TEST(Orphans, TextZerodAfterUse) {
MallocMessageBuilder builder;
auto root = builder.initRoot<TestAllTypes>();
const word* zerosStart = builder.getSegmentsForOutput()[0].end();
root.setTextField("abcd123");
const word* zerosEnd = builder.getSegmentsForOutput()[0].end();
root.setDataField(data("foo")); // guard against overruns
EXPECT_EQ(1u, builder.getSegmentsForOutput().size()); // otherwise test is invalid
root.disownTextField();
EXPECT_TRUE(allZero(zerosStart, zerosEnd));
EXPECT_EQ(data("foo"), root.getDataField());
}
TEST(Orphans, DataZerodAfterUse) {
MallocMessageBuilder builder;
auto root = builder.initRoot<TestAllTypes>();
const word* zerosStart = builder.getSegmentsForOutput()[0].end();
root.setDataField(data("abcd123"));
const word* zerosEnd = builder.getSegmentsForOutput()[0].end();
root.setTextField("foo"); // guard against overruns
EXPECT_EQ(1u, builder.getSegmentsForOutput().size()); // otherwise test is invalid
root.disownDataField();
EXPECT_TRUE(allZero(zerosStart, zerosEnd));
EXPECT_EQ("foo", root.getTextField());
}
} // namespace
} // namespace _ (private)
} // namespace capnp
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