Support CBOR bignum in NextSize() (#325)

Add requested feature in stream-mode branch.
This commit is contained in:
Faye Amacker 2022-03-08 12:08:23 -06:00 committed by GitHub
parent 8cc0fef5e5
commit 1fafba071f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 30 additions and 16 deletions

View File

@ -158,13 +158,14 @@ func (sd *StreamDecoder) NextType() (Type, error) {
return UndefinedType, errors.New("cbor: unrecognized type")
}
// NextSize returns the next CBOR data size for four CBOR types.
// NextSize returns the next CBOR data size for five types.
// Returned uint64 represents different kind of size depending on
// the CBOR type:
// - byte string: length (in bytes) of byte string
// - text string: length (in bytes) of text string
// - array: number of array elements
// - map: number of key/value pairs
// the type:
// - ByteStringType : length (in bytes) of byte string
// - TextStringType : length (in bytes) of text string
// - ArrayType : number of array elements
// - MapType : number of key/value pairs
// - BigNumType : length (in bytes) of encoded big number
// Error is returned for indef length data and unsupported types.
// Support for additional types wasn't added for simplicity.
func (sd *StreamDecoder) NextSize() (uint64, error) {
@ -173,12 +174,20 @@ func (sd *StreamDecoder) NextSize() (uint64, error) {
return 0, err
}
ai := sd.dec.d.data[sd.dec.d.off] & 0x1f
off := sd.dec.d.off
if t == BigNumType {
// NextType() validates CBOR tag data (tag number + tag content),
// so it's safe to increment offset to access tag content.
off++ // Increment offset to point to tag content
t = ByteStringType // tag content type is CBOR byte string
}
switch t {
case ByteStringType, TextStringType, ArrayType, MapType:
off := sd.dec.d.off + 1
ai := sd.dec.d.data[off] & 0x1f
off++
// This function only interprets valid head because
// CBOR data is validated in NextType().

View File

@ -1752,11 +1752,11 @@ func TestStreamDecodeNextSize(t *testing.T) {
{"false", []byte{0xf4}, 0, "size operation is not supported"},
{"true", []byte{0xf5}, 0, "size operation is not supported"},
{"nil", []byte{0xf6}, 0, "size operation is not supported"},
{"uint", []byte{0x01}, 0, "size operation is not supported"}, // 1
{"int", []byte{0x20}, 0, "size operation is not supported"}, // -1
{"tag", []byte{0xc2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 0, "size operation is not supported"}, // bignum(18446744073709551616)
{"empty byte string", []byte{0x40}, 0, ""}, // []
{"byte string", []byte{0x45, 0x01, 0x02, 0x03, 0x04, 0x05}, 5, ""}, // [1, 2, 3, 4, 5]
{"uint", []byte{0x01}, 0, "size operation is not supported"}, // 1
{"int", []byte{0x20}, 0, "size operation is not supported"}, // -1
{"tag", []byte{0xc1, 0x1a, 0x51, 0x4b, 0x67, 0xb0}, 0, "size operation is not supported"}, // epoch-based date/time
{"empty byte string", []byte{0x40}, 0, ""}, // []
{"byte string", []byte{0x45, 0x01, 0x02, 0x03, 0x04, 0x05}, 5, ""}, // [1, 2, 3, 4, 5]
{"indef length byte string", []byte{0x5f, 0x42, 0x01, 0x02, 0x043, 0x03, 0x04, 0x05, 0xff}, 0, "size is unavailable for indefinite length"},
{"empty text string", []byte{0x60}, 0, ""}, // ""
{"text string", []byte{0x65, 0x68, 0x65, 0x6c, 0x6c, 0x6f}, 5, ""}, // "hello"
@ -1765,9 +1765,14 @@ func TestStreamDecodeNextSize(t *testing.T) {
{"text string", []byte{0x7a, 0x00, 0x00, 0x00, 0x01, 0x61}, 1, ""}, // "a"
{"text string", []byte{0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x61}, 1, ""}, // "a"
{"indef length text string", []byte{0x7f, 0x65, 0x73, 0x74, 0x72, 0x65, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x67, 0xff}, 0, "size is unavailable for indefinite length"},
{"empty array", []byte{0x80}, 0, ""}, // []
{"array", []byte{0x83, 0x01, 0x02, 0x03}, 3, ""}, // [1, 2, 3]
{"indef length array", []byte{0x9f, 0x01, 0x02, 0x03, 0xff}, 0, "size is unavailable for indefinite length"}, // [1, 2, 3]
{"empty array", []byte{0x80}, 0, ""}, // []
{"array", []byte{0x83, 0x01, 0x02, 0x03}, 3, ""}, // [1, 2, 3]
{"indef length array", []byte{0x9f, 0x01, 0x02, 0x03, 0xff}, 0, "size is unavailable for indefinite length"}, // [1, 2, 3]
{"big int 0", []byte{0xc2, 0x40}, 0, ""}, // bignum: 0
{"big int 1", []byte{0xc2, 0x41, 0x01}, 1, ""}, // bignum: 1
{"big int 18446744073709551616", []byte{0xc2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 9, ""}, // bignum: 18446744073709551616
{"big int -1", []byte{0xc3, 0x40}, 0, ""}, // bignum: -1
{"big int -18446744073709551617", []byte{0xc3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 9, ""}, // bignum: -18446744073709551617
}
for _, tc := range testCases {