From cc5a18678f7c1fdc945952145dcdd2b1bb03251a Mon Sep 17 00:00:00 2001 From: Ben Luddy Date: Mon, 10 Jun 2024 11:46:01 -0400 Subject: [PATCH] Disable recognition of Binary(Unm|M)arshaler in CBOR serializer. The underlying CBOR library will by default encode a value to and from byte string if its type implements encoding.BinaryMarshaler or encoding.BinaryUnmarshaler, respectively. This is now disabled via an option to avoid diverging from JSON in those cases. --- .../serializer/cbor/internal/modes/decode.go | 4 ++++ .../cbor/internal/modes/decode_test.go | 20 +++++++++++++++++++ .../serializer/cbor/internal/modes/encode.go | 4 ++++ .../cbor/internal/modes/encode_test.go | 12 +++++++++++ 4 files changed, 40 insertions(+) diff --git a/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/cbor/internal/modes/decode.go b/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/cbor/internal/modes/decode.go index 79484c2da57..895b0deff95 100644 --- a/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/cbor/internal/modes/decode.go +++ b/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/cbor/internal/modes/decode.go @@ -135,6 +135,10 @@ var Decode cbor.DecMode = func() cbor.DecMode { // Reject anything other than the simple values true, false, and null. SimpleValues: simpleValues, + + // Disable default recognition of types implementing encoding.BinaryUnmarshaler, + // which is not recognized for JSON decoding. + BinaryUnmarshaler: cbor.BinaryUnmarshalerNone, }.DecMode() if err != nil { panic(err) diff --git a/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/cbor/internal/modes/decode_test.go b/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/cbor/internal/modes/decode_test.go index 0156a459ce2..79567d9df54 100644 --- a/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/cbor/internal/modes/decode_test.go +++ b/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/cbor/internal/modes/decode_test.go @@ -29,6 +29,12 @@ import ( "github.com/google/go-cmp/cmp" ) +type int64BinaryUnmarshaler int64 + +func (i *int64BinaryUnmarshaler) UnmarshalBinary(_ []byte) error { + return nil +} + func TestDecode(t *testing.T) { hex := func(h string) []byte { b, err := hex.DecodeString(h) @@ -203,6 +209,20 @@ func TestDecode(t *testing.T) { want: "AQIDBA==", assertOnError: assertNilError, }, + { + name: "into non-string type implementing BinaryUnmarshaler", + in: hex("40"), // '' + into: int64BinaryUnmarshaler(7), + assertOnError: assertOnConcreteError(func(t *testing.T, e *cbor.UnmarshalTypeError) { + want := &cbor.UnmarshalTypeError{ + CBORType: "byte string", + GoType: reflect.TypeFor[int64BinaryUnmarshaler]().String(), + } + if e.CBORType != want.CBORType || e.GoType != want.GoType { + t.Errorf("expected %q, got %q", want, e) + } + }), + }, }) group(t, "text string", []test{ diff --git a/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/cbor/internal/modes/encode.go b/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/cbor/internal/modes/encode.go index 30bdcf9440d..5eb2b74c41e 100644 --- a/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/cbor/internal/modes/encode.go +++ b/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/cbor/internal/modes/encode.go @@ -87,6 +87,10 @@ var Encode cbor.EncMode = func() cbor.EncMode { // base64 encoding of the original bytes. No base64 encoding or decoding needs to be // performed for []byte-to-CBOR-to-[]byte roundtrips. ByteSliceLaterFormat: cbor.ByteSliceLaterFormatBase64, + + // Disable default recognition of types implementing encoding.BinaryMarshaler, which + // is not recognized for JSON encoding. + BinaryMarshaler: cbor.BinaryMarshalerNone, }.EncMode() if err != nil { panic(err) diff --git a/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/cbor/internal/modes/encode_test.go b/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/cbor/internal/modes/encode_test.go index c93158f6b4b..3da44188cb9 100644 --- a/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/cbor/internal/modes/encode_test.go +++ b/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/cbor/internal/modes/encode_test.go @@ -26,6 +26,12 @@ import ( "github.com/google/go-cmp/cmp" ) +type int64BinaryMarshaler int64 + +func (i int64BinaryMarshaler) MarshalBinary() ([]byte, error) { + return []byte{}, nil +} + func TestEncode(t *testing.T) { for _, tc := range []struct { name string @@ -34,6 +40,12 @@ func TestEncode(t *testing.T) { want []byte assertOnError func(t *testing.T, e error) }{ + { + name: "implementations of BinaryMarshaler are ignored", + in: int64BinaryMarshaler(7), + want: []byte{0x07}, + assertOnError: assertNilError, + }, { name: "all duplicate fields are ignored", // Matches behavior of JSON serializer. in: struct {