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.
This commit is contained in:
Ben Luddy 2024-06-10 11:46:01 -04:00
parent 4b2fafc75e
commit cc5a18678f
No known key found for this signature in database
GPG Key ID: A6551E73A5974C30
4 changed files with 40 additions and 0 deletions

View File

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

View File

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

View File

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

View File

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