mirror of
https://github.com/containerd/containerd.git
synced 2026-11-06 05:17:02 +00:00
Merge pull request #14174 from thaJeztah/bump_cbor
vendor: github.com/fxamacker/cbor/v2 v2.9.4
This commit is contained in:
9 files changed
+241
-89
No files matched your search
@@ -108,7 +108,7 @@ require (
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.13.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.1.0 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.9.1 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.9.4 // indirect
|
||||
github.com/go-jose/go-jose/v4 v4.1.5 // indirect
|
||||
github.com/go-logr/logr v1.4.4 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
|
||||
@@ -106,8 +106,8 @@ github.com/felixge/httpsnoop v1.1.0 h1:3YtUj32ZZkqZtt3sZZsClsymw/QDuVfpNhoA31zeO
|
||||
github.com/felixge/httpsnoop v1.1.0/go.mod h1:Zqxgdd+1Rkcz8euOqdr7lqgCRJztwr5hp9vDSi5UZCE=
|
||||
github.com/fsnotify/fsnotify v1.10.1 h1:b0/UzAf9yR5rhf3RPm9gf3ehBPpf0oZKIjtpKrx59Ho=
|
||||
github.com/fsnotify/fsnotify v1.10.1/go.mod h1:TLheqan6HD6GBK6PrDWyDPBaEV8LspOxvPSjC+bVfgo=
|
||||
github.com/fxamacker/cbor/v2 v2.9.1 h1:2rWm8B193Ll4VdjsJY28jxs70IdDsHRWgQYAI80+rMQ=
|
||||
github.com/fxamacker/cbor/v2 v2.9.1/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
|
||||
github.com/fxamacker/cbor/v2 v2.9.4 h1:xwjVlxEMR3S605oUlgBjKLTTeGFciYPGYCtF/35LKGo=
|
||||
github.com/fxamacker/cbor/v2 v2.9.4/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
|
||||
github.com/go-jose/go-jose/v4 v4.1.5 h1:RjgjO2LOtWOJKUC5wpwY9LR3B3vwVAz6JS2YHfYU6eA=
|
||||
github.com/go-jose/go-jose/v4 v4.1.5/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
|
||||
+14
-12
@@ -683,7 +683,7 @@ because RFC 8949 treats CBOR data item with remaining bytes as malformed.
|
||||
Other useful functions:
|
||||
- `Diagnose`, `DiagnoseFirst` produce human-readable [Extended Diagnostic Notation](https://www.rfc-editor.org/rfc/rfc8610.html#appendix-G) from CBOR data.
|
||||
- `UnmarshalFirst` decodes first CBOR data item and return any remaining bytes.
|
||||
- `Wellformed` returns true if the CBOR data item is well-formed.
|
||||
- `Wellformed` returns nil error if the CBOR data item is well-formed.
|
||||
|
||||
Interfaces identical or comparable to Go `encoding` packages include:
|
||||
`Marshaler`, `Unmarshaler`, `BinaryMarshaler`, and `BinaryUnmarshaler`.
|
||||
@@ -702,27 +702,29 @@ Default limits may need to be increased for systems handling very large data (e.
|
||||
|
||||
## Status
|
||||
|
||||
v2.9.1 (Mar 29-30, 2026) includes important bugfixes, defensive checks, improved code quality, and more tests. Although not public, the fuzzer was also improved by adding more fuzz tests.
|
||||
v2.9.2 (Sunday, May 3, 2026) refactors and hardens the streaming encoder by adding stricter checks for encoding to CBOR indefinite-length data. This prevents improper use of this library from producing malformed CBOR indefinite-length data that would be rejected by the decoder.
|
||||
|
||||
v2.9.1 passed fuzz tests and is production quality.
|
||||
This release includes other bugfixes, defensive checks, and added more tests.
|
||||
|
||||
The minimum version of Go required to build:
|
||||
- v2.8.0 and newer releases require go 1.20+.
|
||||
- v2.7.1 and older releases require go 1.17+.
|
||||
v2.9.2 passed fuzz tests (billions of executions) and is production quality.
|
||||
|
||||
For more details, see [v2.9.1 release notes](https://github.com/fxamacker/cbor/releases).
|
||||
For more details, see [v2.9.2 release notes](https://github.com/fxamacker/cbor/releases).
|
||||
|
||||
### Prior Releases
|
||||
|
||||
[v2.9.0](https://github.com/fxamacker/cbor/releases/tag/v2.9.0) (Jul 13, 2025) improved interoperability/transcoding between CBOR & JSON, refactored tests, and improved docs. It passed fuzz tests (billions of executions) and is production quality.
|
||||
Releases and commits tend to be on Sundays because my work schedule didn't leave time to work on this during weekdays (sometimes consecutive weekends and consecutive Christmas breaks, too). Monday morning releases were to allow more fuzzing to run overnight before clicking the release button.
|
||||
|
||||
[v2.8.0](https://github.com/fxamacker/cbor/releases/tag/v2.8.0) (March 30, 2025) is a small release primarily to add `omitzero` option to struct field tags and fix bugs. It passed fuzz tests (billions of executions) and is production quality.
|
||||
[v2.9.1](https://github.com/fxamacker/cbor/releases/tag/v2.9.1) (Monday, Mar 30, 2026) includes important bugfixes, defensive checks, improved code quality, and more tests. Although not public, the fuzzer was also improved by adding more fuzz tests. It passed fuzz tests (billions of executions) and is production quality.
|
||||
|
||||
[v2.7.0](https://github.com/fxamacker/cbor/releases/tag/v2.7.0) (June 23, 2024) adds features and improvements that help large projects (e.g. Kubernetes) use CBOR as an alternative to JSON and Protocol Buffers. Other improvements include speedups, improved memory use, bug fixes, new serialization options, etc. It passed fuzz tests (5+ billion executions) and is production quality.
|
||||
[v2.9.0](https://github.com/fxamacker/cbor/releases/tag/v2.9.0) (Sunday, Jul 13, 2025) improved interoperability/transcoding between CBOR & JSON, refactored tests, and improved docs. It passed fuzz tests (billions of executions) and is production quality.
|
||||
|
||||
[v2.6.0](https://github.com/fxamacker/cbor/releases/tag/v2.6.0) (February 2024) adds important new features, optimizations, and bug fixes. It is especially useful to systems that need to convert data between CBOR and JSON. New options and optimizations improve handling of bignum, integers, maps, and strings.
|
||||
[v2.8.0](https://github.com/fxamacker/cbor/releases/tag/v2.8.0) (Sunday, March 30, 2025) is a small release primarily to add `omitzero` option to struct field tags and fix bugs. It passed fuzz tests (billions of executions) and is production quality.
|
||||
|
||||
[v2.5.0](https://github.com/fxamacker/cbor/releases/tag/v2.5.0) was released on Sunday, August 13, 2023 with new features and important bug fixes. It is fuzz tested and production quality after extended beta [v2.5.0-beta](https://github.com/fxamacker/cbor/releases/tag/v2.5.0-beta) (Dec 2022) -> [v2.5.0](https://github.com/fxamacker/cbor/releases/tag/v2.5.0) (Aug 2023).
|
||||
[v2.7.0](https://github.com/fxamacker/cbor/releases/tag/v2.7.0) (Monday, June 23, 2024) adds features and improvements that help large projects (e.g. Kubernetes) use CBOR as an alternative to JSON and Protocol Buffers. Other improvements include speedups, improved memory use, bug fixes, new serialization options, etc. It passed fuzz tests (5+ billion executions) and is production quality.
|
||||
|
||||
[v2.6.0](https://github.com/fxamacker/cbor/releases/tag/v2.6.0) (Sunday, Feb 11, 2024) adds important new features, optimizations, and bug fixes. It is especially useful to systems that need to convert data between CBOR and JSON. New options and optimizations improve handling of bignum, integers, maps, and strings.
|
||||
|
||||
[v2.5.0](https://github.com/fxamacker/cbor/releases/tag/v2.5.0) (Sunday, August 13, 2023) adds new features and important bug fixes. It is fuzz tested and production quality after extended beta [v2.5.0-beta](https://github.com/fxamacker/cbor/releases/tag/v2.5.0-beta) (Dec 2022) -> [v2.5.0](https://github.com/fxamacker/cbor/releases/tag/v2.5.0) (Aug 2023).
|
||||
|
||||
__IMPORTANT__: 👉 Before upgrading from v2.4 or older release, please read the notable changes highlighted in the release notes. v2.5.0 is a large release with bug fixes to error handling for extraneous data in `Unmarshal`, etc. that should be reviewed before upgrading.
|
||||
|
||||
|
||||
+27
-7
@@ -41,13 +41,14 @@ const (
|
||||
)
|
||||
|
||||
type typeInfo struct {
|
||||
elemTypeInfo *typeInfo
|
||||
keyTypeInfo *typeInfo
|
||||
typ reflect.Type
|
||||
kind reflect.Kind
|
||||
nonPtrType reflect.Type
|
||||
nonPtrKind reflect.Kind
|
||||
spclType specialType
|
||||
elemTypeInfo *typeInfo
|
||||
keyTypeInfo *typeInfo
|
||||
typ reflect.Type
|
||||
kind reflect.Kind
|
||||
nonPtrType reflect.Type
|
||||
nonPtrKind reflect.Kind
|
||||
spclType specialType
|
||||
keyNeedsHashableValueCheck bool
|
||||
}
|
||||
|
||||
func newTypeInfo(t reflect.Type) *typeInfo {
|
||||
@@ -85,12 +86,31 @@ func newTypeInfo(t reflect.Type) *typeInfo {
|
||||
tInfo.elemTypeInfo = getTypeInfo(t.Elem())
|
||||
case reflect.Map:
|
||||
tInfo.keyTypeInfo = getTypeInfo(t.Key())
|
||||
tInfo.keyNeedsHashableValueCheck = needsHashableValueCheck(t.Key())
|
||||
tInfo.elemTypeInfo = getTypeInfo(t.Elem())
|
||||
}
|
||||
|
||||
return &tInfo
|
||||
}
|
||||
|
||||
// needsHashableValueCheck returns true if the hashability of a value of
|
||||
// the given type can't be determined by the static type.
|
||||
func needsHashableValueCheck(typ reflect.Type) bool {
|
||||
switch typ.Kind() {
|
||||
case reflect.Interface:
|
||||
return true
|
||||
case reflect.Array:
|
||||
return needsHashableValueCheck(typ.Elem())
|
||||
case reflect.Struct:
|
||||
for i := 0; i < typ.NumField(); i++ {
|
||||
if needsHashableValueCheck(typ.Field(i).Type) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type decodingStructType struct {
|
||||
fields decodingFields
|
||||
fieldIndicesByName map[string]int // Only populated if toArray is false
|
||||
|
||||
+45
-19
@@ -1769,6 +1769,7 @@ func (d *decoder) parseToTime() (time.Time, bool, error) {
|
||||
}
|
||||
return t, true, nil
|
||||
}
|
||||
d.skip()
|
||||
return time.Time{}, false, &UnmarshalTypeError{CBORType: t.String(), GoType: typeTime.String()}
|
||||
|
||||
case cborTypeTextString:
|
||||
@@ -1845,6 +1846,7 @@ func (d *decoder) parseToTime() (time.Time, bool, error) {
|
||||
return time.Unix(int64(seconds), int64(fractional*1e9)), true, nil
|
||||
|
||||
default:
|
||||
d.skip()
|
||||
return time.Time{}, false, &UnmarshalTypeError{CBORType: t.String(), GoType: typeTime.String()}
|
||||
}
|
||||
}
|
||||
@@ -2263,7 +2265,7 @@ func (d *decoder) applyByteStringTextConversion(
|
||||
default:
|
||||
// If this happens, there is a bug: the decoder has pushed an invalid
|
||||
// "expected later encoding" tag to the stack.
|
||||
panic(fmt.Sprintf("unrecognized expected later encoding tag: %d", d.expectedLaterEncodingTags))
|
||||
panic(fmt.Sprintf("unrecognized expected later encoding tag: %d", d.expectedLaterEncodingTags[len(d.expectedLaterEncodingTags)-1]))
|
||||
}
|
||||
|
||||
case reflect.Slice:
|
||||
@@ -2486,7 +2488,6 @@ func (d *decoder) parseMapToMap(v reflect.Value, tInfo *typeInfo) error { //noli
|
||||
keyType, eleType := tInfo.keyTypeInfo.typ, tInfo.elemTypeInfo.typ
|
||||
reuseKey, reuseEle := isImmutableKind(tInfo.keyTypeInfo.kind), isImmutableKind(tInfo.elemTypeInfo.kind)
|
||||
var keyValue, eleValue reflect.Value
|
||||
keyIsInterfaceType := keyType == typeIntf // If key type is interface{}, need to check if key value is hashable.
|
||||
var err, lastErr error
|
||||
keyCount := v.Len()
|
||||
var existingKeys map[any]bool // Store existing map keys, used for detecting duplicate map key.
|
||||
@@ -2515,22 +2516,28 @@ func (d *decoder) parseMapToMap(v reflect.Value, tInfo *typeInfo) error { //noli
|
||||
}
|
||||
|
||||
// Detect if CBOR map key can be used as Go map key.
|
||||
if keyIsInterfaceType && keyValue.Elem().IsValid() {
|
||||
if !isHashableValue(keyValue.Elem()) {
|
||||
var converted bool
|
||||
if d.dm.mapKeyByteString == MapKeyByteStringAllowed {
|
||||
var k any
|
||||
k, converted = convertByteSliceToByteString(keyValue.Elem().Interface())
|
||||
if converted {
|
||||
keyValue.Set(reflect.ValueOf(k))
|
||||
if tInfo.keyNeedsHashableValueCheck {
|
||||
containedKeyValue := keyValue
|
||||
if keyValue.Kind() == reflect.Interface {
|
||||
containedKeyValue = keyValue.Elem()
|
||||
}
|
||||
if containedKeyValue.IsValid() {
|
||||
if !isHashableValue(containedKeyValue) {
|
||||
var converted bool
|
||||
if d.dm.mapKeyByteString == MapKeyByteStringAllowed {
|
||||
var k any
|
||||
k, converted = convertByteSliceToByteString(containedKeyValue.Interface())
|
||||
if converted {
|
||||
keyValue.Set(reflect.ValueOf(k))
|
||||
}
|
||||
}
|
||||
}
|
||||
if !converted {
|
||||
if err == nil {
|
||||
err = &InvalidMapKeyTypeError{keyValue.Elem().Type().String()}
|
||||
if !converted {
|
||||
if err == nil {
|
||||
err = &InvalidMapKeyTypeError{containedKeyValue.Type().String()}
|
||||
}
|
||||
d.skip()
|
||||
continue
|
||||
}
|
||||
d.skip()
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3044,7 +3051,6 @@ func (d *decoder) nextCBORNil() bool {
|
||||
type jsonUnmarshaler interface{ UnmarshalJSON([]byte) error }
|
||||
|
||||
var (
|
||||
typeIntf = reflect.TypeOf([]any(nil)).Elem()
|
||||
typeTime = reflect.TypeOf(time.Time{})
|
||||
typeBigInt = reflect.TypeOf(big.Int{})
|
||||
typeUnmarshaler = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
|
||||
@@ -3265,15 +3271,35 @@ func isHashableValue(rv reflect.Value) bool {
|
||||
case reflect.Slice, reflect.Map, reflect.Func:
|
||||
return false
|
||||
|
||||
case reflect.Struct:
|
||||
switch rv.Type() {
|
||||
case reflect.Struct, reflect.Interface:
|
||||
switch rt := rv.Type(); rt {
|
||||
case typeTag:
|
||||
tag := rv.Interface().(Tag)
|
||||
return isHashableValue(reflect.ValueOf(tag.Content))
|
||||
case typeTime:
|
||||
return true
|
||||
case typeBigInt:
|
||||
return false
|
||||
default:
|
||||
// Both Type.Comparable() and Value.Comparable() checks are needed.
|
||||
// - Type.Comparable() returns true for interface types, so
|
||||
// Value.Comparable() is needed to check the dynamic value.
|
||||
// - Value.Comparable() returns true for zero-length array of interface,
|
||||
// array, or struct type (as of go1.27.1), so Type.Comparable() is
|
||||
// needed to reject zero-length array of uncomparable type.
|
||||
return rt.Comparable() && rv.Comparable()
|
||||
}
|
||||
|
||||
case reflect.Array:
|
||||
switch rt := rv.Type(); rt.Elem().Kind() {
|
||||
case reflect.Slice, reflect.Map, reflect.Func:
|
||||
return false
|
||||
|
||||
case reflect.Struct, reflect.Array, reflect.Interface:
|
||||
return rt.Comparable() && rv.Comparable()
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
+15
-5
@@ -56,20 +56,30 @@ modes won't accidentally change at runtime after they're created.
|
||||
|
||||
Modes are intended to be reused and are safe for concurrent use.
|
||||
|
||||
EncMode and DecMode Interfaces
|
||||
EncMode, UserBufferEncMode, and DecMode Interfaces
|
||||
|
||||
// EncMode interface uses immutable options and is safe for concurrent use.
|
||||
type EncMode interface {
|
||||
Marshal(v interface{}) ([]byte, error)
|
||||
Marshal(v any) ([]byte, error)
|
||||
NewEncoder(w io.Writer) *Encoder
|
||||
EncOptions() EncOptions // returns copy of options
|
||||
EncOptions() EncOptions
|
||||
}
|
||||
|
||||
// UserBufferEncMode extends EncMode with MarshalToBuffer, which supports
|
||||
// user specified buffer rather than encoding into the built-in buffer pool.
|
||||
type UserBufferEncMode interface {
|
||||
EncMode
|
||||
MarshalToBuffer(v any, buf *bytes.Buffer) error
|
||||
}
|
||||
|
||||
// DecMode interface uses immutable options and is safe for concurrent use.
|
||||
type DecMode interface {
|
||||
Unmarshal(data []byte, v interface{}) error
|
||||
Unmarshal(data []byte, v any) error
|
||||
UnmarshalFirst(data []byte, v any) (rest []byte, err error)
|
||||
Valid(data []byte) error // Deprecated: use Wellformed instead.
|
||||
Wellformed(data []byte) error
|
||||
NewDecoder(r io.Reader) *Decoder
|
||||
DecOptions() DecOptions // returns copy of options
|
||||
DecOptions() DecOptions
|
||||
}
|
||||
|
||||
Using Default Encoding Mode
|
||||
|
||||
+131
-42
@@ -6,6 +6,7 @@ package cbor
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
)
|
||||
@@ -157,11 +158,32 @@ func (dec *Decoder) overwriteBuf(newBuf []byte) {
|
||||
dec.off = 0
|
||||
}
|
||||
|
||||
// indefDataItem tracks open indefinite-length data item during encoding.
|
||||
// typ is the CBOR type of the indefinite-length data item.
|
||||
// count is the number of items written so far.
|
||||
// For indefinite-length maps, count must be even (key/value pairs) when
|
||||
// the container is closed.
|
||||
type indefDataItem struct {
|
||||
typ cborType
|
||||
count int
|
||||
}
|
||||
|
||||
// IndefiniteLengthMapOddItemCountError indicates that EndIndefinite was
|
||||
// called on an open indefinite-length map with an odd number of items.
|
||||
type IndefiniteLengthMapOddItemCountError struct {
|
||||
count int
|
||||
}
|
||||
|
||||
func (e *IndefiniteLengthMapOddItemCountError) Error() string {
|
||||
return fmt.Sprintf("cbor: cannot end indefinite-length map with %d item(s)", e.count)
|
||||
}
|
||||
|
||||
// Encoder writes CBOR values to io.Writer.
|
||||
type Encoder struct {
|
||||
w io.Writer
|
||||
em *encMode
|
||||
indefTypes []cborType
|
||||
w io.Writer
|
||||
em *encMode
|
||||
indefs []indefDataItem
|
||||
scratch [1]byte // reused for single-byte writes (indefinite-length head and break code)
|
||||
}
|
||||
|
||||
// NewEncoder returns a new encoder that writes to w using the default encoding options.
|
||||
@@ -171,37 +193,40 @@ func NewEncoder(w io.Writer) *Encoder {
|
||||
|
||||
// Encode writes the CBOR encoding of v.
|
||||
func (enc *Encoder) Encode(v any) error {
|
||||
if len(enc.indefTypes) > 0 {
|
||||
switch enc.indefTypes[len(enc.indefTypes)-1] {
|
||||
case cborTypeTextString:
|
||||
if v == nil {
|
||||
return errors.New("cbor: cannot encode nil for indefinite-length text string")
|
||||
}
|
||||
k := reflect.TypeOf(v).Kind()
|
||||
if k != reflect.String {
|
||||
return errors.New("cbor: cannot encode item type " + k.String() + " for indefinite-length text string")
|
||||
}
|
||||
case cborTypeByteString:
|
||||
if v == nil {
|
||||
return errors.New("cbor: cannot encode nil for indefinite-length byte string")
|
||||
}
|
||||
t := reflect.TypeOf(v)
|
||||
k := t.Kind()
|
||||
if (k != reflect.Array && k != reflect.Slice) || t.Elem().Kind() != reflect.Uint8 {
|
||||
return errors.New("cbor: cannot encode item type " + k.String() + " for indefinite-length byte string")
|
||||
}
|
||||
if len(enc.indefs) > 0 {
|
||||
err := validateIndefiniteLengthChunkByType(enc.indefs[len(enc.indefs)-1].typ, v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
buf := getEncodeBuffer()
|
||||
|
||||
err := encode(buf, enc.em, reflect.ValueOf(v))
|
||||
|
||||
// Validate the encoded chunk against the indefinite-length data item using a byte-based check.
|
||||
// This reliably detects chunks from cbor.Marshaler, registered tags, StringToByteString, etc.,
|
||||
// which may produce a chunk inconsistent with the parent's major type.
|
||||
// Applies only to indefinite-length byte/text string parents (RFC 8949 Section 3.2.3).
|
||||
if err == nil && len(enc.indefs) > 0 {
|
||||
err = validateIndefiniteLengthChunkByData(enc.indefs[len(enc.indefs)-1].typ, buf.Bytes(), v)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
_, err = enc.w.Write(buf.Bytes())
|
||||
}
|
||||
|
||||
putEncodeBuffer(buf)
|
||||
return err
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(enc.indefs) > 0 {
|
||||
enc.indefs[len(enc.indefs)-1].count++
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// StartIndefiniteByteString starts indefinite-length byte string encoding.
|
||||
@@ -233,37 +258,101 @@ func (enc *Encoder) StartIndefiniteMap() error {
|
||||
}
|
||||
|
||||
// EndIndefinite closes last opened indefinite-length value.
|
||||
// It returns *IndefiniteLengthMapOddItemCountError without writing the
|
||||
// "break" code if the open indefinite-length map has an odd number of
|
||||
// items; the encoder state is unchanged so the caller can write the
|
||||
// missing value and retry.
|
||||
func (enc *Encoder) EndIndefinite() error {
|
||||
if len(enc.indefTypes) == 0 {
|
||||
if len(enc.indefs) == 0 {
|
||||
return errors.New("cbor: cannot encode \"break\" code outside indefinite length values")
|
||||
}
|
||||
_, err := enc.w.Write([]byte{cborBreakFlag})
|
||||
if err == nil {
|
||||
enc.indefTypes = enc.indefTypes[:len(enc.indefTypes)-1]
|
||||
|
||||
// Verify that indefinite-length map has even number of elements
|
||||
top := enc.indefs[len(enc.indefs)-1]
|
||||
if top.typ == cborTypeMap && top.count%2 != 0 {
|
||||
return &IndefiniteLengthMapOddItemCountError{count: top.count}
|
||||
}
|
||||
return err
|
||||
|
||||
// Write break code
|
||||
enc.scratch[0] = cborBreakFlag
|
||||
_, err := enc.w.Write(enc.scratch[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
enc.indefs = enc.indefs[:len(enc.indefs)-1]
|
||||
|
||||
// Increment parent container's item count because the child
|
||||
// (indefinite-length data item) is fully written to the stream.
|
||||
if len(enc.indefs) > 0 {
|
||||
enc.indefs[len(enc.indefs)-1].count++
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (enc *Encoder) startIndefinite(typ cborType) error {
|
||||
if enc.em.indefLength == IndefLengthForbidden {
|
||||
return &IndefiniteLengthError{typ}
|
||||
}
|
||||
var head byte
|
||||
switch typ {
|
||||
case cborTypeByteString:
|
||||
head = cborByteStringWithIndefiniteLengthHead
|
||||
case cborTypeTextString:
|
||||
head = cborTextStringWithIndefiniteLengthHead
|
||||
case cborTypeArray:
|
||||
head = cborArrayWithIndefiniteLengthHead
|
||||
case cborTypeMap:
|
||||
head = cborMapWithIndefiniteLengthHead
|
||||
|
||||
// Verify that new indefinite-length data item is not a chunk in indefinite-length byte/text string.
|
||||
if len(enc.indefs) > 0 {
|
||||
parent := enc.indefs[len(enc.indefs)-1].typ
|
||||
if parent == cborTypeByteString || parent == cborTypeTextString {
|
||||
return errors.New("cbor: cannot encode indefinite-length " + typ.String() +
|
||||
" as chunk of indefinite-length " + parent.String())
|
||||
}
|
||||
}
|
||||
_, err := enc.w.Write([]byte{head})
|
||||
if err == nil {
|
||||
enc.indefTypes = append(enc.indefTypes, typ)
|
||||
|
||||
// Write indefinite-length head.
|
||||
enc.scratch[0] = byte(typ) | additionalInformationAsIndefiniteLengthFlag
|
||||
_, err := enc.w.Write(enc.scratch[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
|
||||
enc.indefs = append(enc.indefs, indefDataItem{typ: typ})
|
||||
return nil
|
||||
}
|
||||
|
||||
// validateIndefiniteLengthChunkByType rejects chunks based solely on their Go type.
|
||||
func validateIndefiniteLengthChunkByType(indefiniteLengthCborType cborType, v any) error {
|
||||
if indefiniteLengthCborType != cborTypeByteString &&
|
||||
indefiniteLengthCborType != cborTypeTextString {
|
||||
return nil
|
||||
}
|
||||
if v == nil {
|
||||
return errors.New("cbor: cannot encode nil for indefinite-length " + indefiniteLengthCborType.String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// validateIndefiniteLengthChunkByData checks that chunk is a definite-length
|
||||
// CBOR data item with a matching major type.
|
||||
// No-op for indefinite-length array/map, where any data item is valid.
|
||||
func validateIndefiniteLengthChunkByData(indefiniteLengthCborType cborType, chunk []byte, v any) error {
|
||||
if indefiniteLengthCborType != cborTypeByteString &&
|
||||
indefiniteLengthCborType != cborTypeTextString {
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(chunk) == 0 {
|
||||
return errors.New("cbor: cannot encode item type " + reflect.TypeOf(v).Kind().String() +
|
||||
" for indefinite-length " + indefiniteLengthCborType.String())
|
||||
}
|
||||
|
||||
t, ai := parseInitialByte(chunk[0])
|
||||
if t != indefiniteLengthCborType {
|
||||
return errors.New("cbor: cannot encode item type " + reflect.TypeOf(v).Kind().String() +
|
||||
" for indefinite-length " + indefiniteLengthCborType.String())
|
||||
}
|
||||
|
||||
if ai == additionalInformationAsIndefiniteLengthFlag {
|
||||
return errors.New("cbor: cannot encode indefinite-length " + indefiniteLengthCborType.String() +
|
||||
" as chunk of indefinite-length " + indefiniteLengthCborType.String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RawMessage is a raw encoded CBOR value.
|
||||
|
||||
+5
@@ -155,6 +155,7 @@ type TagSet interface {
|
||||
Add(opts TagOptions, contentType reflect.Type, num uint64, nestedNum ...uint64) error
|
||||
|
||||
// Remove removes given tag content type from TagSet.
|
||||
// Remove is a no-op if contentType is nil.
|
||||
Remove(contentType reflect.Type)
|
||||
|
||||
tagProvider
|
||||
@@ -245,7 +246,11 @@ func (t *syncTagSet) Add(opts TagOptions, contentType reflect.Type, num uint64,
|
||||
}
|
||||
|
||||
// Remove removes given tag content type from TagSet.
|
||||
// Remove is a no-op if contentType is nil.
|
||||
func (t *syncTagSet) Remove(contentType reflect.Type) {
|
||||
if contentType == nil {
|
||||
return
|
||||
}
|
||||
for contentType.Kind() == reflect.Pointer {
|
||||
contentType = contentType.Elem()
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -353,7 +353,7 @@ github.com/felixge/httpsnoop
|
||||
## explicit; go 1.23
|
||||
github.com/fsnotify/fsnotify
|
||||
github.com/fsnotify/fsnotify/internal
|
||||
# github.com/fxamacker/cbor/v2 v2.9.1
|
||||
# github.com/fxamacker/cbor/v2 v2.9.4
|
||||
## explicit; go 1.20
|
||||
github.com/fxamacker/cbor/v2
|
||||
# github.com/go-jose/go-jose/v4 v4.1.5
|
||||
|
||||
Reference in new issue
Block a user