From f76e2b559ca1e9863000e03740af6de36e0b6dcc Mon Sep 17 00:00:00 2001 From: Jernej Kos Date: Thu, 3 Aug 2023 15:15:04 +0200 Subject: [PATCH] go/common/cbor: Relax CBOR decoding for gRPC/RHP endpoints --- .changelog/5335.bugfix.md | 1 + go/common/cbor/cbor.go | 30 ++++++++++++++++++++++++++++++ go/common/cbor/cbor_test.go | 13 ++++++++++++- go/common/cbor/codec.go | 2 +- go/common/grpc/cbor.go | 2 +- 5 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 .changelog/5335.bugfix.md diff --git a/.changelog/5335.bugfix.md b/.changelog/5335.bugfix.md new file mode 100644 index 00000000000..55f039e1beb --- /dev/null +++ b/.changelog/5335.bugfix.md @@ -0,0 +1 @@ +go/common/cbor: Relax CBOR decoding for gRPC/RHP endpoints diff --git a/go/common/cbor/cbor.go b/go/common/cbor/cbor.go index 971047e973f..b4956659228 100644 --- a/go/common/cbor/cbor.go +++ b/go/common/cbor/cbor.go @@ -53,9 +53,20 @@ var ( MaxMapPairs: 2147483647, // Maximum allowed. } + // decOptionsRPC are decoding options for gRPC endpoints. They are only used when explicitly + // requested by using the UnmarshalRPC method. + decOptionsRPC = cbor.DecOptions{ + DupMapKey: cbor.DupMapKeyEnforcedAPF, + IndefLength: cbor.IndefLengthForbidden, + TagsMd: cbor.TagsForbidden, + MaxArrayElements: 10_000_000, // Usually limited by blob size limits anyway. + MaxMapPairs: 10_000_000, // Usually limited by blob size limits anyway. + } + encMode cbor.EncMode decMode cbor.DecMode decModeTrusted cbor.DecMode + decModeRPC cbor.DecMode ) func init() { @@ -69,6 +80,9 @@ func init() { if decModeTrusted, err = decOptionsTrusted.DecMode(); err != nil { panic(err) } + if decModeRPC, err = decOptionsRPC.DecMode(); err != nil { + panic(err) + } } // Marshal serializes a given type into a CBOR byte vector. @@ -100,6 +114,17 @@ func UnmarshalTrusted(data []byte, dst interface{}) error { return decModeTrusted.Unmarshal(data, dst) } +// UnmarshalRPC deserializes a CBOR byte vector into a given type. +// +// This method is suitable for RPC endpoints as it relaxes some decoding restrictions. +func UnmarshalRPC(data []byte, dst interface{}) error { + if data == nil { + return nil + } + + return decModeRPC.Unmarshal(data, dst) +} + // MustUnmarshal deserializes a CBOR byte vector into a given type. // Panics if unmarshal fails. func MustUnmarshal(data []byte, dst interface{}) { @@ -117,3 +142,8 @@ func NewEncoder(w io.Writer) *cbor.Encoder { func NewDecoder(r io.Reader) *cbor.Decoder { return decMode.NewDecoder(r) } + +// NewDecoderRPC creates a new CBOR decoder with relaxed decoding restrictions. +func NewDecoderRPC(r io.Reader) *cbor.Decoder { + return decModeRPC.NewDecoder(r) +} diff --git a/go/common/cbor/cbor_test.go b/go/common/cbor/cbor_test.go index 0eb0143329c..8feb57e861d 100644 --- a/go/common/cbor/cbor_test.go +++ b/go/common/cbor/cbor_test.go @@ -44,9 +44,17 @@ func TestEncoderDecoder(t *testing.T) { err = dec.Decode(&x) require.NoError(err, "Decode") require.EqualValues(42, x, "decoded value should be correct") + + err = enc.Encode(32) + require.NoError(err, "Encode") + + dec = NewDecoderRPC(&buf) + err = dec.Decode(&x) + require.NoError(err, "Decode") + require.EqualValues(32, x, "decoded value should be correct") } -func TestDecodeUnknowField(t *testing.T) { +func TestDecodeUnknownField(t *testing.T) { require := require.New(t) type a struct { @@ -69,4 +77,7 @@ func TestDecodeUnknowField(t *testing.T) { err = UnmarshalTrusted(raw, &dec) require.NoError(err, "unknown fields from trusted sources should pass") + + err = UnmarshalRPC(raw, &dec) + require.NoError(err, "unknown fields from RPC should pass") } diff --git a/go/common/cbor/codec.go b/go/common/cbor/codec.go index 035b96f39f6..7d902b82929 100644 --- a/go/common/cbor/codec.go +++ b/go/common/cbor/codec.go @@ -56,7 +56,7 @@ func (c *MessageReader) Read(msg interface{}) error { // Decode message bytes. r := io.LimitReader(c.reader, int64(length)) - dec := NewDecoder(r) + dec := NewDecoderRPC(r) if err := dec.Decode(msg); err != nil { return err } diff --git a/go/common/grpc/cbor.go b/go/common/grpc/cbor.go index 27a26830060..912b146b7d0 100644 --- a/go/common/grpc/cbor.go +++ b/go/common/grpc/cbor.go @@ -17,7 +17,7 @@ func (c *CBORCodec) Marshal(v interface{}) ([]byte, error) { } func (c *CBORCodec) Unmarshal(data []byte, v interface{}) error { - return cbor.Unmarshal(data, v) + return cbor.UnmarshalRPC(data, v) } func (c *CBORCodec) Name() string {