diff --git a/proto/engine/v1/electra.go b/proto/engine/v1/electra.go index 18f47e181f9..85cc6453915 100644 --- a/proto/engine/v1/electra.go +++ b/proto/engine/v1/electra.go @@ -29,27 +29,37 @@ func (ebe *ExecutionBundleElectra) GetDecodedExecutionRequests() (*ExecutionRequ requests := &ExecutionRequests{} var prevTypeNum uint8 for i := range ebe.ExecutionRequests { - requestType := ebe.ExecutionRequests[i][0] - // Requests must be sorted in ascending order by request type. + requestType, requestListInSSZBytes, err := decodeExecutionRequest(ebe.ExecutionRequests[i]) + if err != nil { + return nil, err + } if prevTypeNum > requestType { return nil, errors.New("invalid execution request type order, requests should be in sorted order") } prevTypeNum = requestType - requestListInSSZBytes := ebe.ExecutionRequests[i][1:] switch requestType { case depositRequestType: + if len(requestListInSSZBytes) < drSize { + return nil, errors.New("invalid deposit request length, requests should be at least the size of 1 request") + } drs, err := unmarshalItems(requestListInSSZBytes, drSize, func() *DepositRequest { return &DepositRequest{} }) if err != nil { return nil, err } requests.Deposits = drs case withdrawalRequestType: + if len(requestListInSSZBytes) < wrSize { + return nil, errors.New("invalid withdrawal request length, requests should be at least the size of 1 request") + } wrs, err := unmarshalItems(requestListInSSZBytes, wrSize, func() *WithdrawalRequest { return &WithdrawalRequest{} }) if err != nil { return nil, err } requests.Withdrawals = wrs case consolidationRequestType: + if len(requestListInSSZBytes) < crSize { + return nil, errors.New("invalid consolidations request length, requests should be at least the size of 1 request") + } crs, err := unmarshalItems(requestListInSSZBytes, crSize, func() *ConsolidationRequest { return &ConsolidationRequest{} }) if err != nil { return nil, err @@ -59,10 +69,16 @@ func (ebe *ExecutionBundleElectra) GetDecodedExecutionRequests() (*ExecutionRequ return nil, errors.Errorf("unsupported request type %d", requestType) } } - return requests, nil } +func decodeExecutionRequest(req []byte) (typ uint8, data []byte, err error) { + if len(req) < 1 { + return 0, nil, errors.New("invalid execution request, length less than 1") + } + return req[0], req[1:], nil +} + func EncodeExecutionRequests(requests *ExecutionRequests) ([]hexutil.Bytes, error) { if requests == nil { return nil, errors.New("invalid execution requests") diff --git a/proto/engine/v1/electra_test.go b/proto/engine/v1/electra_test.go index c79250e3c86..490a50e3f85 100644 --- a/proto/engine/v1/electra_test.go +++ b/proto/engine/v1/electra_test.go @@ -47,6 +47,33 @@ func TestGetDecodedExecutionRequests(t *testing.T) { _, err = ebe.GetDecodedExecutionRequests() require.ErrorContains(t, "invalid execution request type order", err) }) + t.Run("Requests should error if it's shorter than 1 byte", func(t *testing.T) { + depositRequestBytes, err := hexutil.Decode("0x610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + "620000000000000000000000000000000000000000000000000000000000000000" + + "4059730700000063000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000000000000000000000000000000000000000000000000000") + require.NoError(t, err) + consolidationRequestBytes, err := hexutil.Decode("0x6600000000000000000000000000000000000000" + + "670000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + "680000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") + require.NoError(t, err) + ebe := &enginev1.ExecutionBundleElectra{ + ExecutionRequests: [][]byte{append([]byte{}, depositRequestBytes...), append([]byte{2}, consolidationRequestBytes...)}, + } + _, err = ebe.GetDecodedExecutionRequests() + require.ErrorContains(t, "invalid execution request, length less than 1", err) + }) + t.Run("If a request type is provided, but the request list is shorter than the ssz of 1 request we error", func(t *testing.T) { + consolidationRequestBytes, err := hexutil.Decode("0x6600000000000000000000000000000000000000" + + "670000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + "680000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") + require.NoError(t, err) + ebe := &enginev1.ExecutionBundleElectra{ + ExecutionRequests: [][]byte{append([]byte{0}, []byte{}...), append([]byte{2}, consolidationRequestBytes...)}, + } + _, err = ebe.GetDecodedExecutionRequests() + require.ErrorContains(t, "invalid deposit request length", err) + }) } func TestEncodeExecutionRequests(t *testing.T) {