From fcfa9432ad3f9b238bb07f0344b2952c4949326c Mon Sep 17 00:00:00 2001 From: Preston Van Loon Date: Sun, 16 Feb 2020 08:35:05 -0800 Subject: [PATCH 1/2] Check attestation bitlist length in aggregation to prevent panic --- beacon-chain/core/helpers/attestation.go | 14 +++++++++- beacon-chain/core/helpers/attestation_test.go | 27 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/beacon-chain/core/helpers/attestation.go b/beacon-chain/core/helpers/attestation.go index a0677568c270..9e5448b400cf 100644 --- a/beacon-chain/core/helpers/attestation.go +++ b/beacon-chain/core/helpers/attestation.go @@ -16,6 +16,10 @@ var ( // ErrAttestationAggregationBitsOverlap is returned when two attestations aggregation // bits overlap with each other. ErrAttestationAggregationBitsOverlap = errors.New("overlapping aggregation bits") + + // ErrAttestationAggregationBitsDifferentLen is returned when two attestation aggregation bits + // have different lengths. + ErrAttestationAggregationBitsDifferentLen = errors.New("different bitlist lengths") ) // AggregateAttestations such that the minimal number of attestations are returned. @@ -32,7 +36,7 @@ func AggregateAttestations(atts []*ethpb.Attestation) ([]*ethpb.Attestation, err } for j := i + 1; j < len(atts); j++ { b := atts[j] - if !a.AggregationBits.Overlaps(b.AggregationBits) { + if a.AggregationBits.Len() == b.AggregationBits.Len() && !a.AggregationBits.Overlaps(b.AggregationBits) { var err error a, err = AggregateAttestation(a, b) if err != nil { @@ -50,6 +54,11 @@ func AggregateAttestations(atts []*ethpb.Attestation) ([]*ethpb.Attestation, err for i, a := range atts { for j := i + 1; j < len(atts); j++ { b := atts[j] + + if a.AggregationBits.Len() != b.AggregationBits.Len() { + continue + } + if a.AggregationBits.Contains(b.AggregationBits) { // If b is fully contained in a, then b can be removed. atts = append(atts[:j], atts[j+1:]...) @@ -74,6 +83,9 @@ var signatureFromBytes = bls.SignatureFromBytes // AggregateAttestation aggregates attestations a1 and a2 together. func AggregateAttestation(a1 *ethpb.Attestation, a2 *ethpb.Attestation) (*ethpb.Attestation, error) { + if a1.AggregationBits.Len() != a2.AggregationBits.Len() { + return nil, ErrAttestationAggregationBitsDifferentLen + } if a1.AggregationBits.Overlaps(a2.AggregationBits) { return nil, ErrAttestationAggregationBitsOverlap } diff --git a/beacon-chain/core/helpers/attestation_test.go b/beacon-chain/core/helpers/attestation_test.go index 4bd3c5d18295..c30e756bac8a 100644 --- a/beacon-chain/core/helpers/attestation_test.go +++ b/beacon-chain/core/helpers/attestation_test.go @@ -62,6 +62,22 @@ func TestAggregateAttestation_OverlapFails(t *testing.T) { } } +func TestAggregateAttestation_DiffLengthFails(t *testing.T) { + tests := []struct { + a1 *ethpb.Attestation + a2 *ethpb.Attestation + }{ + {a1: ðpb.Attestation{AggregationBits: bitfield.Bitlist{0x0F}}, + a2: ðpb.Attestation{AggregationBits: bitfield.Bitlist{0x11}}}, + } + for _, tt := range tests { + _, err := helpers.AggregateAttestation(tt.a1, tt.a2) + if err != helpers.ErrAttestationAggregationBitsDifferentLen { + t.Error("Did not receive wanted error") + } + } +} + func bitlistWithAllBitsSet(length uint64) bitfield.Bitlist { b := bitfield.NewBitlist(length) for i := uint64(0); i < length; i++ { @@ -167,6 +183,17 @@ func TestAggregateAttestations(t *testing.T) { {0b00000011, 0b1}, }, }, + { + name: "two attestations with different bitlist lengths", + inputs: []bitfield.Bitlist{ + {0b00000011, 0b10}, + {0b00000100, 0b1}, + }, + want: []bitfield.Bitlist{ + {0b00000011, 0b10}, + {0b00000100, 0b1}, + }, + }, } var makeAttestationsFromBitlists = func(bl []bitfield.Bitlist) []*ethpb.Attestation { From d5b828fea3f74049b5fda842f73c7fb5b3df1893 Mon Sep 17 00:00:00 2001 From: Preston Van Loon Date: Sun, 16 Feb 2020 08:36:44 -0800 Subject: [PATCH 2/2] Add case for overlap too --- beacon-chain/core/helpers/attestation_test.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/beacon-chain/core/helpers/attestation_test.go b/beacon-chain/core/helpers/attestation_test.go index c30e756bac8a..298d1b83aa6c 100644 --- a/beacon-chain/core/helpers/attestation_test.go +++ b/beacon-chain/core/helpers/attestation_test.go @@ -184,13 +184,15 @@ func TestAggregateAttestations(t *testing.T) { }, }, { - name: "two attestations with different bitlist lengths", + name: "attestations with different bitlist lengths", inputs: []bitfield.Bitlist{ {0b00000011, 0b10}, + {0b00000111, 0b100}, {0b00000100, 0b1}, }, want: []bitfield.Bitlist{ {0b00000011, 0b10}, + {0b00000111, 0b100}, {0b00000100, 0b1}, }, },