From 07965467ee1d521871594bbd330083d964b85002 Mon Sep 17 00:00:00 2001 From: Aayush Date: Wed, 5 Jul 2023 11:01:38 -0400 Subject: [PATCH] feat: fvm: apply a max length when decoding events --- chain/types/event.go | 26 -------------------------- chain/vm/fvm.go | 4 ++-- chain/vm/fvm_util.go | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 28 deletions(-) create mode 100644 chain/vm/fvm_util.go diff --git a/chain/types/event.go b/chain/types/event.go index 91b0e95d3..106a120e2 100644 --- a/chain/types/event.go +++ b/chain/types/event.go @@ -1,11 +1,6 @@ package types import ( - "bytes" - "fmt" - - cbg "github.com/whyrusleeping/cbor-gen" - "github.com/filecoin-project/go-state-types/abi" ) @@ -38,24 +33,3 @@ type EventEntry struct { } type FilterID [32]byte // compatible with EthHash - -// DecodeEvents decodes a CBOR list of CBOR-encoded events. -func DecodeEvents(input []byte) ([]Event, error) { - r := bytes.NewReader(input) - typ, len, err := cbg.NewCborReader(r).ReadHeader() - if err != nil { - return nil, fmt.Errorf("failed to read events: %w", err) - } - if typ != cbg.MajArray { - return nil, fmt.Errorf("expected a CBOR list, was major type %d", typ) - } - events := make([]Event, 0, len) - for i := 0; i < int(len); i++ { - var evt Event - if err := evt.UnmarshalCBOR(r); err != nil { - return nil, fmt.Errorf("failed to parse event: %w", err) - } - events = append(events, evt) - } - return events, nil -} diff --git a/chain/vm/fvm.go b/chain/vm/fvm.go index 7c79972c7..0efaa6302 100644 --- a/chain/vm/fvm.go +++ b/chain/vm/fvm.go @@ -458,7 +458,7 @@ func (vm *FVM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet } if vm.returnEvents && len(ret.EventsBytes) > 0 { - applyRet.Events, err = types.DecodeEvents(ret.EventsBytes) + applyRet.Events, err = decodeEvents(ret.EventsBytes) if err != nil { return nil, fmt.Errorf("failed to decode events returned by the FVM: %w", err) } @@ -514,7 +514,7 @@ func (vm *FVM) ApplyImplicitMessage(ctx context.Context, cmsg *types.Message) (* } if vm.returnEvents && len(ret.EventsBytes) > 0 { - applyRet.Events, err = types.DecodeEvents(ret.EventsBytes) + applyRet.Events, err = decodeEvents(ret.EventsBytes) if err != nil { return nil, fmt.Errorf("failed to decode events returned by the FVM: %w", err) } diff --git a/chain/vm/fvm_util.go b/chain/vm/fvm_util.go new file mode 100644 index 000000000..9f3dfd869 --- /dev/null +++ b/chain/vm/fvm_util.go @@ -0,0 +1,39 @@ +package vm + +import ( + "bytes" + "fmt" + + cbg "github.com/whyrusleeping/cbor-gen" + + "github.com/filecoin-project/lotus/chain/types" +) + +const MaxEventSliceLength = 6_000_000 + +// DecodeEvents decodes a CBOR list of CBOR-encoded events. +func decodeEvents(input []byte) ([]types.Event, error) { + r := bytes.NewReader(input) + typ, length, err := cbg.NewCborReader(r).ReadHeader() + if err != nil { + return nil, fmt.Errorf("failed to read events: %w", err) + } + + if length > MaxEventSliceLength { + log.Errorf("extremely long event slice (len %d) returned, not decoding", length) + return nil, nil + } + + if typ != cbg.MajArray { + return nil, fmt.Errorf("expected a CBOR list, was major type %d", typ) + } + events := make([]types.Event, 0, length) + for i := 0; i < int(length); i++ { + var evt types.Event + if err := evt.UnmarshalCBOR(r); err != nil { + return nil, fmt.Errorf("failed to parse event: %w", err) + } + events = append(events, evt) + } + return events, nil +}