Compare commits
6 Commits
feature/cb
...
release-2.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
948c054444 | ||
|
|
608e40e88e | ||
|
|
efbaf6c3a0 | ||
|
|
c3ffc7a1de | ||
|
|
8a96f6d88c | ||
|
|
19b7fb6109 |
2
.github/workflows/ci-go-cover.yml
vendored
2
.github/workflows/ci-go-cover.yml
vendored
@ -38,7 +38,7 @@ jobs:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
|
||||
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
|
||||
with:
|
||||
go-version: 1.21
|
||||
check-latest: true
|
||||
|
||||
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
@ -26,10 +26,10 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [macos-latest, ubuntu-latest, windows-latest]
|
||||
go-version: [1.17, 1.18, 1.19, '1.20', 1.21, 1.22, 1.23]
|
||||
go-version: [1.17, 1.19, '1.20', 1.21, 1.22]
|
||||
steps:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
|
||||
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
check-latest: true
|
||||
|
||||
6
.github/workflows/codeql-analysis.yml
vendored
6
.github/workflows/codeql-analysis.yml
vendored
@ -32,14 +32,14 @@ jobs:
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@4dd16135b69a43b6c8efb853346f8437d92d3c93 # v3.26.6
|
||||
uses: github/codeql-action/init@23acc5c183826b7a8a97bce3cecc52db901f8251 # v3.25.10
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@4dd16135b69a43b6c8efb853346f8437d92d3c93 # v3.26.6
|
||||
uses: github/codeql-action/autobuild@23acc5c183826b7a8a97bce3cecc52db901f8251 # v3.25.10
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@4dd16135b69a43b6c8efb853346f8437d92d3c93 # v3.26.6
|
||||
uses: github/codeql-action/analyze@23acc5c183826b7a8a97bce3cecc52db901f8251 # v3.25.10
|
||||
|
||||
4
.github/workflows/govulncheck.yml
vendored
4
.github/workflows/govulncheck.yml
vendored
@ -37,11 +37,11 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
|
||||
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
|
||||
with:
|
||||
go-version: 1.21.x
|
||||
check-latest: true
|
||||
- name: Install latest from golang.org
|
||||
run: go install golang.org/x/vuln/cmd/govulncheck@4ea4418106cea3bb2c9aa098527c924e9e1fbbb4 # v1.1.3
|
||||
run: go install golang.org/x/vuln/cmd/govulncheck@5507063454b1b8c930db99818a88b52f1f143418 # v1.0.4
|
||||
- name: Run govulncheck
|
||||
run: govulncheck -show=traces ./...
|
||||
|
||||
2
.github/workflows/safer-golangci-lint.yml
vendored
2
.github/workflows/safer-golangci-lint.yml
vendored
@ -37,7 +37,7 @@ jobs:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
|
||||
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
check-latest: true
|
||||
|
||||
@ -38,11 +38,38 @@ func (bs ByteString) MarshalCBOR() ([]byte, error) {
|
||||
|
||||
// UnmarshalCBOR decodes CBOR byte string (major type 2) to ByteString.
|
||||
// Decoding CBOR null and CBOR undefined sets ByteString to be empty.
|
||||
//
|
||||
// Deprecated: No longer used by this codec; kept for compatibility
|
||||
// with user apps that directly call this function.
|
||||
func (bs *ByteString) UnmarshalCBOR(data []byte) error {
|
||||
if bs == nil {
|
||||
return errors.New("cbor.ByteString: UnmarshalCBOR on nil pointer")
|
||||
}
|
||||
|
||||
d := decoder{data: data, dm: defaultDecMode}
|
||||
|
||||
// Check well-formedness of CBOR data item.
|
||||
// ByteString.UnmarshalCBOR() is exported, so
|
||||
// the codec needs to support same behavior for:
|
||||
// - Unmarshal(data, *ByteString)
|
||||
// - ByteString.UnmarshalCBOR(data)
|
||||
err := d.wellformed(false, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return bs.unmarshalCBOR(data)
|
||||
}
|
||||
|
||||
// unmarshalCBOR decodes CBOR byte string (major type 2) to ByteString.
|
||||
// Decoding CBOR null and CBOR undefined sets ByteString to be empty.
|
||||
// This function assumes data is well-formed, and does not perform bounds checking.
|
||||
// This function is called by Unmarshal().
|
||||
func (bs *ByteString) unmarshalCBOR(data []byte) error {
|
||||
if bs == nil {
|
||||
return errors.New("cbor.ByteString: UnmarshalCBOR on nil pointer")
|
||||
}
|
||||
|
||||
// Decoding CBOR null and CBOR undefined to ByteString resets data.
|
||||
// This behavior is similar to decoding CBOR null and CBOR undefined to []byte.
|
||||
if len(data) == 1 && (data[0] == 0xf6 || data[0] == 0xf7) {
|
||||
|
||||
@ -3,7 +3,11 @@
|
||||
|
||||
package cbor
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"io"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestByteString(t *testing.T) {
|
||||
type s1 struct {
|
||||
@ -99,3 +103,110 @@ func TestByteString(t *testing.T) {
|
||||
dm, _ := DecOptions{}.DecMode()
|
||||
testRoundTrip(t, testCases, em, dm)
|
||||
}
|
||||
|
||||
func TestUnmarshalByteStringOnBadData(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
data []byte
|
||||
errMsg string
|
||||
}{
|
||||
// Empty data
|
||||
{
|
||||
name: "nil data",
|
||||
data: nil,
|
||||
errMsg: io.EOF.Error(),
|
||||
},
|
||||
{
|
||||
name: "empty data",
|
||||
data: []byte{},
|
||||
errMsg: io.EOF.Error(),
|
||||
},
|
||||
|
||||
// Wrong CBOR types
|
||||
{
|
||||
name: "uint type",
|
||||
data: hexDecode("01"),
|
||||
errMsg: "cbor: cannot unmarshal positive integer into Go value of type cbor.ByteString",
|
||||
},
|
||||
{
|
||||
name: "int type",
|
||||
data: hexDecode("20"),
|
||||
errMsg: "cbor: cannot unmarshal negative integer into Go value of type cbor.ByteString",
|
||||
},
|
||||
{
|
||||
name: "string type",
|
||||
data: hexDecode("60"),
|
||||
errMsg: "cbor: cannot unmarshal UTF-8 text string into Go value of type cbor.ByteString",
|
||||
},
|
||||
{
|
||||
name: "array type",
|
||||
data: hexDecode("80"),
|
||||
errMsg: "cbor: cannot unmarshal array into Go value of type cbor.ByteString",
|
||||
},
|
||||
{
|
||||
name: "map type",
|
||||
data: hexDecode("a0"),
|
||||
errMsg: "cbor: cannot unmarshal map into Go value of type cbor.ByteString",
|
||||
},
|
||||
{
|
||||
name: "tag type",
|
||||
data: hexDecode("c074323031332d30332d32315432303a30343a30305a"),
|
||||
errMsg: "cbor: cannot unmarshal tag into Go value of type cbor.ByteString",
|
||||
},
|
||||
{
|
||||
name: "float type",
|
||||
data: hexDecode("f90000"),
|
||||
errMsg: "cbor: cannot unmarshal primitives into Go value of type cbor.ByteString",
|
||||
},
|
||||
|
||||
// Truncated CBOR data
|
||||
{
|
||||
name: "truncated head",
|
||||
data: hexDecode("18"),
|
||||
errMsg: io.ErrUnexpectedEOF.Error(),
|
||||
},
|
||||
|
||||
// Truncated CBOR byte string
|
||||
{
|
||||
name: "truncated byte string",
|
||||
data: hexDecode("44010203"),
|
||||
errMsg: io.ErrUnexpectedEOF.Error(),
|
||||
},
|
||||
|
||||
// Extraneous CBOR data
|
||||
{
|
||||
name: "extraneous data",
|
||||
data: hexDecode("c074323031332d30332d32315432303a30343a30305a00"),
|
||||
errMsg: "cbor: 1 bytes of extraneous data starting at index 22",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
// Test ByteString.UnmarshalCBOR(data)
|
||||
{
|
||||
var v ByteString
|
||||
|
||||
err := v.UnmarshalCBOR(tc.data)
|
||||
if err == nil {
|
||||
t.Errorf("UnmarshalCBOR(%x) didn't return error", tc.data)
|
||||
}
|
||||
if !strings.HasPrefix(err.Error(), tc.errMsg) {
|
||||
t.Errorf("UnmarshalCBOR(%x) returned error %q, want %q", tc.data, err.Error(), tc.errMsg)
|
||||
}
|
||||
}
|
||||
// Test Unmarshal(data, *ByteString), which calls ByteString.unmarshalCBOR() under the hood
|
||||
{
|
||||
var v ByteString
|
||||
|
||||
err := Unmarshal(tc.data, &v)
|
||||
if err == nil {
|
||||
t.Errorf("Unmarshal(%x) didn't return error", tc.data)
|
||||
}
|
||||
if !strings.HasPrefix(err.Error(), tc.errMsg) {
|
||||
t.Errorf("Unmarshal(%x) returned error %q, want %q", tc.data, err.Error(), tc.errMsg)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
3
cache.go
3
cache.go
@ -31,6 +31,7 @@ type specialType int
|
||||
const (
|
||||
specialTypeNone specialType = iota
|
||||
specialTypeUnmarshalerIface
|
||||
specialTypeUnexportedUnmarshalerIface
|
||||
specialTypeEmptyIface
|
||||
specialTypeIface
|
||||
specialTypeTag
|
||||
@ -69,6 +70,8 @@ func newTypeInfo(t reflect.Type) *typeInfo {
|
||||
tInfo.spclType = specialTypeTag
|
||||
} else if t == typeTime {
|
||||
tInfo.spclType = specialTypeTime
|
||||
} else if reflect.PtrTo(t).Implements(typeUnexportedUnmarshaler) {
|
||||
tInfo.spclType = specialTypeUnexportedUnmarshalerIface
|
||||
} else if reflect.PtrTo(t).Implements(typeUnmarshaler) {
|
||||
tInfo.spclType = specialTypeUnmarshalerIface
|
||||
}
|
||||
|
||||
49
decode.go
49
decode.go
@ -151,6 +151,10 @@ type Unmarshaler interface {
|
||||
UnmarshalCBOR([]byte) error
|
||||
}
|
||||
|
||||
type unmarshaler interface {
|
||||
unmarshalCBOR([]byte) error
|
||||
}
|
||||
|
||||
// InvalidUnmarshalError describes an invalid argument passed to Unmarshal.
|
||||
type InvalidUnmarshalError struct {
|
||||
s string
|
||||
@ -960,6 +964,10 @@ const (
|
||||
defaultMaxMapPairs = 131072
|
||||
minMaxMapPairs = 16
|
||||
maxMaxMapPairs = 2147483647
|
||||
|
||||
defaultMaxNestedLevels = 32
|
||||
minMaxNestedLevels = 4
|
||||
maxMaxNestedLevels = 65535
|
||||
)
|
||||
|
||||
var defaultSimpleValues = func() *SimpleValueRegistry {
|
||||
@ -1382,7 +1390,8 @@ func (d *decoder) parseToValue(v reflect.Value, tInfo *typeInfo) error { //nolin
|
||||
|
||||
registeredType := d.dm.tags.getTypeFromTagNum(tagNums)
|
||||
if registeredType != nil {
|
||||
if implements(registeredType, tInfo.nonPtrType) {
|
||||
if registeredType.Implements(tInfo.nonPtrType) ||
|
||||
reflect.PtrTo(registeredType).Implements(tInfo.nonPtrType) {
|
||||
v.Set(reflect.New(registeredType))
|
||||
v = v.Elem()
|
||||
tInfo = getTypeInfo(registeredType)
|
||||
@ -1455,6 +1464,9 @@ func (d *decoder) parseToValue(v reflect.Value, tInfo *typeInfo) error { //nolin
|
||||
|
||||
case specialTypeUnmarshalerIface:
|
||||
return d.parseToUnmarshaler(v)
|
||||
|
||||
case specialTypeUnexportedUnmarshalerIface:
|
||||
return d.parseToUnexportedUnmarshaler(v)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1800,6 +1812,26 @@ func (d *decoder) parseToUnmarshaler(v reflect.Value) error {
|
||||
return errors.New("cbor: failed to assert " + v.Type().String() + " as cbor.Unmarshaler")
|
||||
}
|
||||
|
||||
// parseToUnexportedUnmarshaler parses CBOR data to value implementing unmarshaler interface.
|
||||
// It assumes data is well-formed, and does not perform bounds checking.
|
||||
func (d *decoder) parseToUnexportedUnmarshaler(v reflect.Value) error {
|
||||
if d.nextCBORNil() && v.Kind() == reflect.Ptr && v.IsNil() {
|
||||
d.skip()
|
||||
return nil
|
||||
}
|
||||
|
||||
if v.Kind() != reflect.Ptr && v.CanAddr() {
|
||||
v = v.Addr()
|
||||
}
|
||||
if u, ok := v.Interface().(unmarshaler); ok {
|
||||
start := d.off
|
||||
d.skip()
|
||||
return u.unmarshalCBOR(d.data[start:d.off])
|
||||
}
|
||||
d.skip()
|
||||
return errors.New("cbor: failed to assert " + v.Type().String() + " as cbor.unmarshaler")
|
||||
}
|
||||
|
||||
// parse parses CBOR data and returns value in default Go type.
|
||||
// It assumes data is well-formed, and does not perform bounds checking.
|
||||
func (d *decoder) parse(skipSelfDescribedTag bool) (interface{}, error) { //nolint:gocyclo
|
||||
@ -2964,13 +2996,14 @@ func (d *decoder) nextCBORNil() bool {
|
||||
}
|
||||
|
||||
var (
|
||||
typeIntf = reflect.TypeOf([]interface{}(nil)).Elem()
|
||||
typeTime = reflect.TypeOf(time.Time{})
|
||||
typeBigInt = reflect.TypeOf(big.Int{})
|
||||
typeUnmarshaler = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
|
||||
typeBinaryUnmarshaler = reflect.TypeOf((*encoding.BinaryUnmarshaler)(nil)).Elem()
|
||||
typeString = reflect.TypeOf("")
|
||||
typeByteSlice = reflect.TypeOf([]byte(nil))
|
||||
typeIntf = reflect.TypeOf([]interface{}(nil)).Elem()
|
||||
typeTime = reflect.TypeOf(time.Time{})
|
||||
typeBigInt = reflect.TypeOf(big.Int{})
|
||||
typeUnmarshaler = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
|
||||
typeUnexportedUnmarshaler = reflect.TypeOf((*unmarshaler)(nil)).Elem()
|
||||
typeBinaryUnmarshaler = reflect.TypeOf((*encoding.BinaryUnmarshaler)(nil)).Elem()
|
||||
typeString = reflect.TypeOf("")
|
||||
typeByteSlice = reflect.TypeOf([]byte(nil))
|
||||
)
|
||||
|
||||
func fillNil(_ cborType, v reflect.Value) error {
|
||||
|
||||
@ -1,19 +0,0 @@
|
||||
// Copyright (c) Faye Amacker. All rights reserved.
|
||||
// Licensed under the MIT License. See LICENSE in the project root for license information.
|
||||
|
||||
//go:build !tinygo
|
||||
|
||||
package cbor
|
||||
|
||||
import "reflect"
|
||||
|
||||
const (
|
||||
defaultMaxNestedLevels = 32
|
||||
minMaxNestedLevels = 4
|
||||
maxMaxNestedLevels = 65535
|
||||
)
|
||||
|
||||
func implements(concreteType reflect.Type, interfaceType reflect.Type) bool {
|
||||
return concreteType.Implements(interfaceType) ||
|
||||
reflect.PtrTo(concreteType).Implements(interfaceType)
|
||||
}
|
||||
@ -1,109 +0,0 @@
|
||||
// Copyright (c) Faye Amacker. All rights reserved.
|
||||
// Licensed under the MIT License. See LICENSE in the project root for license information.
|
||||
|
||||
//go:build !tinygo
|
||||
|
||||
package cbor
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestUnmarshalDeepNesting(t *testing.T) {
|
||||
// Construct this object rather than embed such a large constant in the code
|
||||
type TestNode struct {
|
||||
Value int
|
||||
Child *TestNode
|
||||
}
|
||||
n := &TestNode{Value: 0}
|
||||
root := n
|
||||
for i := 0; i < 65534; i++ {
|
||||
child := &TestNode{Value: i}
|
||||
n.Child = child
|
||||
n = child
|
||||
}
|
||||
em, err := EncOptions{}.EncMode()
|
||||
if err != nil {
|
||||
t.Errorf("EncMode() returned error %v", err)
|
||||
}
|
||||
data, err := em.Marshal(root)
|
||||
if err != nil {
|
||||
t.Errorf("Marshal() deeply nested object returned error %v", err)
|
||||
}
|
||||
|
||||
// Try unmarshal it
|
||||
dm, err := DecOptions{MaxNestedLevels: 65535}.DecMode()
|
||||
if err != nil {
|
||||
t.Errorf("DecMode() returned error %v", err)
|
||||
}
|
||||
var readback TestNode
|
||||
err = dm.Unmarshal(data, &readback)
|
||||
if err != nil {
|
||||
t.Errorf("Unmarshal() of deeply nested object returned error: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(root, &readback) {
|
||||
t.Errorf("Unmarshal() of deeply nested object did not match\nGot: %#v\n Want: %#v\n",
|
||||
&readback, root)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnmarshalRegisteredTagToInterface(t *testing.T) {
|
||||
var err error
|
||||
tags := NewTagSet()
|
||||
err = tags.Add(TagOptions{EncTag: EncTagRequired, DecTag: DecTagRequired}, reflect.TypeOf(C{}), 279)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
err = tags.Add(TagOptions{EncTag: EncTagRequired, DecTag: DecTagRequired}, reflect.TypeOf(D{}), 280)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
encMode, _ := PreferredUnsortedEncOptions().EncModeWithTags(tags)
|
||||
decMode, _ := DecOptions{}.DecModeWithTags(tags)
|
||||
|
||||
v1 := A1{Field: &C{Field: 5}}
|
||||
data1, err := encMode.Marshal(v1)
|
||||
if err != nil {
|
||||
t.Fatalf("Marshal(%+v) returned error %v", v1, err)
|
||||
}
|
||||
|
||||
v2 := A2{Fields: []B{&C{Field: 5}, &D{Field: "a"}}}
|
||||
data2, err := encMode.Marshal(v2)
|
||||
if err != nil {
|
||||
t.Fatalf("Marshal(%+v) returned error %v", v2, err)
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
data []byte
|
||||
unmarshalToObj interface{}
|
||||
wantValue interface{}
|
||||
}{
|
||||
{
|
||||
name: "interface type",
|
||||
data: data1,
|
||||
unmarshalToObj: &A1{},
|
||||
wantValue: &v1,
|
||||
},
|
||||
{
|
||||
name: "slice of interface type",
|
||||
data: data2,
|
||||
unmarshalToObj: &A2{},
|
||||
wantValue: &v2,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
err = decMode.Unmarshal(tc.data, tc.unmarshalToObj)
|
||||
if err != nil {
|
||||
t.Errorf("Unmarshal(0x%x) returned error %v", tc.data, err)
|
||||
}
|
||||
if !reflect.DeepEqual(tc.unmarshalToObj, tc.wantValue) {
|
||||
t.Errorf("Unmarshal(0x%x) = %v, want %v", tc.data, tc.unmarshalToObj, tc.wantValue)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -4786,6 +4786,44 @@ func TestUnmarshalIntoMapError(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnmarshalDeepNesting(t *testing.T) {
|
||||
// Construct this object rather than embed such a large constant in the code
|
||||
type TestNode struct {
|
||||
Value int
|
||||
Child *TestNode
|
||||
}
|
||||
n := &TestNode{Value: 0}
|
||||
root := n
|
||||
for i := 0; i < 65534; i++ {
|
||||
child := &TestNode{Value: i}
|
||||
n.Child = child
|
||||
n = child
|
||||
}
|
||||
em, err := EncOptions{}.EncMode()
|
||||
if err != nil {
|
||||
t.Errorf("EncMode() returned error %v", err)
|
||||
}
|
||||
data, err := em.Marshal(root)
|
||||
if err != nil {
|
||||
t.Errorf("Marshal() deeply nested object returned error %v", err)
|
||||
}
|
||||
|
||||
// Try unmarshal it
|
||||
dm, err := DecOptions{MaxNestedLevels: 65535}.DecMode()
|
||||
if err != nil {
|
||||
t.Errorf("DecMode() returned error %v", err)
|
||||
}
|
||||
var readback TestNode
|
||||
err = dm.Unmarshal(data, &readback)
|
||||
if err != nil {
|
||||
t.Errorf("Unmarshal() of deeply nested object returned error: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(root, &readback) {
|
||||
t.Errorf("Unmarshal() of deeply nested object did not match\nGot: %#v\n Want: %#v\n",
|
||||
&readback, root)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStructToArrayError(t *testing.T) {
|
||||
type coseHeader struct {
|
||||
Alg int `cbor:"1,keyasint,omitempty"`
|
||||
@ -4995,8 +5033,8 @@ func TestDecModeDefaultMaxNestedLevel(t *testing.T) {
|
||||
t.Errorf("DecMode() returned error %v", err)
|
||||
} else {
|
||||
maxNestedLevels := dm.DecOptions().MaxNestedLevels
|
||||
if maxNestedLevels != defaultMaxNestedLevels {
|
||||
t.Errorf("DecOptions().MaxNestedLevels = %d, want %v", maxNestedLevels, defaultMaxNestedLevels)
|
||||
if maxNestedLevels != 32 {
|
||||
t.Errorf("DecOptions().MaxNestedLevels = %d, want %v", maxNestedLevels, 32)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -7698,7 +7736,7 @@ type A2 struct {
|
||||
Fields []B
|
||||
}
|
||||
|
||||
func TestUnmarshalRegisteredTagToConcreteType(t *testing.T) {
|
||||
func TestUnmarshalRegisteredTagToInterface(t *testing.T) {
|
||||
var err error
|
||||
tags := NewTagSet()
|
||||
err = tags.Add(TagOptions{EncTag: EncTagRequired, DecTag: DecTagRequired}, reflect.TypeOf(C{}), 279)
|
||||
@ -7719,18 +7757,36 @@ func TestUnmarshalRegisteredTagToConcreteType(t *testing.T) {
|
||||
t.Fatalf("Marshal(%+v) returned error %v", v1, err)
|
||||
}
|
||||
|
||||
v2 := A2{Fields: []B{&C{Field: 5}, &D{Field: "a"}}}
|
||||
data2, err := encMode.Marshal(v2)
|
||||
if err != nil {
|
||||
t.Fatalf("Marshal(%+v) returned error %v", v2, err)
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
data []byte
|
||||
unmarshalToObj interface{}
|
||||
wantValue interface{}
|
||||
}{
|
||||
{
|
||||
name: "interface type",
|
||||
data: data1,
|
||||
unmarshalToObj: &A1{},
|
||||
wantValue: &v1,
|
||||
},
|
||||
{
|
||||
name: "concrete type",
|
||||
data: data1,
|
||||
unmarshalToObj: &A1{Field: &C{}},
|
||||
wantValue: &v1,
|
||||
},
|
||||
{
|
||||
name: "slice of interface type",
|
||||
data: data2,
|
||||
unmarshalToObj: &A2{},
|
||||
wantValue: &v2,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
|
||||
@ -1,24 +0,0 @@
|
||||
// Copyright (c) Faye Amacker. All rights reserved.
|
||||
// Licensed under the MIT License. See LICENSE in the project root for license information.
|
||||
|
||||
//go:build tinygo
|
||||
|
||||
package cbor
|
||||
|
||||
import "reflect"
|
||||
|
||||
const (
|
||||
defaultMaxNestedLevels = 16 // was 32 for non-tinygo (24+ for tinygo v0.33 panics tests)
|
||||
minMaxNestedLevels = 4 // same as non-tinygo
|
||||
maxMaxNestedLevels = 65535 // same as non-tinygo (to allow testing)
|
||||
)
|
||||
|
||||
// tinygo v0.33 doesn't implement Type.AssignableTo() and it panics.
|
||||
// Type.AssignableTo() is used under the hood for Type.Implements().
|
||||
//
|
||||
// More details in https://github.com/tinygo-org/tinygo/issues/4277.
|
||||
//
|
||||
// implements() always returns false until tinygo implements Type.AssignableTo().
|
||||
func implements(concreteType reflect.Type, interfaceType reflect.Type) bool {
|
||||
return false
|
||||
}
|
||||
@ -1,111 +0,0 @@
|
||||
// Copyright (c) Faye Amacker. All rights reserved.
|
||||
// Licensed under the MIT License. See LICENSE in the project root for license information.
|
||||
|
||||
//go:build tinygo
|
||||
|
||||
package cbor
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestUnmarshalDeepNesting tests marshaling and unmarshaling of deeply nesting objects.
|
||||
// tinygo v0.33 fails with roughly 24+ levels of nested objects.
|
||||
func TestUnmarshalDeepNesting(t *testing.T) {
|
||||
// Construct this object rather than embed such a large constant in the code.
|
||||
type TestNode struct {
|
||||
Value int
|
||||
Child *TestNode
|
||||
}
|
||||
n := &TestNode{Value: 0}
|
||||
root := n
|
||||
const tinygoNestedLevels = 24
|
||||
for i := 1; i < tinygoNestedLevels; i++ {
|
||||
child := &TestNode{Value: i}
|
||||
n.Child = child
|
||||
n = child
|
||||
}
|
||||
em, err := EncOptions{}.EncMode()
|
||||
if err != nil {
|
||||
t.Errorf("EncMode() returned error %v", err)
|
||||
}
|
||||
data, err := em.Marshal(root)
|
||||
if err != nil {
|
||||
t.Errorf("Marshal() deeply nested object returned error %v", err)
|
||||
}
|
||||
|
||||
// Try unmarshal it
|
||||
dm, err := DecOptions{MaxNestedLevels: tinygoNestedLevels}.DecMode()
|
||||
if err != nil {
|
||||
t.Errorf("DecMode() returned error %v", err)
|
||||
}
|
||||
var readback TestNode
|
||||
err = dm.Unmarshal(data, &readback)
|
||||
if err != nil {
|
||||
t.Errorf("Unmarshal() of deeply nested object returned error: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(root, &readback) {
|
||||
t.Errorf("Unmarshal() of deeply nested object did not match\nGot: %#v\n Want: %#v\n",
|
||||
&readback, root)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnmarshalRegisteredTagToInterface(t *testing.T) {
|
||||
var err error
|
||||
tags := NewTagSet()
|
||||
err = tags.Add(TagOptions{EncTag: EncTagRequired, DecTag: DecTagRequired}, reflect.TypeOf(C{}), 279)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
err = tags.Add(TagOptions{EncTag: EncTagRequired, DecTag: DecTagRequired}, reflect.TypeOf(D{}), 280)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
encMode, _ := PreferredUnsortedEncOptions().EncModeWithTags(tags)
|
||||
decMode, _ := DecOptions{}.DecModeWithTags(tags)
|
||||
|
||||
v1 := A1{Field: &C{Field: 5}}
|
||||
data1, err := encMode.Marshal(v1)
|
||||
if err != nil {
|
||||
t.Fatalf("Marshal(%+v) returned error %v", v1, err)
|
||||
}
|
||||
|
||||
v2 := A2{Fields: []B{&C{Field: 5}, &D{Field: "a"}}}
|
||||
data2, err := encMode.Marshal(v2)
|
||||
if err != nil {
|
||||
t.Fatalf("Marshal(%+v) returned error %v", v2, err)
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
data []byte
|
||||
unmarshalToObj interface{}
|
||||
wantValue interface{}
|
||||
}{
|
||||
{
|
||||
name: "interface type",
|
||||
data: data1,
|
||||
unmarshalToObj: &A1{},
|
||||
wantValue: &v1,
|
||||
},
|
||||
{
|
||||
name: "slice of interface type",
|
||||
data: data2,
|
||||
unmarshalToObj: &A2{},
|
||||
wantValue: &v2,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
err = decMode.Unmarshal(tc.data, tc.unmarshalToObj)
|
||||
if err == nil {
|
||||
t.Errorf("Unmarshal(0x%x) returned no error, expect error", tc.data)
|
||||
} else if _, ok := err.(*UnmarshalTypeError); !ok {
|
||||
t.Errorf("Unmarshal(0x%x) returned wrong error type %T, want (*UnmarshalTypeError)", tc.data, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
// Copyright (c) Faye Amacker. All rights reserved.
|
||||
// Licensed under the MIT License. See LICENSE in the project root for license information.
|
||||
|
||||
//go:build go1.20 && !tinygo
|
||||
//go:build go1.20
|
||||
|
||||
package cbor
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Copyright (c) Faye Amacker. All rights reserved.
|
||||
// Licensed under the MIT License. See LICENSE in the project root for license information.
|
||||
|
||||
//go:build !go1.20 || tinygo
|
||||
//go:build !go1.20
|
||||
|
||||
package cbor
|
||||
|
||||
|
||||
@ -319,7 +319,7 @@ func TestInvalidTypeMarshal(t *testing.T) {
|
||||
{"map of channel cannot be marshaled", make(map[string]chan bool), "cbor: unsupported type: map[string]chan bool"},
|
||||
{"struct of channel cannot be marshaled", s1{}, "cbor: unsupported type: cbor.s1"},
|
||||
{"struct of channel cannot be marshaled", s2{}, "cbor: unsupported type: cbor.s2"},
|
||||
{"function cannot be marshaled", func(i int) int { return i * i }, "cbor: unsupported type: func"},
|
||||
{"function cannot be marshaled", func(i int) int { return i * i }, "cbor: unsupported type: func(int) int"},
|
||||
{"complex cannot be marshaled", complex(100, 8), "cbor: unsupported type: complex128"},
|
||||
}
|
||||
em, err := EncOptions{Sort: SortCanonical}.EncMode()
|
||||
@ -334,7 +334,7 @@ func TestInvalidTypeMarshal(t *testing.T) {
|
||||
t.Errorf("Marshal(%v) didn't return an error, want error %q", tc.value, tc.wantErrorMsg)
|
||||
} else if _, ok := err.(*UnsupportedTypeError); !ok {
|
||||
t.Errorf("Marshal(%v) error type %T, want *UnsupportedTypeError", tc.value, err)
|
||||
} else if !strings.HasPrefix(err.Error(), tc.wantErrorMsg) {
|
||||
} else if err.Error() != tc.wantErrorMsg {
|
||||
t.Errorf("Marshal(%v) error %q, want %q", tc.value, err.Error(), tc.wantErrorMsg)
|
||||
} else if b != nil {
|
||||
t.Errorf("Marshal(%v) = 0x%x, want nil", tc.value, b)
|
||||
@ -346,7 +346,7 @@ func TestInvalidTypeMarshal(t *testing.T) {
|
||||
t.Errorf("Marshal(%v) didn't return an error, want error %q", tc.value, tc.wantErrorMsg)
|
||||
} else if _, ok := err.(*UnsupportedTypeError); !ok {
|
||||
t.Errorf("Marshal(%v) error type %T, want *UnsupportedTypeError", tc.value, err)
|
||||
} else if !strings.HasPrefix(err.Error(), tc.wantErrorMsg) {
|
||||
} else if err.Error() != tc.wantErrorMsg {
|
||||
t.Errorf("Marshal(%v) error %q, want %q", tc.value, err.Error(), tc.wantErrorMsg)
|
||||
} else if b != nil {
|
||||
t.Errorf("Marshal(%v) = 0x%x, want nil", tc.value, b)
|
||||
|
||||
@ -45,6 +45,9 @@ func (sv SimpleValue) MarshalCBOR() ([]byte, error) {
|
||||
}
|
||||
|
||||
// UnmarshalCBOR decodes CBOR simple value (major type 7) to SimpleValue.
|
||||
//
|
||||
// Deprecated: No longer used by this codec; kept for compatibility
|
||||
// with user apps that directly call this function.
|
||||
func (sv *SimpleValue) UnmarshalCBOR(data []byte) error {
|
||||
if sv == nil {
|
||||
return errors.New("cbor.SimpleValue: UnmarshalCBOR on nil pointer")
|
||||
@ -52,6 +55,29 @@ func (sv *SimpleValue) UnmarshalCBOR(data []byte) error {
|
||||
|
||||
d := decoder{data: data, dm: defaultDecMode}
|
||||
|
||||
// Check well-formedness of CBOR data item.
|
||||
// SimpleValue.UnmarshalCBOR() is exported, so
|
||||
// the codec needs to support same behavior for:
|
||||
// - Unmarshal(data, *SimpleValue)
|
||||
// - SimpleValue.UnmarshalCBOR(data)
|
||||
err := d.wellformed(false, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return sv.unmarshalCBOR(data)
|
||||
}
|
||||
|
||||
// unmarshalCBOR decodes CBOR simple value (major type 7) to SimpleValue.
|
||||
// This function assumes data is well-formed, and does not perform bounds checking.
|
||||
// This function is called by Unmarshal().
|
||||
func (sv *SimpleValue) unmarshalCBOR(data []byte) error {
|
||||
if sv == nil {
|
||||
return errors.New("cbor.SimpleValue: UnmarshalCBOR on nil pointer")
|
||||
}
|
||||
|
||||
d := decoder{data: data, dm: defaultDecMode}
|
||||
|
||||
typ, ai, val := d.getHead()
|
||||
|
||||
if typ != cborTypePrimitives {
|
||||
|
||||
@ -5,7 +5,9 @@ package cbor
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@ -51,6 +53,125 @@ func TestUnmarshalSimpleValue(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestUnmarshalSimpleValueOnBadData(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
data []byte
|
||||
errMsg string
|
||||
}{
|
||||
// Empty data
|
||||
{
|
||||
name: "nil data",
|
||||
data: nil,
|
||||
errMsg: io.EOF.Error(),
|
||||
},
|
||||
{
|
||||
name: "empty data",
|
||||
data: []byte{},
|
||||
errMsg: io.EOF.Error(),
|
||||
},
|
||||
|
||||
// Wrong CBOR types
|
||||
{
|
||||
name: "uint type",
|
||||
data: hexDecode("01"),
|
||||
errMsg: "cbor: cannot unmarshal positive integer into Go value of type SimpleValue",
|
||||
},
|
||||
{
|
||||
name: "int type",
|
||||
data: hexDecode("20"),
|
||||
errMsg: "cbor: cannot unmarshal negative integer into Go value of type SimpleValue",
|
||||
},
|
||||
{
|
||||
name: "byte string type",
|
||||
data: hexDecode("40"),
|
||||
errMsg: "cbor: cannot unmarshal byte string into Go value of type SimpleValue",
|
||||
},
|
||||
{
|
||||
name: "string type",
|
||||
data: hexDecode("60"),
|
||||
errMsg: "cbor: cannot unmarshal UTF-8 text string into Go value of type SimpleValue",
|
||||
},
|
||||
{
|
||||
name: "array type",
|
||||
data: hexDecode("80"),
|
||||
errMsg: "cbor: cannot unmarshal array into Go value of type SimpleValue",
|
||||
},
|
||||
{
|
||||
name: "map type",
|
||||
data: hexDecode("a0"),
|
||||
errMsg: "cbor: cannot unmarshal map into Go value of type SimpleValue",
|
||||
},
|
||||
{
|
||||
name: "tag type",
|
||||
data: hexDecode("c074323031332d30332d32315432303a30343a30305a"),
|
||||
errMsg: "cbor: cannot unmarshal tag into Go value of type SimpleValue",
|
||||
},
|
||||
{
|
||||
name: "float type",
|
||||
data: hexDecode("f90000"),
|
||||
errMsg: "cbor: cannot unmarshal primitives into Go value of type SimpleValue",
|
||||
},
|
||||
|
||||
// Truncated CBOR data
|
||||
{
|
||||
name: "truncated head",
|
||||
data: hexDecode("18"),
|
||||
errMsg: io.ErrUnexpectedEOF.Error(),
|
||||
},
|
||||
|
||||
// Truncated CBOR simple value
|
||||
{
|
||||
name: "truncated simple value",
|
||||
data: hexDecode("f8"),
|
||||
errMsg: io.ErrUnexpectedEOF.Error(),
|
||||
},
|
||||
|
||||
// Invalid simple value
|
||||
{
|
||||
name: "invalid simple value",
|
||||
data: hexDecode("f800"),
|
||||
errMsg: "cbor: invalid simple value 0 for type primitives",
|
||||
},
|
||||
|
||||
// Extraneous CBOR data
|
||||
{
|
||||
name: "extraneous data",
|
||||
data: hexDecode("f4f5"),
|
||||
errMsg: "cbor: 1 bytes of extraneous data starting at index 1",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
// Test SimpleValue.UnmarshalCBOR(data)
|
||||
{
|
||||
var v SimpleValue
|
||||
|
||||
err := v.UnmarshalCBOR(tc.data)
|
||||
if err == nil {
|
||||
t.Errorf("UnmarshalCBOR(%x) didn't return error", tc.data)
|
||||
}
|
||||
if !strings.HasPrefix(err.Error(), tc.errMsg) {
|
||||
t.Errorf("UnmarshalCBOR(%x) returned error %q, want %q", tc.data, err.Error(), tc.errMsg)
|
||||
}
|
||||
}
|
||||
// Test Unmarshal(data, *SimpleValue), which calls SimpleValue.unmarshalCBOR() under the hood
|
||||
{
|
||||
var v SimpleValue
|
||||
|
||||
err := Unmarshal(tc.data, &v)
|
||||
if err == nil {
|
||||
t.Errorf("Unmarshal(%x) didn't return error", tc.data)
|
||||
}
|
||||
if !strings.HasPrefix(err.Error(), tc.errMsg) {
|
||||
t.Errorf("Unmarshal(%x) returned error %q, want %q", tc.data, err.Error(), tc.errMsg)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func testUnmarshalInvalidSimpleValueToEmptyInterface(t *testing.T, data []byte) {
|
||||
var v interface{}
|
||||
if err := Unmarshal(data, v); err == nil {
|
||||
|
||||
@ -692,7 +692,7 @@ func TestEncoderError(t *testing.T) {
|
||||
wantErrorMsg string
|
||||
}{
|
||||
{"channel cannot be marshaled", make(chan bool), "cbor: unsupported type: chan bool"},
|
||||
{"function cannot be marshaled", func(i int) int { return i * i }, "cbor: unsupported type: func"},
|
||||
{"function cannot be marshaled", func(i int) int { return i * i }, "cbor: unsupported type: func(int) int"},
|
||||
{"complex cannot be marshaled", complex(100, 8), "cbor: unsupported type: complex128"},
|
||||
}
|
||||
var w bytes.Buffer
|
||||
@ -705,7 +705,7 @@ func TestEncoderError(t *testing.T) {
|
||||
t.Errorf("Encode(%v) didn't return an error, want error %q", tc.value, tc.wantErrorMsg)
|
||||
} else if _, ok := err.(*UnsupportedTypeError); !ok {
|
||||
t.Errorf("Encode(%v) error type %T, want *UnsupportedTypeError", tc.value, err)
|
||||
} else if !strings.HasPrefix(err.Error(), tc.wantErrorMsg) {
|
||||
} else if err.Error() != tc.wantErrorMsg {
|
||||
t.Errorf("Encode(%v) error %q, want %q", tc.value, err.Error(), tc.wantErrorMsg)
|
||||
}
|
||||
})
|
||||
|
||||
26
tag.go
26
tag.go
@ -23,11 +23,37 @@ type RawTag struct {
|
||||
}
|
||||
|
||||
// UnmarshalCBOR sets *t with tag number and raw tag content copied from data.
|
||||
//
|
||||
// Deprecated: No longer used by this codec; kept for compatibility
|
||||
// with user apps that directly call this function.
|
||||
func (t *RawTag) UnmarshalCBOR(data []byte) error {
|
||||
if t == nil {
|
||||
return errors.New("cbor.RawTag: UnmarshalCBOR on nil pointer")
|
||||
}
|
||||
|
||||
d := decoder{data: data, dm: defaultDecMode}
|
||||
|
||||
// Check if data is a well-formed CBOR data item.
|
||||
// RawTag.UnmarshalCBOR() is exported, so
|
||||
// the codec needs to support same behavior for:
|
||||
// - Unmarshal(data, *RawTag)
|
||||
// - RawTag.UnmarshalCBOR(data)
|
||||
err := d.wellformed(false, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return t.unmarshalCBOR(data)
|
||||
}
|
||||
|
||||
// unmarshalCBOR sets *t with tag number and raw tag content copied from data.
|
||||
// This function assumes data is well-formed, and does not perform bounds checking.
|
||||
// This function is called by Unmarshal().
|
||||
func (t *RawTag) unmarshalCBOR(data []byte) error {
|
||||
if t == nil {
|
||||
return errors.New("cbor.RawTag: UnmarshalCBOR on nil pointer")
|
||||
}
|
||||
|
||||
// Decoding CBOR null and undefined to cbor.RawTag is no-op.
|
||||
if len(data) == 1 && (data[0] == 0xf6 || data[0] == 0xf7) {
|
||||
return nil
|
||||
|
||||
122
tag_test.go
122
tag_test.go
@ -1536,3 +1536,125 @@ func TestEncodeBuiltinTag(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnmarshalRawTagOnBadData(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
data []byte
|
||||
errMsg string
|
||||
}{
|
||||
// Empty data
|
||||
{
|
||||
name: "nil data",
|
||||
data: nil,
|
||||
errMsg: io.EOF.Error(),
|
||||
},
|
||||
{
|
||||
name: "empty data",
|
||||
data: []byte{},
|
||||
errMsg: io.EOF.Error(),
|
||||
},
|
||||
|
||||
// Wrong CBOR types
|
||||
{
|
||||
name: "uint type",
|
||||
data: hexDecode("01"),
|
||||
errMsg: "cbor: cannot unmarshal positive integer into Go value of type cbor.RawTag",
|
||||
},
|
||||
{
|
||||
name: "int type",
|
||||
data: hexDecode("20"),
|
||||
errMsg: "cbor: cannot unmarshal negative integer into Go value of type cbor.RawTag",
|
||||
},
|
||||
{
|
||||
name: "byte string type",
|
||||
data: hexDecode("40"),
|
||||
errMsg: "cbor: cannot unmarshal byte string into Go value of type cbor.RawTag",
|
||||
},
|
||||
{
|
||||
name: "string type",
|
||||
data: hexDecode("60"),
|
||||
errMsg: "cbor: cannot unmarshal UTF-8 text string into Go value of type cbor.RawTag",
|
||||
},
|
||||
{
|
||||
name: "array type",
|
||||
data: hexDecode("80"),
|
||||
errMsg: "cbor: cannot unmarshal array into Go value of type cbor.RawTag",
|
||||
},
|
||||
{
|
||||
name: "map type",
|
||||
data: hexDecode("a0"),
|
||||
errMsg: "cbor: cannot unmarshal map into Go value of type cbor.RawTag",
|
||||
},
|
||||
{
|
||||
name: "primitive type",
|
||||
data: hexDecode("f4"),
|
||||
errMsg: "cbor: cannot unmarshal primitives into Go value of type cbor.RawTag",
|
||||
},
|
||||
{
|
||||
name: "float type",
|
||||
data: hexDecode("f90000"),
|
||||
errMsg: "cbor: cannot unmarshal primitives into Go value of type cbor.RawTag",
|
||||
},
|
||||
|
||||
// Truncated CBOR data
|
||||
{
|
||||
name: "truncated head",
|
||||
data: hexDecode("18"),
|
||||
errMsg: io.ErrUnexpectedEOF.Error(),
|
||||
},
|
||||
|
||||
// Truncated CBOR tag data
|
||||
{
|
||||
name: "truncated tag number",
|
||||
data: hexDecode("d8"),
|
||||
errMsg: io.ErrUnexpectedEOF.Error(),
|
||||
},
|
||||
{
|
||||
name: "tag number not followed by tag content",
|
||||
data: hexDecode("da"),
|
||||
errMsg: io.ErrUnexpectedEOF.Error(),
|
||||
},
|
||||
{
|
||||
name: "truncated tag content",
|
||||
data: hexDecode("c074323031332d30332d32315432303a30343a3030"),
|
||||
errMsg: io.ErrUnexpectedEOF.Error(),
|
||||
},
|
||||
|
||||
// Extraneous CBOR data
|
||||
{
|
||||
name: "extraneous data",
|
||||
data: hexDecode("c074323031332d30332d32315432303a30343a30305a00"),
|
||||
errMsg: "cbor: 1 bytes of extraneous data starting at index 22",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
// Test RawTag.UnmarshalCBOR(data)
|
||||
{
|
||||
var v RawTag
|
||||
|
||||
err := v.UnmarshalCBOR(tc.data)
|
||||
if err == nil {
|
||||
t.Errorf("UnmarshalCBOR(%x) didn't return error", tc.data)
|
||||
}
|
||||
if !strings.HasPrefix(err.Error(), tc.errMsg) {
|
||||
t.Errorf("UnmarshalCBOR(%x) returned error %q, want %q", tc.data, err.Error(), tc.errMsg)
|
||||
}
|
||||
}
|
||||
// Test Unmarshal(data, *RawTag), which calls RawTag.unmarshalCBOR() under the hood
|
||||
{
|
||||
var v RawTag
|
||||
|
||||
err := Unmarshal(tc.data, &v)
|
||||
if err == nil {
|
||||
t.Errorf("Unmarshal(%x) didn't return error", tc.data)
|
||||
}
|
||||
if !strings.HasPrefix(err.Error(), tc.errMsg) {
|
||||
t.Errorf("Unmarshal(%x) returned error %q, want %q", tc.data, err.Error(), tc.errMsg)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,34 +0,0 @@
|
||||
// Copyright (c) Faye Amacker. All rights reserved.
|
||||
// Licensed under the MIT License. See LICENSE in the project root for license information.
|
||||
|
||||
//go:build !tinygo
|
||||
|
||||
package cbor
|
||||
|
||||
import "testing"
|
||||
|
||||
func Test32Depth(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
data []byte
|
||||
wantDepth int
|
||||
}{
|
||||
{"32-level array", hexDecode("82018181818181818181818181818181818181818181818181818181818181818101"), 32},
|
||||
{"32-level indefinite length array", hexDecode("9f018181818181818181818181818181818181818181818181818181818181818101ff"), 32},
|
||||
{"32-level map", hexDecode("a1018181818181818181818181818181818181818181818181818181818181818101"), 32},
|
||||
{"32-level indefinite length map", hexDecode("bf018181818181818181818181818181818181818181818181818181818181818101ff"), 32},
|
||||
{"32-level tag", hexDecode("d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d86474323031332d30332d32315432303a30343a30305a"), 32}, // 100(100(...("2013-03-21T20:04:00Z")))
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
d := decoder{data: tc.data, dm: defaultDecMode}
|
||||
depth, err := d.wellformedInternal(0, false)
|
||||
if err != nil {
|
||||
t.Errorf("wellformed(0x%x) returned error %v", tc.data, err)
|
||||
}
|
||||
if depth != tc.wantDepth {
|
||||
t.Errorf("wellformed(0x%x) returned depth %d, want %d", tc.data, depth, tc.wantDepth)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -5,7 +5,6 @@ package cbor
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strconv"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@ -103,11 +102,11 @@ func TestDepth(t *testing.T) {
|
||||
{"tagged map and array", hexDecode("d864a26161016162d865820203"), 2}, // 100({"a": 1, "b": 101([2, 3])})
|
||||
{"tagged map and array", hexDecode("d864a26161016162d865d866820203"), 3}, // 100({"a": 1, "b": 101(102([2, 3]))})
|
||||
{"nested tag", hexDecode("d864d865d86674323031332d30332d32315432303a30343a30305a"), 2}, // 100(101(102("2013-03-21T20:04:00Z")))
|
||||
{"16-level array", hexDecode("820181818181818181818181818181818101"), 16},
|
||||
{"16-level indefinite length array", hexDecode("9f0181818181818181818181818181818101ff"), 16},
|
||||
{"16-level map", hexDecode("a10181818181818181818181818181818101"), 16},
|
||||
{"16-level indefinite length map", hexDecode("bf0181818181818181818181818181818101ff"), 16},
|
||||
{"16-level tag", hexDecode("d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d86474323031332d30332d32315432303a30343a30305a"), 16}, // 100(100(...("2013-03-21T20:04:00Z")))
|
||||
{"32-level array", hexDecode("82018181818181818181818181818181818181818181818181818181818181818101"), 32},
|
||||
{"32-level indefinite length array", hexDecode("9f018181818181818181818181818181818181818181818181818181818181818101ff"), 32},
|
||||
{"32-level map", hexDecode("a1018181818181818181818181818181818181818181818181818181818181818101"), 32},
|
||||
{"32-level indefinite length map", hexDecode("bf018181818181818181818181818181818181818181818181818181818181818101ff"), 32},
|
||||
{"32-level tag", hexDecode("d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d86474323031332d30332d32315432303a30343a30305a"), 32}, // 100(100(...("2013-03-21T20:04:00Z")))
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
@ -146,31 +145,31 @@ func TestDepthError(t *testing.T) {
|
||||
name: "33-level array",
|
||||
data: hexDecode("8201818181818181818181818181818181818181818181818181818181818181818101"),
|
||||
opts: DecOptions{},
|
||||
wantErrorMsg: "cbor: exceeded max nested level " + strconv.Itoa(defaultMaxNestedLevels),
|
||||
wantErrorMsg: "cbor: exceeded max nested level 32",
|
||||
},
|
||||
{
|
||||
name: "33-level indefinite length array",
|
||||
data: hexDecode("9f01818181818181818181818181818181818181818181818181818181818181818101ff"),
|
||||
opts: DecOptions{},
|
||||
wantErrorMsg: "cbor: exceeded max nested level " + strconv.Itoa(defaultMaxNestedLevels),
|
||||
wantErrorMsg: "cbor: exceeded max nested level 32",
|
||||
},
|
||||
{
|
||||
name: "33-level map",
|
||||
data: hexDecode("a101818181818181818181818181818181818181818181818181818181818181818101"),
|
||||
opts: DecOptions{},
|
||||
wantErrorMsg: "cbor: exceeded max nested level " + strconv.Itoa(defaultMaxNestedLevels),
|
||||
wantErrorMsg: "cbor: exceeded max nested level 32",
|
||||
},
|
||||
{
|
||||
name: "33-level indefinite length map",
|
||||
data: hexDecode("bf01818181818181818181818181818181818181818181818181818181818181818101ff"),
|
||||
opts: DecOptions{},
|
||||
wantErrorMsg: "cbor: exceeded max nested level " + strconv.Itoa(defaultMaxNestedLevels),
|
||||
wantErrorMsg: "cbor: exceeded max nested level 32",
|
||||
},
|
||||
{
|
||||
name: "33-level tag",
|
||||
data: hexDecode("d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d86474323031332d30332d32315432303a30343a30305a"),
|
||||
opts: DecOptions{},
|
||||
wantErrorMsg: "cbor: exceeded max nested level " + strconv.Itoa(defaultMaxNestedLevels),
|
||||
wantErrorMsg: "cbor: exceeded max nested level 32",
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user