go-capnp
go-capnp copied to clipboard
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
@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: https://github.com/capnproto/go-capnp/blob/0d218d2660ffa094198d7aba689c4eb04ff6ae18/struct.go#L201
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
}