OpenAtomFoundation / xupercore

The kernel of xuperchain.
Apache License 2.0
61 stars 47 forks source link

network: panic on marshal protobuf message #251

Closed icexin closed 2 years ago

icexin commented 3 years ago

xupercore version: https://github.com/xuperchain/xupercore/commit/cb95ad3570b2e52cf602f1332be0ec2ffa20d291 go version: go version go1.16.5 linux/amd64

output:

[node2] panic: runtime error: invalid memory address or nil pointer dereference                                                                                                       [9/1935]
[node2] [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x476ce7]
[node2] 
[node2] goroutine 608920341 [running]:
[node2] google.golang.org/protobuf/encoding/protowire.AppendBytes(...)
[node2]         /home/fanbingxin/go/pkg/mod/google.golang.org/protobuf@v1.26.0-rc.1/encoding/protowire/wire.go:426
[node2] google.golang.org/protobuf/internal/impl.appendBytesNoZero(0xc001744000, 0x268, 0x270, 0xc0458addf0, 0xc0002ba218, 0xc003733502, 0xc001744000, 0x246, 0x270, 0x0, ...)
[node2]         /home/fanbingxin/go/pkg/mod/google.golang.org/protobuf@v1.26.0-rc.1/internal/impl/codec_gen.go:5396 +0xec
[node2] google.golang.org/protobuf/internal/impl.(*MessageInfo).marshalAppendPointer(0xc0002b69a0, 0xc001744000, 0x3, 0x270, 0xc0458adce0, 0x70c802, 0x1768900, 0xc0458addd0, 0x195, 0xc00188e
320, ...)
[node2]         /home/fanbingxin/go/pkg/mod/google.golang.org/protobuf@v1.26.0-rc.1/internal/impl/encode.go:139 +0x107
[node2] google.golang.org/protobuf/internal/impl.(*MessageInfo).marshal(0xc0002b69a0, 0x1da04d8, 0xc126dca390, 0xc001744000, 0x3, 0x270, 0x2, 0xc0002b69a0, 0x1da04d8, 0xc126dca390, ...)
[node2]         /home/fanbingxin/go/pkg/mod/google.golang.org/protobuf@v1.26.0-rc.1/internal/impl/encode.go:107 +0x8d
[node2] google.golang.org/protobuf/proto.MarshalOptions.marshal(0xc126010001, 0xc001744000, 0x3, 0x270, 0x1da04d8, 0xc126dca390, 0x677975, 0xc126000000, 0x1da04d8, 0xc126dca390, ...)
[node2]         /home/fanbingxin/go/pkg/mod/google.golang.org/protobuf@v1.26.0-rc.1/proto/encode.go:163 +0x25e
[node2] google.golang.org/protobuf/proto.MarshalOptions.MarshalAppend(0xc001010001, 0xc001744000, 0x3, 0x270, 0x1d605e0, 0xc126dca390, 0x270, 0x400, 0x7f2b37082300, 0x20300000000000, ...)
[node2]         /home/fanbingxin/go/pkg/mod/google.golang.org/protobuf@v1.26.0-rc.1/proto/encode.go:122 +0x98
[node2] google.golang.org/protobuf/internal/impl.appendMessageSlice(0xc001744000, 0x1, 0x270, 0xc006fbe200, 0xa, 0x1da4ae0, 0x1976520, 0x2, 0xc003733870, 0x41c553, ...)
[node2]         /home/fanbingxin/go/pkg/mod/google.golang.org/protobuf@v1.26.0-rc.1/internal/impl/codec_field.go:541 +0x21a
[node2] google.golang.org/protobuf/internal/impl.makeMessageSliceFieldCoder.func2(0xc001744000, 0x0, 0x270, 0xc006fbe200, 0xc00d209680, 0x41bc02, 0x296f3e8, 0x296f3e8, 0xc006fbe200, 0x1da4ae
0, ...)
[node2]         /home/fanbingxin/go/pkg/mod/google.golang.org/protobuf@v1.26.0-rc.1/internal/impl/codec_field.go:457 +0x85
[node2] google.golang.org/protobuf/internal/impl.(*MessageInfo).marshalAppendPointer(0xc000481340, 0xc001744000, 0x0, 0x270, 0xc006fbe200, 0xc000aa8102, 0xc001744000, 0x7f2acd9e64d0, 0xc0004
81301, 0x10100c006fbe200, ...)
[node2]         /home/fanbingxin/go/pkg/mod/google.golang.org/protobuf@v1.26.0-rc.1/internal/impl/encode.go:139 +0x107
[node2] google.golang.org/protobuf/internal/impl.(*MessageInfo).marshal(0xc000481340, 0x1da04d8, 0xc126dca350, 0xc001744000, 0x0, 0x270, 0x2, 0x4547cc, 0x270, 0x16de060, ...)
[node2]         /home/fanbingxin/go/pkg/mod/google.golang.org/protobuf@v1.26.0-rc.1/internal/impl/encode.go:107 +0x8d
[node2] google.golang.org/protobuf/proto.MarshalOptions.marshal(0xc126000001, 0x0, 0x0, 0x0, 0x1da04d8, 0xc126dca350, 0xc126dca350, 0x1da04d8, 0xc126dca350, 0x18b67e0, ...)
[node2]         /home/fanbingxin/go/pkg/mod/google.golang.org/protobuf@v1.26.0-rc.1/proto/encode.go:163 +0x25e
[node2] google.golang.org/protobuf/proto.MarshalOptions.MarshalAppend(0x1000001, 0x0, 0x0, 0x0, 0x1d605e0, 0xc126dca350, 0x7f2b5dafad28, 0x40, 0xc006fbe2c0, 0x2, ...)
[node2]         /home/fanbingxin/go/pkg/mod/google.golang.org/protobuf@v1.26.0-rc.1/proto/encode.go:122 +0x98
[node2] github.com/golang/protobuf/proto.marshalAppend(0x0, 0x0, 0x0, 0x1d82e08, 0xc006fbe200, 0x411a00, 0x18, 0x17d7e40, 0x450701, 0xc0a802c2b8, ...)
[node2]         /home/fanbingxin/go/pkg/mod/github.com/golang/protobuf@v1.4.3/proto/wire.go:40 +0xdc
[node2] github.com/golang/protobuf/proto.Marshal(...)
[node2]         /home/fanbingxin/go/pkg/mod/github.com/golang/protobuf@v1.4.3/proto/wire.go:23
[node2] github.com/xuperchain/xupercore/kernel/network/p2p.NewMessage(0x1b, 0x1d82e08, 0xc006fbe200, 0xc003733c70, 0x3, 0x3, 0xc004e98c00)
[node2]         /home/fanbingxin/go/src/github.com/xuperchain/xupercore/kernel/network/p2p/message.go:44 +0x1b2
[node2] github.com/xuperchain/xupercore/kernel/engines/xuperos/net.(*NetEvent).handleGetBlockHeaders.func2(0x0, 0x0, 0x0, 0xc054de2340, 0xc0ece0e330)
[node2]         /home/fanbingxin/go/src/github.com/xuperchain/xupercore/kernel/engines/xuperos/net/net_event.go:354 +0x185
[node2] github.com/xuperchain/xupercore/kernel/engines/xuperos/net.(*NetEvent).handleGetBlockHeaders(0xc00015f6e0, 0x1d94108, 0xc0ece0e300, 0xc065624630, 0x0, 0x0, 0x0)
[node2]         /home/fanbingxin/go/src/github.com/xuperchain/xupercore/kernel/engines/xuperos/net/net_event.go:422 +0x907
[node2] github.com/xuperchain/xupercore/kernel/network/p2p.(*subscriber).HandleMessage(0xc0008fb540, 0x1d94108, 0xc0ece0e2a0, 0xc065624630, 0x1d5f5e0, 0xc000ab2640, 0x0, 0x0)
[node2]         /home/fanbingxin/go/src/github.com/xuperchain/xupercore/kernel/network/p2p/subscriber.go:126 +0x4d4
[node2] github.com/xuperchain/xupercore/kernel/network/p2p.(*dispatcher).Dispatch.func2(0xc081372180, 0xc0ece0e2a0, 0xc065624630, 0x1d5f5e0, 0xc000ab2640, 0xc0014d6be0, 0x1d82f88, 0xc0008fb5
40)
icexin commented 2 years ago

这段代码可以快速复现,原因在于缓存里面的block消息被修改了NextHash字段,于此同时另外一个协程在序列化block

func TestBrokenMessage(t *testing.T) {
    for {
        wg := sync.WaitGroup{}
        wg.Add(2)
        msg := new(pb.InternalBlock)
        go func() {
            defer wg.Done()
            proto.Marshal(msg)
        }()
        go func() {
            defer wg.Done()
            msg.NextHash = []byte{'a'}
        }()
        wg.Wait()
    }
}