Disable conflicting encode options when marshaling cbor.Tag.
Encode options, especially those that control the mapping from Go type to CBOR type, can result in output containing tag validity errors. For tag numbers that are built in, it's possible to "do the right thing" and override those options on a case-by-case basis. This can't and does not prevent tag validity errors for unrecognized tag numbers. Signed-off-by: Ben Luddy <bluddy@redhat.com>
This commit is contained in:
parent
69326f1c86
commit
0cabb4afed
15
encode.go
15
encode.go
@ -1648,8 +1648,21 @@ func encodeTag(e *bytes.Buffer, em *encMode, v reflect.Value) error {
|
||||
// Marshal tag number
|
||||
encodeHead(e, byte(cborTypeTag), t.Number)
|
||||
|
||||
vem := *em // shallow copy
|
||||
|
||||
// For built-in tags, disable settings that may introduce tag validity errors when
|
||||
// marshaling certain Content values.
|
||||
switch t.Number {
|
||||
case tagNumRFC3339Time:
|
||||
vem.stringType = StringToTextString
|
||||
vem.stringMajorType = cborTypeTextString
|
||||
case tagNumUnsignedBignum, tagNumNegativeBignum:
|
||||
vem.byteSlice = ByteSliceToByteString
|
||||
vem.byteSliceEncodingTag = 0
|
||||
}
|
||||
|
||||
// Marshal tag content
|
||||
return encode(e, em, reflect.ValueOf(t.Content))
|
||||
return encode(e, &vem, reflect.ValueOf(t.Content))
|
||||
}
|
||||
|
||||
// encodeHead writes CBOR head of specified type t and returns number of bytes written.
|
||||
|
||||
4
tag.go
4
tag.go
@ -7,7 +7,9 @@ import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Tag represents CBOR tag data, including tag number and unmarshaled tag content.
|
||||
// Tag represents CBOR tag data, including tag number and unmarshaled tag content. Marshaling and
|
||||
// unmarshaling of tag content is subject to any encode and decode options that would apply to
|
||||
// enclosed data item if it were to appear outside of a tag.
|
||||
type Tag struct {
|
||||
Number uint64
|
||||
Content interface{}
|
||||
|
||||
46
tag_test.go
46
tag_test.go
@ -1490,3 +1490,49 @@ func TestMarshalRawTagContainingMalformedCBORData(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestEncodeBuiltinTag tests that marshaling a value of type Tag "does the right thing" when
|
||||
// marshaling the enclosed data item of a built-in tag number.
|
||||
func TestEncodeBuiltinTag(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
tag Tag
|
||||
opts EncOptions
|
||||
want []byte
|
||||
}{
|
||||
{
|
||||
name: "unsigned bignum content not enclosed in expected encoding tag",
|
||||
tag: Tag{Number: tagNumUnsignedBignum, Content: []byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
|
||||
opts: EncOptions{ByteSlice: ByteSliceExpectedEncodingBase16},
|
||||
want: []byte{0xc2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
},
|
||||
{
|
||||
name: "negative bignum content not enclosed in expected encoding tag",
|
||||
tag: Tag{Number: tagNumNegativeBignum, Content: []byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
|
||||
opts: EncOptions{ByteSlice: ByteSliceExpectedEncodingBase16},
|
||||
want: []byte{0xc3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
},
|
||||
{
|
||||
name: "rfc 3339 content is not encoded as byte string",
|
||||
tag: Tag{Number: tagNumRFC3339Time, Content: "2013-03-21T20:04:00Z"},
|
||||
opts: EncOptions{String: StringToByteString},
|
||||
want: hexDecode("c074323031332d30332d32315432303a30343a30305a"),
|
||||
},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
em, err := tc.opts.EncMode()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
got, err := em.Marshal(tc.tag)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !bytes.Equal(got, tc.want) {
|
||||
t.Errorf("unexpected difference\ngot: 0x%x\nwant: 0x%x", got, tc.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user