Setting a field in the data section of an unmarshaled struct created with a previous version that did not have any data section fields panics
xortive opened this issue · comments
@0xbf613bdc8c0f6ae4;
struct OldStruct @0xee1b66e79b51bbbf { # 0 bytes, 2 ptrs
foo @0 :Data; # ptr[0]
bar @1 :Data; # ptr[1]
}
struct NewStruct @0xb78a3d22d4285878 { # 8 bytes, 2 ptrs
foo @0 :Data; # ptr[0]
bar @1 :Data; # ptr[1]
newField @2 :Bool; # bits[0, 1)
}
If one were to serialize OldStruct
with go-capnp
, deserialize it, and set newField
, it will panic here:
Line 201 in 0d218d2
I think go-capnp
should allocate a data section in this scenario to match the C++ implementation.
reproduction test:
func TestDataSectionBug(t *testing.T) {
arena := capnp.SingleSegment(nil)
oldMsg, seg, err := capnp.NewMessage(arena)
assert.NoError(t, err)
oldStruct, err := schema.NewOldStruct(seg)
assert.NoError(t, err)
err = oldStruct.SetFoo([]byte{255, 255})
assert.NoError(t, err)
err = oldStruct.SetFoo([]byte{127, 127})
assert.NoError(t, err)
oldSerialized, err := oldMsg.Marshal()
assert.NoError(t, err)
newMsg, err := capnp.Unmarshal(oldSerialized)
assert.NoError(t, err)
newStruct, err := schema.ReadRootNewStruct(newMsg)
assert.NoError(t, err)
newStruct.SetNewField(true) // panics
}