From aae7660410f0ef90279e14afaaf2f429fdc2a186 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Thu, 11 Mar 2021 15:09:25 +0100 Subject: [PATCH] p2p/enr: fix decoding of incomplete lists (#22484) Given a list of less than two elements DecodeRLP returned rlp.EOL, leading to issues in outer decoders. --- p2p/enr/enr.go | 7 +++++++ p2p/enr/enr_test.go | 23 +++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/p2p/enr/enr.go b/p2p/enr/enr.go index c36ae9e3ed..05e43fd805 100644 --- a/p2p/enr/enr.go +++ b/p2p/enr/enr.go @@ -50,6 +50,7 @@ var ( errNotSorted = errors.New("record key/value pairs are not sorted by key") errDuplicateKey = errors.New("record contains duplicate key") errIncompletePair = errors.New("record contains incomplete k/v pair") + errIncompleteList = errors.New("record contains less than two list elements") errTooBig = fmt.Errorf("record bigger than %d bytes", SizeLimit) errEncodeUnsigned = errors.New("can't encode unsigned record") errNotFound = errors.New("no such key in record") @@ -209,9 +210,15 @@ func decodeRecord(s *rlp.Stream) (dec Record, raw []byte, err error) { return dec, raw, err } if err = s.Decode(&dec.signature); err != nil { + if err == rlp.EOL { + err = errIncompleteList + } return dec, raw, err } if err = s.Decode(&dec.seq); err != nil { + if err == rlp.EOL { + err = errIncompleteList + } return dec, raw, err } // The rest of the record contains sorted k/v pairs. diff --git a/p2p/enr/enr_test.go b/p2p/enr/enr_test.go index 96a9ced5cf..bf3f104744 100644 --- a/p2p/enr/enr_test.go +++ b/p2p/enr/enr_test.go @@ -231,6 +231,29 @@ func TestRecordTooBig(t *testing.T) { require.NoError(t, signTest([]byte{5}, &r)) } +// This checks that incomplete RLP inputs are handled correctly. +func TestDecodeIncomplete(t *testing.T) { + type decTest struct { + input []byte + err error + } + tests := []decTest{ + {[]byte{0xC0}, errIncompleteList}, + {[]byte{0xC1, 0x1}, errIncompleteList}, + {[]byte{0xC2, 0x1, 0x2}, nil}, + {[]byte{0xC3, 0x1, 0x2, 0x3}, errIncompletePair}, + {[]byte{0xC4, 0x1, 0x2, 0x3, 0x4}, nil}, + {[]byte{0xC5, 0x1, 0x2, 0x3, 0x4, 0x5}, errIncompletePair}, + } + for _, test := range tests { + var r Record + err := rlp.DecodeBytes(test.input, &r) + if err != test.err { + t.Errorf("wrong error for %X: %v", test.input, err) + } + } +} + // TestSignEncodeAndDecodeRandom tests encoding/decoding of records containing random key/value pairs. func TestSignEncodeAndDecodeRandom(t *testing.T) { var r Record