feat: fvm: apply a max length when decoding events

This commit is contained in:
Aayush 2023-07-05 11:01:38 -04:00
parent 1358d70128
commit 07965467ee
3 changed files with 41 additions and 28 deletions

View File

@ -1,11 +1,6 @@
package types package types
import ( import (
"bytes"
"fmt"
cbg "github.com/whyrusleeping/cbor-gen"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
) )
@ -38,24 +33,3 @@ type EventEntry struct {
} }
type FilterID [32]byte // compatible with EthHash 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
}

View File

@ -458,7 +458,7 @@ func (vm *FVM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet
} }
if vm.returnEvents && len(ret.EventsBytes) > 0 { if vm.returnEvents && len(ret.EventsBytes) > 0 {
applyRet.Events, err = types.DecodeEvents(ret.EventsBytes) applyRet.Events, err = decodeEvents(ret.EventsBytes)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to decode events returned by the FVM: %w", err) 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 { if vm.returnEvents && len(ret.EventsBytes) > 0 {
applyRet.Events, err = types.DecodeEvents(ret.EventsBytes) applyRet.Events, err = decodeEvents(ret.EventsBytes)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to decode events returned by the FVM: %w", err) return nil, fmt.Errorf("failed to decode events returned by the FVM: %w", err)
} }

39
chain/vm/fvm_util.go Normal file
View File

@ -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
}