Repository: fxamacker/cbor
Pull request #169 (2020-02-22 18:18:07)

Support decoding CBOR byte string to Go byte array and also prevent potential decoding error
Added support for decoding CBOR byte string (major type 2) to
Go byte array.  Go byte slices were already supported.

Decoding is handled the same way as encoding/json, which says:

"To unmarshal a JSON array into a Go array, Unmarshal decodes
JSON array elements into corresponding Go array elements. If the
Go array is smaller than the JSON array, the additional JSON array
elements are discarded. If the JSON array is smaller than the
Go array, the additional Go array elements are set to zero values."

Closes: #133

<hr> 

Fix potential error decoding shorter CBOR indefinite length array to 
Go array (slices are OK)

There's no problem decoding to Go slice, which is the recommended and
default Go type for CBOR arrays.

This fix prevents potential errors that can happen when CBOR indefinite
length array has fewer elements than Go array.

This problem was detected by an updated version of fxamacker/cbor-fuzz
and exists in all prior versions of this library.

Closes: #170 


Patch:
diff --git a/README.md b/README.md
index 8e15f5b..9f8f2d2 100644
--- a/README.md
+++ b/README.md
@@ -14,17 +14,17 @@ __What is CBOR__?  [CBOR](CBOR_GOLANG.md) ([RFC 7049](https://tools.ietf.org/htm
 
 This CBOR library is safe and fast. Here's how it compares to another library using test data from RFC 8392 A.1.
 
-|     | fxamacker/cbor 2.1 | ugorji/go 1.1.7 |
-| --- | ------------------ | --------------- |
-| Encode CWT claims | 457 ns/op, 176 B/op, 2 allocs/op | 995 ns/op, 1424 B/op, 4 allocs/op | 
-| Decode CWT claims | 796 ns/op, 176 B/op, 6 allocs/op | 1105 ns/op, 568 B/op, 6 allocs/op |
+|                   | fxamacker/cbor 2.1          |ugorji/go 1.1.7                   |
+|-------------------|-----------------------------|----------------------------------|
+|Encode CWT claims  | 457 ns/op, 176 B/op, 2 allocs/op | 995 ns/op, 1424 B/op, 4 allocs/op
+|Decode CWT claims  | 796 ns/op, 176 B/op,	6 allocs/op | 1105 ns/op, 568 B/op, 6 allocs/op
 
 Speed is only one factor. There are more important factors.
 
-|     | fxamacker/cbor 2.1 | ugorji/go 1.1.7 |
-| --- | ------------------ | --------------- |
-| Malformed data #1 | 57.4 ns/op, 32 B/op, 1 allocs/op | ⚠️ fatal error: out of memory |
-| Malformed data #2 | 67.7 ns/op, 32 B/op, 1 allocs/op | ⚠️ runtime: out of memory: cannot allocate |
+|                   | fxamacker/cbor 2.1               |ugorji/go 1.1.7                   |
+|-------------------|----------------------------------|----------------------------------|
+|Malformed data #1  | 57.4 ns/op, 32 B/op, 1 allocs/op |⚠️ fatal error: out of memory
+|Malformed data #2  | 67.7 ns/op, 32 B/op, 1 allocs/op |⚠️ runtime: out of memory: cannot allocate
 
 Benchmarks used Go 1.12, linux_amd64, and default options for each CBOR library.
 
@@ -74,7 +74,7 @@ Using Go modules is recommended.
 $ GO111MODULE=on go get github.com/fxamacker/cbor/v2
 ```
 
-```go
+```
 import (
 	"github.com/fxamacker/cbor/v2" // imports as package "cbor"
 )
@@ -100,15 +100,14 @@ Functions with identical signatures to encoding/json include:
 __Default Mode__  
 
 If default options are acceptable, package level functions can be used for encoding and decoding.
+```
+b, err := cbor.Marshal(v)
 
-```go
-b, err := cbor.Marshal(v)        // encode v to []byte b
-
-err := cbor.Unmarshal(b, &v)     // decode []byte b to v
+err := cbor.Unmarshal(b, &v)
 
-encoder := cbor.NewEncoder(w)    // create encoder with io.Writer w
+encoder := cbor.NewEncoder(w)
 
-decoder := cbor.NewDecoder(r)    // create decoder with io.Reader r
+decoder := cbor.NewDecoder(r)
 ```
 
 __Modes__
@@ -128,27 +127,28 @@ __Creating and Using Encoding Modes__
 
 Most apps will probably create one EncMode and DecMode before init().  However, there's no limit and each can use different options.
 
-```go
+```
 // Create EncOptions using either struct literal or a function.
 opts := cbor.CanonicalEncOptions()
 
-// If needed, modify opts. For example: opts.Time = cbor.TimeUnix
+// If needed, modify encoding options
+opts.Time = cbor.TimeUnix
 
 // Create reusable EncMode interface with immutable options, safe for concurrent use.
 em, err := opts.EncMode()   
 
 // Use EncMode like encoding/json, with same function signatures.
-b, err := em.Marshal(v)      // encode v to []byte b
-
-encoder := em.NewEncoder(w)  // create encoder with io.Writer w
-err := encoder.Encode(v)     // encode v to io.Writer w
+b, err := em.Marshal(v)
+// or
+encoder := em.NewEncoder(w)
+err := encoder.Encode(v)
 ```
 
 __Creating Modes With CBOR Tags__
 
 A TagSet is used to specify CBOR tags.
  
-```go
+```
 em, err := opts.EncMode()                  // no tags
 em, err := opts.EncModeWithTags(ts)        // immutable tags
 em, err := opts.EncModeWithSharedTags(ts)  // mutable shared tags
@@ -158,14 +158,12 @@ TagSet and all modes using it are safe for concurrent use.  Equivalent API is av
 
 __Predefined Encoding Options__
 
-```go
-func CanonicalEncOptions() EncOptions {}            // settings for RFC 7049 Canonical CBOR
-func CTAP2EncOptions() EncOptions {}                // settings for FIDO2 CTAP2 Canonical CBOR
-func CoreDetEncOptions() EncOptions {}              // settings from a draft RFC (subject to change)
-func PreferredUnsortedEncOptions() EncOptions {}    // settings from a draft RFC (subject to change)
 ```
-
-The empty curly braces prevent a syntax highlighting bug on GitHub, please ignore them.
+func CanonicalEncOptions() EncOptions     // settings for RFC 7049 Canonical CBOR
+func CTAP2EncOptions() EncOptions         // settings for FIDO2 CTAP2 Canonical CBOR
+func CoreDetEncOptions() EncOptions       // modern settings from a draft RFC (subject to change)
+func PreferredUnsortedEncOptions() EncOptions  // modern settings from a draft RFC (subject to change)
+```
 
 __Struct Tags (keyasint, toarray, omitempty)__
 
@@ -190,7 +188,7 @@ Latest version is v2.x, which has:
   * CoreDetEncOptions() is subject to change because it uses draft standard.
   * PreferredUnsortedEncOptions() is subject to change because it uses draft standard.
 * __Passed all tests__ – v2.x passed all 375+ tests on amd64, arm64, ppc64le and s390x with linux.
-* __Passed fuzzing__ – v2.1 passed 361+ million execs in coverage-guided fuzzing on Feb 17, 2020 (release date) and passed 2+ billion execs several days later.
+* __Passed fuzzing__ – v2.1 passed 361+ million execs in coverage-guided fuzzing on Feb 17, 2020.
 
 __Why v2.x?__:
 
@@ -210,7 +208,7 @@ __Roadmap__:
 
 * Milestone v2.2
    - [ ] CBOR BSTR <--> Go byte array. In the meantime, use CBOR BSTR with Go byte slice.   
-   - [ ] Replace some hardcoded limits with options (within allowed ranges) for encoding and decoding (e.g. max nested levels).
+   - [ ] If time allows, add more CBOR tags as default or optional built-in tags.
 
 <hr>
 
@@ -225,37 +223,13 @@ This library is designed to be:
 * __Small__ – Programs in cisco/senml are 4 MB smaller by switching to this library. In extreme cases programs can be smaller by 9+ MB. No code gen and the only imported pkg is x448/float16 which is maintained by the same team.
 * __Safe and reliable__ – No `unsafe` pkg, coverage >95%, coverage-guided fuzzing, and data validation to avoid crashes on malformed or malicious data.
 
-Avoiding `unsafe` package has benefits.  The `unsafe` package [warns](https://golang.org/pkg/unsafe/):
-
-> Packages that import unsafe may be non-portable and are not protected by the Go 1 compatibility guidelines.
-
-All releases prioritize reliability to avoid crashes on decoding malformed CBOR data. See [Fuzzing and Coverage](#fuzzing-and-code-coverage).
-
 Competing factors are balanced:
 
-* __Speed__ vs __safety__ vs __size__ – to keep size small, avoid code generation. For safety, validate data and avoid Go's `unsafe` pkg.  For speed, use safe optimizations such as caching struct metadata. This library is faster than a well-known library that uses `unsafe` and code gen.
-* __Standards compliance__ vs __size__ – Supports CBOR RFC 7049 with minor [limitations](#limitations). To limit bloat, CBOR tags are supported but not all tags are built-in. The API allows users to add tags that aren't built-in.  The API also allows custom encoding and decoding of user-defined Go types.
-
-__Click to expand topic:__
-
-<details>
- <summary>Supported CBOR Features (Highlights)</summary><p>
-
-|     | CBOR&nbsp;Feature&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | Description |
-| --- | :--- | :--- |
-| ✔️ | CBOR tags | API supports built-in and user-defined tags. |
-| ✔️ | Preferred serialization | Ints encode to fewest bytes. Optional float64→float32→float16 if value fits. |
-| ✔️ | Sort map keys | Unsorted, length-first (Canonical CBOR), and bytewise-lexicographic (CTAP2) |
-| ✔️ | Duplicate map keys | Always forbid for encoding, option to allow/forbid for for decoding. |
-| ✔️ | Indefinite length data | Option to allow/forbid for encoding and decoding. |
-| ✔️ | Well-formedness checks | Always checked and enforced. |
-| ✔️ | Basic validity checks | UTF-8 validity, etc. checked after well-formedness. |
-| ✔️ | Security checks | Prevents integer overflow and resource exhaustion described in RFC7049&nbsp;Section&nbsp;8&nbsp;Security&nbsp;Considerations. |
-
-</details>
-
-<details>
- <summary>v2.0 API Design</summary><p>
+* __Speed__ vs __safety__ vs __size__ – to keep size small, avoid code generation. For safety, validate data and avoid Go's `unsafe` pkg.  For speed, use safe optimizations such as caching struct metadata. v1.4 is faster than a well-known library that uses `unsafe` and code gen.
+* __Standards compliance__ – CBOR ([RFC 7049](https://tools.ietf.org/html/rfc7049)) with minor [limitations](#limitations).
+  * Encoder supports options for sorting, floating-point conversions, and more.  Predefined options are also available so you can use "CTAP2 Canonical CBOR", etc. without knowing individual settings.  
+  * Decoder checks for well-formedness, validates data, and limits nested levels to defend against attacks. Decoder has options to handle duplicate map keys.  
+  * Both encoder and decoder supports CBOR tags (built-in and user-defined), and more. See [Standards](#standards).
 
 v2.0 decoupled options from CBOR encoding & decoding functions:
 
@@ -265,7 +239,11 @@ v2.0 decoupled options from CBOR encoding & decoding functions:
 * Features like CBOR tags can be added without more breaking API changes.
 * Options to handle duplicate map keys can be added without more breaking API changes.
 
-</details>
+Avoiding `unsafe` package has benefits.  The `unsafe` package [warns](https://golang.org/pkg/unsafe/):
+
+> Packages that import unsafe may be non-portable and are not protected by the Go 1 compatibility guidelines.
+
+All releases prioritize reliability to avoid crashes on decoding malformed CBOR data. See [Fuzzing and Coverage](#fuzzing-and-code-coverage).
 
 Features not in Go's standard library are usually not added.  However, the __`toarray`__ struct tag in __ugorji/go__ was too useful to ignore. It was added in v1.3 when a project mentioned they were using it with CBOR to save disk space.
 
@@ -329,23 +307,23 @@ Integers always encode to the shortest form that preserves value.  By default, t
 
 Encoding of other data types and map key sort order are determined by encoder options.
 
-| Encoding Option | Available Settings (defaults in bold, aliases in italics) |
-| --------------- | --------------------------------------------------------- |
-| EncOptions.Sort | __`SortNone`__, `SortLengthFirst`, `SortBytewiseLexical`, _`SortCanonical`_, _`SortCTAP2`_, _`SortCoreDeterministic`_ |
-| EncOptions.Time | __`TimeUnix`__, `TimeUnixMicro`, `TimeUnixDynamic`, `TimeRFC3339`, `TimeRFC3339Nano` |
-| EncOptions.TimeTag | __`EncTagNone`__, `EncTagRequired` |
-| EncOptions.ShortestFloat | __`ShortestFloatNone`__, `ShortestFloat16` |
-| EncOptions.InfConvert | __`InfConvertFloat16`__, `InfConvertNone` |
-| EncOptions.NaNConvert | __`NaNConvert7e00`__, `NaNConvertNone`, `NaNConvertQuiet`, `NaNConvertPreserveSignal` |
+|Encoding Option              |Available Settings (defaults in bold, aliases in italics)                              |
+|-----------------------------|---------------------------------------------------------------------------------------|
+|EncOptions.Sort |__`SortNone`__, `SortLengthFirst`, `SortBytewiseLexical`, _`SortCanonical`_, _`SortCTAP2`_, _`SortCoreDeterministic`_ |
+|EncOptions.Time |__`TimeUnix`__, `TimeUnixMicro`, `TimeUnixDynamic`, `TimeRFC3339`, `TimeRFC3339Nano` |
+|EncOptions.TimeTag |__`EncTagNone`__, `EncTagRequired` |
+|EncOptions.ShortestFloat |__`ShortestFloatNone`__, `ShortestFloat16` |
+|EncOptions.InfConvert |__`InfConvertFloat16`__, `InfConvertNone` |
+|EncOptions.NaNConvert |__`NaNConvert7e00`__, `NaNConvertNone`, `NaNConvertQuiet`, `NaNConvertPreserveSignal` |
 
 See [Options](#options) section for details about each setting.
 
 ### Decoding Options
 
-| Decoding Option | Available Settings (defaults in bold, aliases in italics) |
-| --------------- | --------------------------------------------------------- |
-| DecOptions.TimeTag | __`DecTagIgnored`__, `DecTagOptional`, `DecTagRequired` |
-| DecOptions.DupMapKey | __`DupMapKeyQuiet`__, `DupMapKeyEnforcedAPF` |
+|Decoding Option              |Available Settings (defaults in bold, aliases in italics)                              |
+|-----------------------------|---------------------------------------------------------------------------------------|
+|DecOptions.TimeTag |__`DecTagIgnored`__, `DecTagOptional`, `DecTagRequired` |
+|DecOptions.DupMapKey |__`DupMapKeyQuiet`__, `DupMapKeyEnforcedAPF` |
 
 See [Options](#options) section for details about each setting.
 
@@ -362,23 +340,22 @@ See [Options](#options) section for details about each setting.
 ⚓  [Install](#installation) • [Status](#current-status) • [Design Goals](#design-goals) • [Features](#features) • [Standards](#standards) • [API](#api) • [Usage](#usage) • [Fuzzing](#fuzzing-and-code-coverage) • [Security Policy](#security-policy) • [License](#license)
 
 ## Standards
-This library is a full-featured generic CBOR [(RFC 7049)](https://tools.ietf.org/html/rfc7049) encoder and decoder.  Notable CBOR features include:
-
-|     | CBOR&nbsp;Feature&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | Description |
-| --- | :--- | :--- |
-| ✔️ | CBOR tags | API supports built-in and user-defined tags. |
-| ✔️ | Preferred serialization | Ints encode to fewest bytes. Optional float64→float32→float16 if value fits. |
-| ✔️ | Sort map keys | Unsorted, length-first (Canonical CBOR), and bytewise-lexicographic (CTAP2) |
-| ✔️ | Duplicate map keys | Always forbid for encoding, option to allow/forbid for for decoding. |
-| ✔️ | Indefinite length data | Option to allow/forbid for encoding and decoding. |
-| ✔️ | Well-formedness checks | Always checked and enforced. |
-| ✔️ | Basic validity checks | UTF-8 validity, etc. checked after well-formedness. |
-| ✔️ | Security checks | Prevents integer overflow and resource exhaustion described in RFC7049&nbsp;Section&nbsp;8&nbsp;Security&nbsp;Considerations. |
+This library is a small, fast, safe, and full-featured generic CBOR [(RFC 7049)](https://tools.ietf.org/html/rfc7049) encoder and decoder.  Notable features include:
 
-See the Features section for list of [Encoding Options](#encoding-options) and [Decoding Options](#decoding-options).
+* CBOR tags (API supports built-in and user-defined) for both encoder and decoder
+* Definite and indefinite length data for both encoder and decoder
+* Encoder option for preferred serialization, including IEEE 754 binary16
+* Encoder option for sorting map keys: length-first (Canonical CBOR) and bytewise-lexical (CTAP2 & 7049bis)
+* Encoder options for floating-point shortest form, NaN, and Infinity
+* Decoder option to detect and reject duplicate map keys
+* Decoder checks for well-formedness and validates data
+* Decoder doesn't crash and avoids resource exhaustion from malformed/malicious CBOR data
 
 Known limitations are noted in the [Limitations section](#limitations). 
 
+Integers always encode to the shortest form that preserves value. Floats can optionally encode to shortest form:  
+float64 -> float32 -> float16 when values can be preserved.
+
 Go nil values for slices, maps, pointers, etc. are encoded as CBOR null.  Empty slices, maps, etc. are encoded as empty CBOR arrays and maps.
 
 Decoder checks for all required well-formedness errors, including all "subkinds" of syntax errors and too little data.
@@ -392,10 +369,7 @@ When decoding well-formed CBOR arrays and maps, decoder saves the first error it
 
 See [Options](#options) section for detailed settings or [Features](#features) section for a summary of options.
 
-__Click to expand topic:__
-
-<details>
- <summary>Duplicate Map Keys</summary><p>
+__Duplicate Map Key Options__
 
 This library provides options for fast detection and rejection of duplicate map keys based on applying a Go-specific data model to CBOR's extended generic data model in order to determine duplicate vs distinct map keys. Detection relies on whether the CBOR map key would be a duplicate "key" when decoded and applied to the user-provided Go map or struct. 
 
@@ -403,9 +377,7 @@ This library provides options for fast detection and rejection of duplicate map
 
 `DupMapKeyEnforcedAPF` enforces detection and rejection of duplidate map keys. Decoding stops immediately and returns `DupMapKeyError` when the first duplicate key is detected. The error includes the duplicate map key and the index number. 
 
-APF suffix means "Allow Partial Fill" so the destination map or struct can contain some decoded values at the time of error. It is the caller's responsibility to respond to the `DupMapKeyError` by discarding the partially filled result if that's required by their protocol.
-
-</details>
+APF suffix means "Allow Partial Fill" so the destination map or struct can contain some decoded values at the time of error. It is the caller's responsibility to respond to the `DupMapKeyError` by discarding the partially filled result if that's required by their protocol. 
 
 ## Limitations
 
@@ -438,8 +410,7 @@ EncMode and DecMode use immutable options so their behavior won't accidentally c
 __API for Default Mode__
 
 If default options are acceptable, then you don't need to create EncMode or DecMode.
-
-```go
+```
 Marshal(v interface{}) ([]byte, error)
 NewEncoder(w io.Writer) *Encoder
 
@@ -448,8 +419,7 @@ NewDecoder(r io.Reader) *Decoder
 ```
 
 __API for Creating & Using Encoding Modes__
-
-```go
+```
 // EncMode interface uses immutable options and is safe for concurrent use.
 type EncMode interface {
 	Marshal(v interface{}) ([]byte, error)
@@ -463,29 +433,25 @@ type EncOptions struct {
 }
 
 // EncMode returns an EncMode interface created from EncOptions.
-func (opts EncOptions) EncMode() (EncMode, error) {}
+func (opts EncOptions) EncMode() (EncMode, error) 
 
 // EncModeWithTags returns EncMode with options and tags that are both immutable. 
-func (opts EncOptions) EncModeWithTags(tags TagSet) (EncMode, error) {}
+func (opts EncOptions) EncModeWithTags(tags TagSet) (EncMode, error)
 
 // EncModeWithSharedTags returns EncMode with immutable options and mutable shared tags. 
-func (opts EncOptions) EncModeWithSharedTags(tags TagSet) (EncMode, error) {}
+func (opts EncOptions) EncModeWithSharedTags(tags TagSet) (EncMode, error)
 ```
 
-The empty curly braces prevent a syntax highlighting bug, please ignore them.
-
 __API for Predefined Encoding Options__
-
-```go
-func CanonicalEncOptions() EncOptions {}            // settings for RFC 7049 Canonical CBOR
-func CTAP2EncOptions() EncOptions {}                // settings for FIDO2 CTAP2 Canonical CBOR
-func CoreDetEncOptions() EncOptions {}              // settings from a draft RFC (subject to change)
-func PreferredUnsortedEncOptions() EncOptions {}    // settings from a draft RFC (subject to change)
+```
+func CanonicalEncOptions() EncOptions     // settings for RFC 7049 Canonical CBOR
+func CTAP2EncOptions() EncOptions         // settings for FIDO2 CTAP2 Canonical CBOR
+func CoreDetEncOptions() EncOptions       // modern settings from a draft RFC (subject to change)
+func PreferredUnsortedEncOptions() EncOptions  // modern settings from a draft RFC (subject to change)
 ```
 
 __API for Creating & Using Decoding Modes__
-
-```go
+```
 // DecMode interface uses immutable options and is safe for concurrent use.
 type DecMode interface {
 	Unmarshal(data []byte, v interface{}) error
@@ -499,24 +465,22 @@ type DecOptions struct {
 }
 
 // DecMode returns a DecMode interface created from DecOptions.
-func (opts DecOptions) DecMode() (DecMode, error) {}
+func (opts DecOptions) DecMode() (DecMode, error)
 
 // DecModeWithTags returns DecMode with options and tags that are both immutable. 
-func (opts DecOptions) DecModeWithTags(tags TagSet) (DecMode, error) {}
+func (opts DecOptions) DecModeWithTags(tags TagSet) (DecMode, error)
 
 // DecModeWithSharedTags returns DecMode with immutable options and mutable shared tags. 
-func (opts DecOptions) DecModeWithSharedTags(tags TagSet) (DecMode, error) {}
+func (opts DecOptions) DecModeWithSharedTags(tags TagSet) (DecMode, error)
 ```
 
-The empty curly braces prevent a syntax highlighting bug, please ignore them.
-
 __API for Using CBOR Tags__
 
 `TagSet` can be used to associate user-defined Go type(s) to tag number(s).  It's also used to create EncMode or DecMode. For example, `em := EncOptions{...}.EncModeWithTags(ts)` or `em := EncOptions{...}.EncModeWithSharedTags(ts)`. This allows every standard API exported by em (like `Marshal` and `NewEncoder`) to use the specified tags automatically.
 
 `Tag` and `RawTag` can be used to encode/decode a tag number with a Go value, but `TagSet` is generally recommended.
 
-```go
+```
 type TagSet interface {
     // Add adds given tag number(s), content type, and tag options to TagSet.
     Add(opts TagOptions, contentType reflect.Type, num uint64, nestedNum ...uint64) error
@@ -527,8 +491,7 @@ type TagSet interface {
 ```
 
 `Tag` and `RawTag` types can also be used to encode/decode tag number with Go value.
-
-```go
+```
 type Tag struct {
     Number  uint64
     Content interface{}
@@ -552,20 +515,20 @@ Options for the decoding and encoding are listed here.
 
 ### Decoding Options
 
-| DecOptions.TimeTag | Description |
-| ------------------ | ----------- |
-| DecTagIgnored (default) | Tag numbers are ignored (if present) for time values. |
-| DecTagOptional | Tag numbers are only checked for validity if present for time values. |
-| DecTagRequired | Tag numbers must be provided for time values except for CBOR Null and CBOR Undefined. |
+|DecOptions.TimeTag           |Description                                                                            |
+|-----------------------------|---------------------------------------------------------------------------------------|
+|DecTagIgnored (default)      |Tag numbers are ignored (if present) for time values.|
+|DecTagOptional               |Tag numbers are only checked for validity if present for time values.|
+|DecTagRequired               |Tag numbers must be provided for time values except for CBOR Null and CBOR Undefined.|
 
 CBOR Null and CBOR Undefined are silently treated as Go's zero time instant.  Go's `time` package provides `IsZero` function, which reports whether t represents the zero time instant, January 1, year 1, 00:00:00 UTC. 
 
 __Duplicate Map Key Options__
 
-| DecOptions.DupMapKey | Description |
-| -------------------- | ----------- |
-| DupMapKeyQuiet (default) | turns off detection of duplicate map keys. It uses a "keep fastest" method by choosing either "keep first" or "keep last" depending on the Go data type. |
-| DupMapKeyEnforcedAPF | enforces detection and rejection of duplidate map keys. Decoding stops immediately and returns `DupMapKeyError` when the first duplicate key is detected. The error includes the duplicate map key and the index number. |
+|DecOptions.DupMapKey         |Description                                                                            |
+|-----------------------------|---------------------------------------------------------------------------------------|
+|DupMapKeyQuiet (default)     |turns off detection of duplicate map keys. It uses a "keep fastest" method by choosing either "keep first" or "keep last" depending on the Go data type.|
+|DupMapKeyEnforcedAPF         |enforces detection and rejection of duplidate map keys. Decoding stops immediately and returns `DupMapKeyError` when the first duplicate key is detected. The error includes the duplicate map key and the index number.|
 
 `DupMapKeyEnforcedAPF` uses "Allow Partial Fill" so the destination map or struct can contain some decoded values at the time of error.  Users can respond to the `DupMapKeyError` by discarding the partially filled result if that's required by their protocol.
 
@@ -575,36 +538,36 @@ __Integers always encode to the shortest form that preserves value__.  Encoding
 
 These functions are provided to create and return a modifiable EncOptions struct with predefined settings.
 
-| Predefined EncOptions | Description |
-| --------------------- | ----------- |
-| CanonicalEncOptions() |[Canonical CBOR (RFC 7049 Section 3.9)](https://tools.ietf.org/html/rfc7049#section-3.9). |
-| CTAP2EncOptions() |[CTAP2 Canonical CBOR (FIDO2 CTAP2)](https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-client-to-authenticator-protocol-v2.0-id-20180227.html#ctap2-canonical-cbor-encoding-form). |
-| PreferredUnsortedEncOptions() |Unsorted, encode float64->float32->float16 when values fit, NaN values encoded as float16 0x7e00. |
-| CoreDetEncOptions() |PreferredUnsortedEncOptions() + map keys are sorted bytewise lexicographic. |
+|Predefined EncOptions        |Description                                                                            |
+|-----------------------------|---------------------------------------------------------------------------------------|
+|CanonicalEncOptions() |[Canonical CBOR (RFC 7049 Section 3.9)](https://tools.ietf.org/html/rfc7049#section-3.9).|
+|CTAP2EncOptions() |[CTAP2 Canonical CBOR (FIDO2 CTAP2)](https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-client-to-authenticator-protocol-v2.0-id-20180227.html#ctap2-canonical-cbor-encoding-form).|
+|PreferredUnsortedEncOptions() |Unsorted, encode float64->float32->float16 when values fit, NaN values encoded as float16 0x7e00.|
+|CoreDetEncOptions() |PreferredUnsortedEncOptions() + map keys are sorted bytewise lexicographic.|
 
 🌱 CoreDetEncOptions() and PreferredUnsortedEncOptions() are subject to change until the draft RFC they used is approved by IETF.
 
-| EncOptions.Sort | Description |
-| --------------- | ----------- |
-| SortNone (default) |No sorting for map keys. |
-| SortLengthFirst |Length-first map key ordering. |
-| SortBytewiseLexical |Bytewise lexicographic map key ordering |
-| SortCanonical |(alias) Same as SortLengthFirst [(RFC 7049 Section 3.9)](https://tools.ietf.org/html/rfc7049#section-3.9) |
-| SortCTAP2 |(alias) Same as SortBytewiseLexical [(CTAP2 Canonical CBOR)](https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-client-to-authenticator-protocol-v2.0-id-20180227.html#ctap2-canonical-cbor-encoding-form). |
-| SortCoreDeterministic |(alias) Same as SortBytewiseLexical. |
-
-| EncOptions.Time | Description |
-| --------------- | ----------- |
-| TimeUnix (default) | (seconds) Encode as integer. |
-| TimeUnixMicro | (microseconds) Encode as floating-point.  ShortestFloat option determines size. |
-| TimeUnixDynamic | (seconds or microseconds) Encode as integer if time doesn't have fractional seconds, otherwise encode as floating-point rounded to microseconds. |
-| TimeRFC3339 | (seconds) Encode as RFC 3339 formatted string. |
-| TimeRFC3339Nano | (nanoseconds) Encode as RFC3339 formatted string. |
-
-| EncOptions.TimeTag | Description |
-| ------------------ | ----------- |
-| EncTagNone (default) | Tag number will not be encoded for time values. |
-| EncTagRequired | Tag number (0 or 1) will be encoded unless time value is undefined/zero-instant. |
+|EncOptions.Sort              |Description                                                                            |
+|-----------------------------|---------------------------------------------------------------------------------------|
+|SortNone (default) |No sorting for map keys.|
+|SortLengthFirst |Length-first map key ordering.|
+|SortBytewiseLexical |Bytewise lexicographic map key ordering|
+|SortCanonical |(alias) Same as SortLengthFirst [(RFC 7049 Section 3.9)](https://tools.ietf.org/html/rfc7049#section-3.9)|
+|SortCTAP2 |(alias) Same as SortBytewiseLexical [(CTAP2 Canonical CBOR)](https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-client-to-authenticator-protocol-v2.0-id-20180227.html#ctap2-canonical-cbor-encoding-form).|
+|SortCoreDeterministic |(alias) Same as SortBytewiseLexical.|
+
+|EncOptions.Time              |Description                                                                            |
+|-----------------------------|---------------------------------------------------------------------------------------|
+|TimeUnix (default) |(seconds) Encode as integer.|
+|TimeUnixMicro |(microseconds) Encode as floating-point.  ShortestFloat option determines size.|
+|TimeUnixDynamic |(seconds or microseconds) Encode as integer if time doesn't have fractional seconds, otherwise encode as floating-point rounded to microseconds.|
+|TimeRFC3339 |(seconds) Encode as RFC 3339 formatted string.|
+|TimeRFC3339Nano |(nanoseconds) Encode as RFC3339 formatted string.|
+
+|EncOptions.TimeTag           |Description                                                                            |
+|-----------------------------|---------------------------------------------------------------------------------------|
+|EncTagNone (default)         |Tag number will not be encoded for time values.|
+|EncTagRequired               |Tag number (0 or 1) will be encoded unless time value is undefined/zero-instant.|
 
 __Undefined Time Values__
 
@@ -616,25 +579,25 @@ __Floating-Point Options__
 
 Encoder has 3 types of options for floating-point data: ShortestFloatMode, InfConvertMode, and NaNConvertMode.
 
-| EncOptions.ShortestFloat | Description |
-| ------------------------ | ----------- |
-| ShortestFloatNone (default) | No size conversion. Encode float32 and float64 to CBOR floating-point of same bit-size. |
-| ShortestFloat16 | Encode float64 -> float32 -> float16 ([IEEE 754 binary16](https://en.wikipedia.org/wiki/Half-precision_floating-point_format)) when values fit. |
+|EncOptions.ShortestFloat     |Description                                                                            |
+|-----------------------------|---------------------------------------------------------------------------------------|
+|ShortestFloatNone (default) |No size conversion. Encode float32 and float64 to CBOR floating-point of same bit-size.|
+|ShortestFloat16 |Encode float64 -> float32 -> float16 ([IEEE 754 binary16](https://en.wikipedia.org/wiki/Half-precision_floating-point_format)) when values fit.|
 
 Conversions for infinity and NaN use InfConvert and NaNConvert settings.
 
-| EncOptions.InfConvert | Description |
-| --------------------- | ----------- |
-| InfConvertFloat16 (default) | Convert +- infinity to float16 since they always preserve value (recommended) |
-| InfConvertNone |Don't convert +- infinity to other representations -- used by CTAP2 Canonical CBOR |
+|EncOptions.InfConvert        |Description                                                                            |
+|-----------------------------|---------------------------------------------------------------------------------------|
+|InfConvertFloat16 (default) |Convert +- infinity to float16 since they always preserve value (recommended)|
+|InfConvertNone |Don't convert +- infinity to other representations -- used by CTAP2 Canonical CBOR|
 
 
-| EncOptions.NaNConvert | Description |
-| --------------------- | ----------- |
-| NaNConvert7e00 (default) | Encode to 0xf97e00 (CBOR float16 = 0x7e00) -- used by RFC 7049 Canonical CBOR. |
-| NaNConvertNone | Don't convert NaN to other representations -- used by CTAP2 Canonical CBOR. |
-| NaNConvertQuiet | Force quiet bit = 1 and use shortest form that preserves NaN payload. |
-| NaNConvertPreserveSignal | Convert to smallest form that preserves value (quit bit unmodified and NaN payload preserved). |
+|EncOptions.NaNConvert        |Description                                                                            |
+|-----------------------------|---------------------------------------------------------------------------------------|
+|NaNConvert7e00 (default) |Encode to 0xf97e00 (CBOR float16 = 0x7e00) -- used by RFC 7049 Canonical CBOR.|
+|NaNConvertNone |Don't convert NaN to other representations -- used by CTAP2 Canonical CBOR.|
+|NaNConvertQuiet |Force quiet bit = 1 and use shortest form that preserves NaN payload.|
+|NaNConvertPreserveSignal |Convert to smallest form that preserves value (quit bit unmodified and NaN payload preserved).|
 
 <hr>
 
@@ -649,15 +612,14 @@ Functions with identical signatures to encoding/json include:
 __Default Mode__  
 
 If default options are acceptable, package level functions can be used for encoding and decoding.
+```
+b, err := cbor.Marshal(v)
 
-```go
-b, err := cbor.Marshal(v)        // encode v to []byte b
-
-err := cbor.Unmarshal(b, &v)     // decode []byte b to v
+err := cbor.Unmarshal(b, &v)
 
-encoder := cbor.NewEncoder(w)    // create encoder with io.Writer w
+encoder := cbor.NewEncoder(w)
 
-decoder := cbor.NewDecoder(r)    // create decoder with io.Reader r
+decoder := cbor.NewDecoder(r)
 ```
 
 __Modes__
@@ -675,20 +637,21 @@ __Creating and Using Encoding Modes__
 
 EncMode is an interface ([API](#api)) created from EncOptions struct.  EncMode uses immutable options after being created and is safe for concurrent use.  For best performance, EncMode should be reused.
 
-```go
+```
 // Create EncOptions using either struct literal or a function.
 opts := cbor.CanonicalEncOptions()
 
-// If needed, modify opts. For example: opts.Time = cbor.TimeUnix
+// If needed, modify encoding options
+opts.Time = cbor.TimeUnix
 
 // Create reusable EncMode interface with immutable options, safe for concurrent use.
 em, err := opts.EncMode()   
 
 // Use EncMode like encoding/json, with same function signatures.
-b, err := em.Marshal(v)      // encode v to []byte b
-
-encoder := em.NewEncoder(w)  // create encoder with io.Writer w
-err := encoder.Encode(v)     // encode v to io.Writer w
+b, err := em.Marshal(v)
+// or
+encoder := em.NewEncoder(w)
+err := encoder.Encode(v)
 ```
 
 __Struct Tags (keyasint, toarray, omitempty)__
@@ -702,8 +665,7 @@ The `keyasint`, `toarray`, and `omitempty` struct tags make it easy to use compa
 <hr>
 
 __Decoding CWT (CBOR Web Token)__ using `keyasint` and `toarray` struct tags:
-
-```go
+```
 // Signed CWT is defined in RFC 8392
 type signedCWT struct {
 	_           struct{} `cbor:",toarray"`
@@ -729,8 +691,7 @@ if err := cbor.Unmarshal(data, &v); err != nil {
 ```
 
 __Encoding CWT (CBOR Web Token)__ using `keyasint` and `toarray` struct tags:
-
-```go
+```
 // Use signedCWT struct defined in "Decoding CWT" example.
 
 var v signedCWT
@@ -741,8 +702,7 @@ if data, err := cbor.Marshal(v); err != nil {
 ```
 
 __Encoding and Decoding CWT (CBOR Web Token) with CBOR Tags__
-
-```go
+```
 // Use signedCWT struct defined in "Decoding CWT" example.
 
 // Create TagSet (safe for concurrency).
@@ -783,10 +743,10 @@ Comparisons are between this newer library and a well-known library that had 1,0
 
 __This library is safer__.  Small malicious CBOR messages are rejected quickly before they exhaust system resources.
 
-|     | fxamacker/cbor 2.1.0 | ugorji/go 1.1.7 |
-| --- | -------------------- | --------------- |
-| Malformed data #1  | 57.4 ns/op, 32 B/op, 1 allocs/op | ⚠️ fatal error: out of memory |
-| Malformed data #2  | 67.7 ns/op, 32 B/op, 1 allocs/op | ⚠️ runtime: out of memory: cannot allocate |
+|                   | fxamacker/cbor 2.1.0             |ugorji/go 1.1.7                   |
+|-------------------|----------------------------------|----------------------------------|
+|Malformed data #1  | 57.4 ns/op, 32 B/op, 1 allocs/op |⚠️ fatal error: out of memory
+|Malformed data #2  | 67.7 ns/op, 32 B/op, 1 allocs/op |⚠️ runtime: out of memory: cannot allocate
 
 &nbsp;
 
@@ -802,10 +762,10 @@ The resource intensive `codec.CborHandle` initialization (in the other library)
 
 __This library uses less memory__ for encoding and decoding CBOR Web Token (CWT) using test data from RFC 8392 A.1.
 
-|     | fxamacker/cbor 2.1.0 | ugorji/go 1.1.7 |
-| --- | -------------------- | --------------- |
-| Encode CWT claims | 176 B/op, 2 allocs/op | 1424 B/op, 4 allocs/op |
-| Decode CWT claims | 176 B/op, 6 allocs/op | 568 B/op, 6 allocs/op |
+|                    | fxamacker/cbor 2.1.0          |ugorji/go 1.1.7                   |
+|--------------------|-------------------------------|----------------------------------|
+|__Encode CWT claims__| 176 B/op, 2 allocs/op | 1424 B/op, 4 allocs/op
+|__Decode CWT claims__| 176 B/op, 6 allocs/op | 568 B/op, 6 allocs/op
 
 Doing your own comparisons is highly recommended.  Use your most common message sizes and data types.
 
diff --git a/decode.go b/decode.go
index 9ec2902..5624cb8 100644
--- a/decode.go
+++ b/decode.go
@@ -740,23 +740,18 @@ func (d *decodeState) parseTextString() ([]byte, error) {
 	}
 	// Process indefinite length string chunks.
 	b := []byte{}
-	var err error
 	for !d.foundBreak() {
 		_, _, val = d.getHead()
 		x := d.data[d.off : d.off+int(val)]
 		d.off += int(val)
 		if !utf8.Valid(x) {
-			err = &SemanticError{"cbor: invalid UTF-8 string"}
-			break
+			for !d.foundBreak() {
+				d.skip() // Skip remaining chunk on error
+			}
+			return nil, &SemanticError{"cbor: invalid UTF-8 string"}
 		}
 		b = append(b, x...)
 	}
-	if err != nil {
-		for !d.foundBreak() {
-			d.skip() // Skip remaining chunk on error
-		}
-		return nil, err
-	}
 	return b, nil
 }
 
@@ -811,26 +806,29 @@ func (d *decodeState) parseArrayToArray(v reflect.Value, tInfo *typeInfo) error
 	_, ai, val := d.getHead()
 	hasSize := (ai != 31)
 	count := int(val)
-	i := 0
+	gi := 0
+	vLen := v.Len()
 	var err error
-	for ; i < v.Len() && ((hasSize && i < count) || (!hasSize && !d.foundBreak())); i++ {
-		if lastErr := d.parseToValue(v.Index(i), tInfo.elemTypeInfo); lastErr != nil {
-			if err == nil {
-				err = lastErr
+	for ci := 0; (hasSize && ci < count) || (!hasSize && !d.foundBreak()); ci++ {
+		if gi < vLen {
+			// Read CBOR array element and set array element
+			if lastErr := d.parseToValue(v.Index(gi), tInfo.elemTypeInfo); lastErr != nil {
+				if err == nil {
+					err = lastErr
+				}
 			}
+			gi++
+		} else {
+			d.skip() // Skip remaining CBOR array element
 		}
 	}
 	// Set remaining Go array elements to zero values.
-	if i < v.Len() {
+	if gi < vLen {
 		zeroV := reflect.Zero(tInfo.elemTypeInfo.typ)
-		for ; i < v.Len(); i++ {
-			v.Index(i).Set(zeroV)
+		for ; gi < vLen; gi++ {
+			v.Index(gi).Set(zeroV)
 		}
 	}
-	// Skip remaining CBOR array elements
-	for ; (hasSize && i < count) || (!hasSize && !d.foundBreak()); i++ {
-		d.skip()
-	}
 	return err
 }
 
@@ -1462,6 +1460,21 @@ func fillByteString(t cborType, val []byte, v reflect.Value) error {
 		v.SetBytes(val)
 		return nil
 	}
+	if v.Kind() == reflect.Array && v.Type().Elem().Kind() == reflect.Uint8 {
+		vLen := v.Len()
+		i := 0
+		for ; i < vLen && i < len(val); i++ {
+			v.Index(i).SetUint(uint64(val[i]))
+		}
+		// Set remaining Go array elements to zero values.
+		if i < vLen {
+			zeroV := reflect.Zero(reflect.TypeOf(byte(0)))
+			for ; i < vLen; i++ {
+				v.Index(i).Set(zeroV)
+			}
+		}
+		return nil
+	}
 	return &UnmarshalTypeError{Value: t.String(), Type: v.Type()}
 }
 


Test patch:
diff --git a/decode_test.go b/decode_test.go
index cc4a7ab..6a8e7e3 100644
--- a/decode_test.go
+++ b/decode_test.go
@@ -32,6 +32,7 @@ var (
 	typeFloat64         = reflect.TypeOf(float64(0))
 	typeString          = reflect.TypeOf("")
 	typeByteSlice       = reflect.TypeOf([]byte(nil))
+	typeByteArray       = reflect.TypeOf([5]byte{})
 	typeIntSlice        = reflect.TypeOf([]int{})
 	typeStringSlice     = reflect.TypeOf([]string{})
 	typeMapStringInt    = reflect.TypeOf(map[string]int{})
@@ -53,111 +54,111 @@ var unmarshalTests = []unmarshalTest{
 		hexDecode("00"),
 		uint64(0),
 		[]interface{}{uint8(0), uint16(0), uint32(0), uint64(0), uint(0), int8(0), int16(0), int32(0), int64(0), int(0), float32(0), float64(0)},
-		[]reflect.Type{typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 	},
 	{
 		hexDecode("01"),
 		uint64(1),
 		[]interface{}{uint8(1), uint16(1), uint32(1), uint64(1), uint(1), int8(1), int16(1), int32(1), int64(1), int(1), float32(1), float64(1)},
-		[]reflect.Type{typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 	},
 	{
 		hexDecode("0a"),
 		uint64(10),
 		[]interface{}{uint8(10), uint16(10), uint32(10), uint64(10), uint(10), int8(10), int16(10), int32(10), int64(10), int(10), float32(10), float64(10)},
-		[]reflect.Type{typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 	},
 	{
 		hexDecode("17"),
 		uint64(23),
 		[]interface{}{uint8(23), uint16(23), uint32(23), uint64(23), uint(23), int8(23), int16(23), int32(23), int64(23), int(23), float32(23), float64(23)},
-		[]reflect.Type{typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 	},
 	{
 		hexDecode("1818"),
 		uint64(24),
 		[]interface{}{uint8(24), uint16(24), uint32(24), uint64(24), uint(24), int8(24), int16(24), int32(24), int64(24), int(24), float32(24), float64(24)},
-		[]reflect.Type{typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 	},
 	{
 		hexDecode("1819"),
 		uint64(25),
 		[]interface{}{uint8(25), uint16(25), uint32(25), uint64(25), uint(25), int8(25), int16(25), int32(25), int64(25), int(25), float32(25), float64(25)},
-		[]reflect.Type{typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 	},
 	{
 		hexDecode("1864"),
 		uint64(100),
 		[]interface{}{uint8(100), uint16(100), uint32(100), uint64(100), uint(100), int8(100), int16(100), int32(100), int64(100), int(100), float32(100), float64(100)},
-		[]reflect.Type{typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 	},
 	{
 		hexDecode("1903e8"),
 		uint64(1000),
 		[]interface{}{uint16(1000), uint32(1000), uint64(1000), uint(1000), int16(1000), int32(1000), int64(1000), int(1000), float32(1000), float64(1000)},
-		[]reflect.Type{typeUint8, typeInt8, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeInt8, typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 	},
 	{
 		hexDecode("1a000f4240"),
 		uint64(1000000),
 		[]interface{}{uint32(1000000), uint64(1000000), uint(1000000), int32(1000000), int64(1000000), int(1000000), float32(1000000), float64(1000000)},
-		[]reflect.Type{typeUint8, typeUint16, typeInt8, typeInt16, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeInt8, typeInt16, typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 	},
 	{
 		hexDecode("1b000000e8d4a51000"),
 		uint64(1000000000000),
 		[]interface{}{uint64(1000000000000), uint(1000000000000), int64(1000000000000), int(1000000000000), float32(1000000000000), float64(1000000000000)},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeInt8, typeInt16, typeInt32, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeInt8, typeInt16, typeInt32, typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 	},
 	{
 		hexDecode("1bffffffffffffffff"),
 		uint64(18446744073709551615),
 		[]interface{}{uint64(18446744073709551615), uint(18446744073709551615), float32(18446744073709551615), float64(18446744073709551615)},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeInt8, typeInt16, typeInt32, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeInt8, typeInt16, typeInt32, typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 	},
 	// negative integer
 	{
 		hexDecode("20"),
 		int64(-1),
 		[]interface{}{int8(-1), int16(-1), int32(-1), int64(-1), int(-1), float32(-1), float64(-1)},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 	},
 	{
 		hexDecode("29"),
 		int64(-10),
 		[]interface{}{int8(-10), int16(-10), int32(-10), int64(-10), int(-10), float32(-10), float64(-10)},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 	},
 	{
 		hexDecode("3863"),
 		int64(-100),
 		[]interface{}{int8(-100), int16(-100), int32(-100), int64(-100), int(-100), float32(-100), float64(-100)},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 	},
 	{
 		hexDecode("3903e7"),
 		int64(-1000),
 		[]interface{}{int16(-1000), int32(-1000), int64(-1000), int(-1000), float32(-1000), float64(-1000)},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 	},
 	// {"3bffffffffffffffff", int64(-18446744073709551616)}, // CBOR value -18446744073709551616 overflows Go's int64, see TestNegIntOverflow
 	// byte string
 	{
 		hexDecode("40"),
 		[]byte{},
-		[]interface{}{[]byte{}},
+		[]interface{}{[]byte{}, [0]byte{}, [1]byte{0}, [5]byte{0, 0, 0, 0, 0}},
 		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 	},
 	{
 		hexDecode("4401020304"),
 		[]byte{1, 2, 3, 4},
-		[]interface{}{[]byte{1, 2, 3, 4}},
+		[]interface{}{[]byte{1, 2, 3, 4}, [0]byte{}, [1]byte{1}, [5]byte{1, 2, 3, 4, 0}},
 		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 	},
 	{
 		hexDecode("5f42010243030405ff"),
 		[]byte{1, 2, 3, 4, 5},
-		[]interface{}{[]byte{1, 2, 3, 4, 5}},
+		[]interface{}{[]byte{1, 2, 3, 4, 5}, [0]byte{}, [1]byte{1}, [5]byte{1, 2, 3, 4, 5}, [6]byte{1, 2, 3, 4, 5, 0}},
 		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 	},
 	// text string
@@ -165,61 +166,61 @@ var unmarshalTests = []unmarshalTest{
 		hexDecode("60"),
 		"",
 		[]interface{}{""},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 	},
 	{
 		hexDecode("6161"),
 		"a",
 		[]interface{}{"a"},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 	},
 	{
 		hexDecode("6449455446"),
 		"IETF",
 		[]interface{}{"IETF"},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 	},
 	{
 		hexDecode("62225c"),
 		"\"\\",
 		[]interface{}{"\"\\"},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 	},
 	{
 		hexDecode("62c3bc"),
 		"ü",
 		[]interface{}{"ü"},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 	},
 	{
 		hexDecode("63e6b0b4"),
 		"水",
 		[]interface{}{"水"},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 	},
 	{
 		hexDecode("64f0908591"),
 		"𐅑",
 		[]interface{}{"𐅑"},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 	},
 	{
 		hexDecode("7f657374726561646d696e67ff"),
 		"streaming",
 		[]interface{}{"streaming"},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 	},
 	// array
 	{
 		hexDecode("80"),
 		[]interface{}{},
-		[]interface{}{[]interface{}{}, []byte{}, []string{}, []int{}, [...]int{}, []float32{}, []float64{}},
+		[]interface{}{[]interface{}{}, []byte{}, []string{}, []int{}, [0]int{}, [1]int{0}, [5]int{0}, []float32{}, []float64{}},
 		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeString, typeBool, typeMapStringInt, typeTag, typeRawTag},
 	},
 	{
 		hexDecode("83010203"),
 		[]interface{}{uint64(1), uint64(2), uint64(3)},
-		[]interface{}{[]interface{}{uint64(1), uint64(2), uint64(3)}, []byte{1, 2, 3}, []int{1, 2, 3}, []uint{1, 2, 3}, [...]int{1, 2, 3}, []float32{1, 2, 3}, []float64{1, 2, 3}},
+		[]interface{}{[]interface{}{uint64(1), uint64(2), uint64(3)}, []byte{1, 2, 3}, []int{1, 2, 3}, []uint{1, 2, 3}, [0]int{}, [1]int{1}, [3]int{1, 2, 3}, [5]int{1, 2, 3, 0, 0}, []float32{1, 2, 3}, []float64{1, 2, 3}},
 		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeString, typeBool, typeStringSlice, typeMapStringInt, reflect.TypeOf([3]string{}), typeTag, typeRawTag},
 	},
 	{
@@ -248,7 +249,10 @@ var unmarshalTests = []unmarshalTest{
 			[]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25},
 			[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25},
 			[]uint{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25},
+			[0]int{},
+			[1]int{1},
 			[...]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25},
+			[30]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0},
 			[]float32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25},
 			[]float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25}},
 		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeString, typeBool, typeStringSlice, typeMapStringInt, reflect.TypeOf([3]string{}), typeTag, typeRawTag},
@@ -256,7 +260,7 @@ var unmarshalTests = []unmarshalTest{
 	{
 		hexDecode("9fff"),
 		[]interface{}{},
-		[]interface{}{[]interface{}{}, []byte{}, []string{}, []int{}, [...]int{}, []float32{}, []float64{}},
+		[]interface{}{[]interface{}{}, []byte{}, []string{}, []int{}, [0]int{}, [1]int{0}, [5]int{0, 0, 0, 0, 0}, []float32{}, []float64{}},
 		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeString, typeBool, typeMapStringInt, typeTag, typeRawTag},
 	},
 	{
@@ -279,7 +283,10 @@ var unmarshalTests = []unmarshalTest{
 			[]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25},
 			[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25},
 			[]uint{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25},
+			[0]int{},
+			[1]int{1},
 			[...]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25},
+			[30]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0},
 			[]float32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25},
 			[]float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25}},
 		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeString, typeBool, typeStringSlice, typeMapStringInt, reflect.TypeOf([3]string{}), typeTag, typeRawTag},
@@ -288,33 +295,33 @@ var unmarshalTests = []unmarshalTest{
 		hexDecode("826161a161626163"),
 		[]interface{}{"a", map[interface{}]interface{}{"b": "c"}},
 		[]interface{}{[]interface{}{"a", map[interface{}]interface{}{"b": "c"}}, [...]interface{}{"a", map[interface{}]interface{}{"b": "c"}}},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeString, typeBool, typeStringSlice, typeMapStringInt, reflect.TypeOf([3]string{}), typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeString, typeBool, typeByteArray, typeStringSlice, typeMapStringInt, reflect.TypeOf([3]string{}), typeTag, typeRawTag},
 	},
 	{
 		hexDecode("826161bf61626163ff"),
 		[]interface{}{"a", map[interface{}]interface{}{"b": "c"}},
 		[]interface{}{[]interface{}{"a", map[interface{}]interface{}{"b": "c"}}, [...]interface{}{"a", map[interface{}]interface{}{"b": "c"}}},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeString, typeBool, typeStringSlice, typeMapStringInt, reflect.TypeOf([3]string{}), typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeString, typeBool, typeByteArray, typeStringSlice, typeMapStringInt, reflect.TypeOf([3]string{}), typeTag, typeRawTag},
 	},
 	// map
 	{
 		hexDecode("a0"),
 		map[interface{}]interface{}{},
 		[]interface{}{map[interface{}]interface{}{}, map[string]bool{}, map[string]int{}, map[int]string{}, map[int]bool{}},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeByteSlice, typeString, typeBool, typeIntSlice, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeByteSlice, typeByteArray, typeString, typeBool, typeIntSlice, typeTag, typeRawTag},
 	},
 	{
 		hexDecode("a201020304"),
 		map[interface{}]interface{}{uint64(1): uint64(2), uint64(3): uint64(4)},
 		[]interface{}{map[interface{}]interface{}{uint64(1): uint64(2), uint64(3): uint64(4)}, map[uint]int{1: 2, 3: 4}, map[int]uint{1: 2, 3: 4}},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeByteSlice, typeByteArray, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 	},
 	{
 		hexDecode("a26161016162820203"),
 		map[interface{}]interface{}{"a": uint64(1), "b": []interface{}{uint64(2), uint64(3)}},
 		[]interface{}{map[interface{}]interface{}{"a": uint64(1), "b": []interface{}{uint64(2), uint64(3)}},
 			map[string]interface{}{"a": uint64(1), "b": []interface{}{uint64(2), uint64(3)}}},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeByteSlice, typeByteArray, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 	},
 	{
 		hexDecode("a56161614161626142616361436164614461656145"),
@@ -322,83 +329,83 @@ var unmarshalTests = []unmarshalTest{
 		[]interface{}{map[interface{}]interface{}{"a": "A", "b": "B", "c": "C", "d": "D", "e": "E"},
 			map[string]interface{}{"a": "A", "b": "B", "c": "C", "d": "D", "e": "E"},
 			map[string]string{"a": "A", "b": "B", "c": "C", "d": "D", "e": "E"}},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeByteSlice, typeByteArray, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 	},
 	{
 		hexDecode("bf61610161629f0203ffff"),
 		map[interface{}]interface{}{"a": uint64(1), "b": []interface{}{uint64(2), uint64(3)}},
 		[]interface{}{map[interface{}]interface{}{"a": uint64(1), "b": []interface{}{uint64(2), uint64(3)}},
 			map[string]interface{}{"a": uint64(1), "b": []interface{}{uint64(2), uint64(3)}}},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeByteSlice, typeByteArray, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 	},
 	{
 		hexDecode("bf6346756ef563416d7421ff"),
 		map[interface{}]interface{}{"Fun": true, "Amt": int64(-2)},
 		[]interface{}{map[interface{}]interface{}{"Fun": true, "Amt": int64(-2)},
 			map[string]interface{}{"Fun": true, "Amt": int64(-2)}},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeByteSlice, typeByteArray, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 	},
 	// tag
 	{
 		hexDecode("c074323031332d30332d32315432303a30343a30305a"),
 		time.Date(2013, 3, 21, 20, 4, 0, 0, time.UTC), // 2013-03-21 20:04:00 +0000 UTC
 		[]interface{}{"2013-03-21T20:04:00Z", time.Date(2013, 3, 21, 20, 4, 0, 0, time.UTC), Tag{0, "2013-03-21T20:04:00Z"}, RawTag{0, hexDecode("74323031332d30332d32315432303a30343a30305a")}},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeIntSlice, typeMapStringInt},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeByteArray, typeIntSlice, typeMapStringInt},
 	}, // 0: standard date/time
 	{
 		hexDecode("c11a514b67b0"),
 		time.Date(2013, 3, 21, 20, 4, 0, 0, time.UTC), // 2013-03-21 20:04:00 +0000 UTC
 		[]interface{}{uint32(1363896240), uint64(1363896240), int32(1363896240), int64(1363896240), float32(1363896240), float64(1363896240), time.Date(2013, 3, 21, 20, 4, 0, 0, time.UTC), Tag{1, uint64(1363896240)}, RawTag{1, hexDecode("1a514b67b0")}},
-		[]reflect.Type{typeUint8, typeUint16, typeInt8, typeInt16, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt},
+		[]reflect.Type{typeUint8, typeUint16, typeInt8, typeInt16, typeByteSlice, typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt},
 	}, // 1: epoch-based date/time
 	{
 		hexDecode("c249010000000000000000"),
 		Tag{2, []byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
-		[]interface{}{[]byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, Tag{2, []byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, RawTag{2, hexDecode("49010000000000000000")}},
+		[]interface{}{[]byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, [0]byte{}, [1]byte{0x01}, [3]byte{0x01, 0x00, 0x00}, [...]byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, [10]byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, Tag{2, []byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, RawTag{2, hexDecode("49010000000000000000")}},
 		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeIntSlice, typeMapStringInt},
 	}, // 2: positive bignum: 18446744073709551616
 	{
 		hexDecode("c349010000000000000000"),
 		Tag{3, []byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
-		[]interface{}{[]byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, Tag{3, []byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, RawTag{3, hexDecode("49010000000000000000")}},
+		[]interface{}{[]byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, [0]byte{}, [1]byte{0x01}, [3]byte{0x01, 0x00, 0x00}, [...]byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, [10]byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, Tag{3, []byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, RawTag{3, hexDecode("49010000000000000000")}},
 		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeIntSlice, typeMapStringInt},
 	}, // 3: negative bignum: -18446744073709551617
 	{
 		hexDecode("c1fb41d452d9ec200000"),
 		time.Date(2013, 3, 21, 20, 4, 0, 500000000, time.UTC), // 2013-03-21 20:04:00.5 +0000 UTC
 		[]interface{}{float32(1363896240.5), float64(1363896240.5), time.Date(2013, 3, 21, 20, 4, 0, 500000000, time.UTC), Tag{1, float64(1363896240.5)}, RawTag{1, hexDecode("fb41d452d9ec200000")}},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteSlice, typeByteArray, typeString, typeBool, typeIntSlice, typeMapStringInt},
 	}, // 1: epoch-based date/time
 	{
 		hexDecode("d74401020304"),
 		Tag{23, []byte{0x01, 0x02, 0x03, 0x04}},
-		[]interface{}{[]byte{0x01, 0x02, 0x03, 0x04}, Tag{23, []byte{0x01, 0x02, 0x03, 0x04}}, RawTag{23, hexDecode("4401020304")}},
+		[]interface{}{[]byte{0x01, 0x02, 0x03, 0x04}, [0]byte{}, [1]byte{0x01}, [3]byte{0x01, 0x02, 0x03}, [...]byte{0x01, 0x02, 0x03, 0x04}, [5]byte{0x01, 0x02, 0x03, 0x04, 0x00}, Tag{23, []byte{0x01, 0x02, 0x03, 0x04}}, RawTag{23, hexDecode("4401020304")}},
 		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeIntSlice, typeMapStringInt},
 	}, // 23: expected conversion to base16 encoding
 	{
 		hexDecode("d818456449455446"),
 		Tag{24, []byte{0x64, 0x49, 0x45, 0x54, 0x46}},
-		[]interface{}{[]byte{0x64, 0x49, 0x45, 0x54, 0x46}, Tag{24, []byte{0x64, 0x49, 0x45, 0x54, 0x46}}, RawTag{24, hexDecode("456449455446")}},
+		[]interface{}{[]byte{0x64, 0x49, 0x45, 0x54, 0x46}, [0]byte{}, [1]byte{0x64}, [3]byte{0x64, 0x49, 0x45}, [...]byte{0x64, 0x49, 0x45, 0x54, 0x46}, [6]byte{0x64, 0x49, 0x45, 0x54, 0x46, 0x00}, Tag{24, []byte{0x64, 0x49, 0x45, 0x54, 0x46}}, RawTag{24, hexDecode("456449455446")}},
 		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeIntSlice, typeMapStringInt},
 	}, // 24: encoded cborBytes data item
 	{
 		hexDecode("d82076687474703a2f2f7777772e6578616d706c652e636f6d"),
 		Tag{32, "http://www.example.com"},
 		[]interface{}{"http://www.example.com", Tag{32, "http://www.example.com"}, RawTag{32, hexDecode("76687474703a2f2f7777772e6578616d706c652e636f6d")}},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeIntSlice, typeMapStringInt},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeByteArray, typeIntSlice, typeMapStringInt},
 	}, // 32: URI
 	// primitives
 	{
 		hexDecode("f4"),
 		false,
 		[]interface{}{false},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeByteSlice, typeString, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeByteArray, typeByteSlice, typeString, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 	},
 	{
 		hexDecode("f5"),
 		true,
 		[]interface{}{true},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeByteSlice, typeString, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeByteArray, typeByteSlice, typeString, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 	},
 	{
 		hexDecode("f6"),
@@ -416,7 +423,7 @@ var unmarshalTests = []unmarshalTest{
 		hexDecode("f0"),
 		uint64(16),
 		[]interface{}{uint8(16), uint16(16), uint32(16), uint64(16), uint(16), int8(16), int16(16), int32(16), int64(16), int(16), float32(16), float64(16)},
-		[]reflect.Type{typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeByteSlice, typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 	},
 	// This example is not well-formed because Simple value (with 5-bit value 24) must be >= 32.
 	// See RFC 7049 section 2.3 for details, instead of the incorrect example in RFC 7049 Appendex A.
@@ -433,44 +440,44 @@ var unmarshalTests = []unmarshalTest{
 		hexDecode("f820"),
 		uint64(32),
 		[]interface{}{uint8(32), uint16(32), uint32(32), uint64(32), uint(32), int8(32), int16(32), int32(32), int64(32), int(32), float32(32), float64(32)},
-		[]reflect.Type{typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeByteSlice, typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 	},
 	{
 		hexDecode("f8ff"),
 		uint64(255),
 		[]interface{}{uint8(255), uint16(255), uint32(255), uint64(255), uint(255), int16(255), int32(255), int64(255), int(255), float32(255), float64(255)},
-		[]reflect.Type{typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeByteSlice, typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 	},
 	// More testcases not covered by https://tools.ietf.org/html/rfc7049#appendix-A.
 	{
 		hexDecode("5fff"), // empty indefinite length byte string
 		[]byte{},
-		[]interface{}{[]byte{}},
+		[]interface{}{[]byte{}, [0]byte{}, [1]byte{0x00}},
 		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 	},
 	{
 		hexDecode("7fff"), // empty indefinite length text string
 		"",
 		[]interface{}{""},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 	},
 	{
 		hexDecode("bfff"), // empty indefinite length map
 		map[interface{}]interface{}{},
 		[]interface{}{map[interface{}]interface{}{}, map[string]bool{}, map[string]int{}, map[int]string{}, map[int]bool{}},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeByteSlice, typeString, typeBool, typeIntSlice, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeTag, typeRawTag},
 	},
 	// More test data with tags
 	{
 		hexDecode("c13a0177f2cf"), // 1969-03-21T20:04:00Z, tag 1 with negative integer as epoch time
 		time.Date(1969, 3, 21, 20, 4, 0, 0, time.UTC),
 		[]interface{}{int32(-24638160), int64(-24638160), int32(-24638160), int64(-24638160), float32(-24638160), float64(-24638160), time.Date(1969, 3, 21, 20, 4, 0, 0, time.UTC), Tag{1, int64(-24638160)}, RawTag{1, hexDecode("3a0177f2cf")}},
-		[]reflect.Type{typeUint8, typeUint16, typeInt8, typeInt16, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt},
+		[]reflect.Type{typeUint8, typeUint16, typeInt8, typeInt16, typeByteSlice, typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt},
 	},
 	{
 		hexDecode("d83dd183010203"), // 61(17([1, 2, 3])), nested tags 61 and 17
 		Tag{61, Tag{17, []interface{}{uint64(1), uint64(2), uint64(3)}}},
-		[]interface{}{[]interface{}{uint64(1), uint64(2), uint64(3)}, []byte{1, 2, 3}, []int{1, 2, 3}, []uint{1, 2, 3}, [...]int{1, 2, 3}, []float32{1, 2, 3}, []float64{1, 2, 3}, Tag{61, Tag{17, []interface{}{uint64(1), uint64(2), uint64(3)}}}, RawTag{61, hexDecode("d183010203")}},
+		[]interface{}{[]interface{}{uint64(1), uint64(2), uint64(3)}, []byte{1, 2, 3}, [0]byte{}, [1]byte{1}, [3]byte{1, 2, 3}, [5]byte{1, 2, 3, 0, 0}, []int{1, 2, 3}, []uint{1, 2, 3}, [...]int{1, 2, 3}, []float32{1, 2, 3}, []float64{1, 2, 3}, Tag{61, Tag{17, []interface{}{uint64(1), uint64(2), uint64(3)}}}, RawTag{61, hexDecode("d183010203")}},
 		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeFloat64, typeString, typeBool, typeStringSlice, typeMapStringInt, reflect.TypeOf([3]string{})},
 	},
 }
@@ -493,77 +500,77 @@ var unmarshalFloatTests = []unmarshalFloatTest{
 		hexDecode("f90000"),
 		float64(0.0),
 		[]interface{}{float32(0.0), float64(0.0)},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 		0.0,
 	},
 	{
 		hexDecode("f98000"),
 		float64(-0.0),
 		[]interface{}{float32(-0.0), float64(-0.0)},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 		0.0,
 	},
 	{
 		hexDecode("f93c00"),
 		float64(1.0),
 		[]interface{}{float32(1.0), float64(1.0)},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 		0.0,
 	},
 	{
 		hexDecode("f93e00"),
 		float64(1.5),
 		[]interface{}{float32(1.5), float64(1.5)},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 		0.0,
 	},
 	{
 		hexDecode("f97bff"),
 		float64(65504.0),
 		[]interface{}{float32(65504.0), float64(65504.0)},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 		0.0,
 	},
 	{
 		hexDecode("f90001"), // float16 subnormal value
 		float64(5.960464477539063e-08),
 		[]interface{}{float32(5.960464477539063e-08), float64(5.960464477539063e-08)},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 		1e-16,
 	},
 	{
 		hexDecode("f90400"),
 		float64(6.103515625e-05),
 		[]interface{}{float32(6.103515625e-05), float64(6.103515625e-05)},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 		1e-16,
 	},
 	{
 		hexDecode("f9c400"),
 		float64(-4.0),
 		[]interface{}{float32(-4.0), float64(-4.0)},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 		0.0,
 	},
 	{
 		hexDecode("f97c00"),
 		math.Inf(1),
 		[]interface{}{math.Float32frombits(0x7f800000), math.Inf(1)},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 		0.0,
 	},
 	{
 		hexDecode("f97e00"),
 		math.NaN(),
 		[]interface{}{math.Float32frombits(0x7fc00000), math.NaN()},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 		0.0,
 	},
 	{
 		hexDecode("f9fc00"),
 		math.Inf(-1),
 		[]interface{}{math.Float32frombits(0xff800000), math.Inf(-1)},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 		0.0,
 	},
 	// float32
@@ -571,35 +578,35 @@ var unmarshalFloatTests = []unmarshalFloatTest{
 		hexDecode("fa47c35000"),
 		float64(100000.0),
 		[]interface{}{float32(100000.0), float64(100000.0)},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 		0.0,
 	},
 	{
 		hexDecode("fa7f7fffff"),
 		float64(3.4028234663852886e+38),
 		[]interface{}{float32(3.4028234663852886e+38), float64(3.4028234663852886e+38)},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 		1e-9,
 	},
 	{
 		hexDecode("fa7f800000"),
 		math.Inf(1),
 		[]interface{}{math.Float32frombits(0x7f800000), math.Inf(1)},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 		0.0,
 	},
 	{
 		hexDecode("fa7fc00000"),
 		math.NaN(),
 		[]interface{}{math.Float32frombits(0x7fc00000), math.NaN()},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 		0.0,
 	},
 	{
 		hexDecode("faff800000"),
 		math.Inf(-1),
 		[]interface{}{math.Float32frombits(0xff800000), math.Inf(-1)},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 		0.0,
 	},
 	// float64
@@ -607,42 +614,42 @@ var unmarshalFloatTests = []unmarshalFloatTest{
 		hexDecode("fb3ff199999999999a"),
 		float64(1.1),
 		[]interface{}{float32(1.1), float64(1.1)},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 		1e-9,
 	},
 	{
 		hexDecode("fb7e37e43c8800759c"),
 		float64(1.0e+300),
 		[]interface{}{float64(1.0e+300)},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeFloat32, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 		1e-9,
 	},
 	{
 		hexDecode("fbc010666666666666"),
 		float64(-4.1),
 		[]interface{}{float32(-4.1), float64(-4.1)},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 		1e-9,
 	},
 	{
 		hexDecode("fb7ff0000000000000"),
 		math.Inf(1),
 		[]interface{}{math.Float32frombits(0x7f800000), math.Inf(1)},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 		0.0,
 	},
 	{
 		hexDecode("fb7ff8000000000000"),
 		math.NaN(),
 		[]interface{}{math.Float32frombits(0x7fc00000), math.NaN()},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 		0.0,
 	},
 	{
 		hexDecode("fbfff0000000000000"),
 		math.Inf(-1),
 		[]interface{}{math.Float32frombits(0xff800000), math.Inf(-1)},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 		0.0,
 	},
 
@@ -651,28 +658,28 @@ var unmarshalFloatTests = []unmarshalFloatTest{
 		hexDecode("f903ff"),
 		float64(0.000060976),
 		[]interface{}{float32(0.000060976), float64(0.000060976)},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 		1e-9,
 	},
 	{
 		hexDecode("f93bff"),
 		float64(0.999511719),
 		[]interface{}{float32(0.999511719), float64(0.999511719)},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 		1e-9,
 	},
 	{
 		hexDecode("f93c01"),
 		float64(1.000976563),
 		[]interface{}{float32(1.000976563), float64(1.000976563)},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 		1e-9,
 	},
 	{
 		hexDecode("f93555"),
 		float64(0.333251953125),
 		[]interface{}{float32(0.333251953125), float64(0.333251953125)},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 		1e-9,
 	},
 	// CBOR test data "canonNums" are from https://github.com/cbor-wg/cbor-test-vectors
@@ -680,70 +687,70 @@ var unmarshalFloatTests = []unmarshalFloatTest{
 		hexDecode("f9bd00"),
 		float64(-1.25),
 		[]interface{}{float32(-1.25), float64(-1.25)},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 		0.0,
 	},
 	{
 		hexDecode("f93e00"),
 		float64(1.5),
 		[]interface{}{float32(1.5), float64(1.5)},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 		0.0,
 	},
 	{
 		hexDecode("fb4024333333333333"),
 		float64(10.1),
 		[]interface{}{float32(10.1), float64(10.1)},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 		0.0,
 	},
 	{
 		hexDecode("f90001"),
 		float64(5.960464477539063e-8),
 		[]interface{}{float32(5.960464477539063e-8), float64(5.960464477539063e-8)},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 		0.0,
 	},
 	{
 		hexDecode("fa7f7fffff"),
 		float64(3.4028234663852886e+38),
 		[]interface{}{float32(3.4028234663852886e+38), float64(3.4028234663852886e+38)},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 		0.0,
 	},
 	{
 		hexDecode("f90400"),
 		float64(0.00006103515625),
 		[]interface{}{float32(0.00006103515625), float64(0.00006103515625)},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 		0.0,
 	},
 	{
 		hexDecode("f933ff"),
 		float64(0.2498779296875),
 		[]interface{}{float32(0.2498779296875), float64(0.2498779296875)},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 		0.0,
 	},
 	{
 		hexDecode("fa33000000"),
 		float64(2.9802322387695312e-8),
 		[]interface{}{float32(2.9802322387695312e-8), float64(2.9802322387695312e-8)},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 		0.0,
 	},
 	{
 		hexDecode("fa33333866"),
 		float64(4.1727979294137185e-8),
 		[]interface{}{float32(4.1727979294137185e-8), float64(4.1727979294137185e-8)},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 		0.0,
 	},
 	{
 		hexDecode("fa37002000"),
 		float64(0.000007636845111846924),
 		[]interface{}{float32(0.000007636845111846924), float64(0.000007636845111846924)},
-		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
+		[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag},
 		0.0,
 	},
 }
@@ -3873,3 +3880,39 @@ func TestUnmarshalDupMapKeyToStructTagTypeError(t *testing.T) {
 		t.Errorf("Unmarshal(0x%x) = %+v (%T), want %+v (%T)", cborData, s2, s2, wantS, wantS)
 	}
 }
+
+func TestIndefiniteLengthArrayToArray(t *testing.T) {
+	testCases := []struct {
+		name     string
+		cborData []byte
+		wantV    interface{}
+	}{
+		{
+			name:     "CBOR empty array to Go 5 elem array",
+			cborData: hexDecode("9fff"),
+			wantV:    [5]byte{},
+		},
+		{
+			name:     "CBOR 3 elem array to Go 5 elem array",
+			cborData: hexDecode("9f010203ff"),
+			wantV:    [5]byte{1, 2, 3, 0, 0},
+		},
+		{
+			name:     "CBOR 10 elem array to Go 5 elem array",
+			cborData: hexDecode("9f0102030405060708090aff"),
+			wantV:    [5]byte{1, 2, 3, 4, 5},
+		},
+	}
+
+	for _, tc := range testCases {
+		t.Run(tc.name, func(t *testing.T) {
+			v := reflect.New(reflect.TypeOf(tc.wantV))
+			if err := Unmarshal(tc.cborData, v.Interface()); err != nil {
+				t.Errorf("Unmarshal(0x%x) returned error %v", tc.cborData, err)
+			}
+			if !reflect.DeepEqual(v.Elem().Interface(), tc.wantV) {
+				t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", tc.cborData, v.Elem().Interface(), v.Elem().Interface(), tc.wantV, tc.wantV)
+			}
+		})
+	}
+}