diff -Nru golang-github-fxamacker-cbor-2.3.0/CONTRIBUTING.md golang-github-fxamacker-cbor-2.4.0/CONTRIBUTING.md --- golang-github-fxamacker-cbor-2.3.0/CONTRIBUTING.md 2021-11-07 18:31:10.000000000 +0000 +++ golang-github-fxamacker-cbor-2.4.0/CONTRIBUTING.md 2022-01-07 21:04:46.000000000 +0000 @@ -1,47 +1,58 @@ # How to contribute -This project started because I needed an easy, small, and crash-proof CBOR library for my [WebAuthn (FIDO2) server library](https://github.com/fxamacker/webauthn). I believe this was the first and still only standalone CBOR library (in Go) that is fuzz tested as of November 10, 2019. +Here are some ways you can contribute: -To my surprise, Stefan Tatschner (rumpelsepp) submitted the first 2 issues when I didn't expect this project to be noticed. So I decided to make it more full-featured for others by announcing releases and asking for feedback. Even this document exists because Montgomery Edwards⁴⁴⁸ (x448) opened [issue #22](https://github.com/fxamacker/cbor/issues/22). In other words, you can contribute by opening an issue that helps the project improve. Especially in the early stages. - -When I announced v1.2 on Go Forum, Jakob Borg (calmh) responded with a thumbs up and encouragement. Another project of equal priority needed my time and Jakob's kind words tipped the scale for me to work on this one (speedups for [milestone v1.3](https://github.com/fxamacker/cbor/issues?q=is%3Aopen+is%3Aissue+milestone%3Av1.3.0).) So words of appreciation or encouragement is nice way to contribute to open source projects. - -Another way is by using this library in your project. It can lead to features that benefit both projects, which is what happened when oasislabs/oasis-core switched to this CBOR libary -- thanks Yawning Angel (yawning) for requesting BinaryMarshaler/BinaryUnmarshaler and Jernej Kos (kostco) for requesting RawMessage! +- Give this library a star on GitHub. It doesn't cost anything and it lets maintainers know you appreciate their work. +- Use this library in your project. By using this library, you're more likely to open an issue with feature request, etc. +- Report security vulnerabilities privately by email after reading this contributing guide and [Security Policy](https://github.com/fxamacker/cbor#security-policy). +- Open an issue with a feature request. It can help prioritize issues if you provide a link to your project and mention if a missing feature prevents your project from using this library. +- Open an issue with a bug report. It's helpful if the bug report includes a link to a reproducer at [Go Playground](https://go.dev/play/). +- Open a PR that would close a specific issue. Ask if it's a good time to open a PR in the issue because a solution might already be in progress. Please also read about the signing requirements before spending time on a PR. If you'd like to contribute code or send CBOR data, please read on (it can save you time!) ## Private reports + Usually, all issues are tracked publicly on [GitHub](https://github.com/fxamacker/cbor/issues). To report security vulnerabilities, please email faye.github@gmail.com and allow time for the problem to be resolved before disclosing it to the public. For more info, see [Security Policy](https://github.com/fxamacker/cbor#security-policy). Please do not send data that might contain personally identifiable information, even if you think you have permission. That type of support requires payment and a contract where I'm indemnified, held harmless, and defended for any data you send to me. -## Prerequisites to pull requests +## Pull requests + +Pull requests have signing requirements and must not be anonymous. Exceptions can be made for docs and CI scripts. + +See our [Pull Request Template](https://github.com/fxamacker/cbor/blob/master/.github/pull_request_template.md) for details. + Please [create an issue](https://github.com/fxamacker/cbor/issues/new/choose), if one doesn't already exist, and describe your concern. You'll need a [GitHub account](https://github.com/signup/free) to do this. If you submit a pull request without creating an issue and getting a response, you risk having your work unused because the bugfix or feature was already done by others and being reviewed before reaching Github. ## Describe your issue + Clearly describe the issue: * If it's a bug, please provide: **version of this library** and **Go** (`go version`), **unmodified error message**, and describe **how to reproduce it**. Also state **what you expected to happen** instead of the error. * If you propose a change or addition, try to give an example how the improved code could look like or how to use it. * If you found a compilation error, please confirm you're using a supported version of Go. If you are, then provide the output of `go version` first, followed by the complete error message. ## Please don't + Please don't send data containing personally identifiable information, even if you think you have permission. That type of support requires payment and a contract where I'm indemnified, held harmless, and defended for any data you send to me. Please don't send CBOR data larger than 512 bytes. If you want to send crash-producing CBOR data > 512 bytes, please get my permission before sending it to me. ## Wanted + * Opening issues that are helpful to the project * Using this library in your project and letting me know * Sending well-formed CBOR data (<= 512 bytes) that causes crashes (none found yet). * Sending malformed CBOR data (<= 512 bytes) that causes crashes (none found yet, but bad actors are better than me at breaking things). -* Sending tests or data for unit tests that increase code coverage (currently at 97.8% for v1.2.) +* Sending tests or data for unit tests that increase code coverage (currently around 98%) * Pull requests with small changes that are well-documented and easily understandable. -* Sponsors, donations, bounties, subscriptions: I'd like to run uninterrupted fuzzing between releases on a server with dedicated CPUs (after v1.3 or v1.4.) +* Sponsors, donations, bounties, or subscriptions. ## Credits -This guide used nlohmann/json contribution guidelines for inspiration as suggested in issue #22. +- This guide used nlohmann/json contribution guidelines for inspiration as suggested in issue #22. +- Special thanks to @lukseven for pointing out the contribution guidelines didn't mention signing requirements. diff -Nru golang-github-fxamacker-cbor-2.3.0/debian/changelog golang-github-fxamacker-cbor-2.4.0/debian/changelog --- golang-github-fxamacker-cbor-2.3.0/debian/changelog 2021-11-28 18:36:21.000000000 +0000 +++ golang-github-fxamacker-cbor-2.4.0/debian/changelog 2022-01-17 17:40:58.000000000 +0000 @@ -1,3 +1,14 @@ +golang-github-fxamacker-cbor (2.4.0-1) unstable; urgency=medium + + [ Aloïs Micard ] + * update debian/gitlab-ci.yml (using pkg-go-tools/ci-config) + + [ Mathias Gibbens ] + * New upstream release + - Add a patch to fix tests on 32bit architectures + + -- Mathias Gibbens Mon, 17 Jan 2022 18:40:58 +0100 + golang-github-fxamacker-cbor (2.3.0-2) unstable; urgency=medium * Source only upload for testing migration diff -Nru golang-github-fxamacker-cbor-2.3.0/debian/copyright golang-github-fxamacker-cbor-2.4.0/debian/copyright --- golang-github-fxamacker-cbor-2.3.0/debian/copyright 2021-11-22 17:28:26.000000000 +0000 +++ golang-github-fxamacker-cbor-2.4.0/debian/copyright 2022-01-17 17:40:50.000000000 +0000 @@ -16,7 +16,7 @@ License: Expat Files: debian/* -Copyright: 2021 Mathias Gibbens +Copyright: 2021-2022 Mathias Gibbens License: Expat Comment: Debian packaging is licensed under the same terms as upstream diff -Nru golang-github-fxamacker-cbor-2.3.0/debian/gitlab-ci.yml golang-github-fxamacker-cbor-2.4.0/debian/gitlab-ci.yml --- golang-github-fxamacker-cbor-2.3.0/debian/gitlab-ci.yml 2021-11-19 10:54:20.000000000 +0000 +++ golang-github-fxamacker-cbor-2.4.0/debian/gitlab-ci.yml 2022-01-17 17:40:50.000000000 +0000 @@ -1,26 +1,6 @@ # auto-generated, DO NOT MODIFY. # The authoritative copy of this file lives at: -# https://salsa.debian.org/go-team/ci/blob/master/config/gitlabciyml.go - -image: stapelberg/ci2 - -test_the_archive: - artifacts: - paths: - - before-applying-commit.json - - after-applying-commit.json - script: - # Create an overlay to discard writes to /srv/gopath/src after the build: - - "rm -rf /cache/overlay/{upper,work}" - - "mkdir -p /cache/overlay/{upper,work}" - - "mount -t overlay overlay -o lowerdir=/srv/gopath/src,upperdir=/cache/overlay/upper,workdir=/cache/overlay/work /srv/gopath/src" - - "export GOPATH=/srv/gopath" - - "export GOCACHE=/cache/go" - # Build the world as-is: - - "ci-build -exemptions=/var/lib/ci-build/exemptions.json > before-applying-commit.json" - # Copy this package into the overlay: - - "GBP_CONF_FILES=:debian/gbp.conf gbp buildpackage --git-no-pristine-tar --git-ignore-branch --git-ignore-new --git-export-dir=/tmp/export --git-no-overlay --git-tarball-dir=/nonexistant --git-cleaner=/bin/true --git-builder='dpkg-buildpackage -S -d --no-sign'" - - "pgt-gopath -dsc /tmp/export/*.dsc" - # Rebuild the world: - - "ci-build -exemptions=/var/lib/ci-build/exemptions.json > after-applying-commit.json" - - "ci-diff before-applying-commit.json after-applying-commit.json" +# https://salsa.debian.org/go-team/infra/pkg-go-tools/blob/master/config/gitlabciyml.go +--- +include: + - https://salsa.debian.org/go-team/infra/pkg-go-tools/-/raw/master/pipeline/test-archive.yml diff -Nru golang-github-fxamacker-cbor-2.3.0/debian/patches/fix-tests-on-32bit.patch golang-github-fxamacker-cbor-2.4.0/debian/patches/fix-tests-on-32bit.patch --- golang-github-fxamacker-cbor-2.3.0/debian/patches/fix-tests-on-32bit.patch 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-fxamacker-cbor-2.4.0/debian/patches/fix-tests-on-32bit.patch 2022-01-17 17:40:50.000000000 +0000 @@ -0,0 +1,391 @@ +From: Mathias Gibbens +Description: Fix tests when run on 32bit architectures +Forwarded: https://github.com/fxamacker/cbor/issues/302 +diff --git a/bench_test.go b/bench_test.go +index cd36ee4..e197d08 100644 +--- a/bench_test.go ++++ b/bench_test.go +@@ -74,7 +74,7 @@ type SenMLRecord struct { + + type T1 struct { + T bool +- UI uint ++ UI uint64 + I int + F float64 + B []byte +@@ -85,7 +85,7 @@ type T1 struct { + + type T2 struct { + T bool `cbor:"1,keyasint"` +- UI uint `cbor:"2,keyasint"` ++ UI uint64 `cbor:"2,keyasint"` + I int `cbor:"3,keyasint"` + F float64 `cbor:"4,keyasint"` + B []byte `cbor:"5,keyasint"` +@@ -97,7 +97,7 @@ type T2 struct { + type T3 struct { + _ struct{} `cbor:",toarray"` + T bool +- UI uint ++ UI uint64 + I int + F float64 + B []byte +@@ -278,7 +278,7 @@ func BenchmarkMarshal(b *testing.B) { + // Marshal map[string]interface{} to CBOR map + m1 := map[string]interface{}{ //nolint:dupl + "T": true, +- "UI": uint(18446744073709551615), ++ "UI": uint64(18446744073709551615), + "I": -1000, + "F": -4.1, + "B": []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, 26}, +@@ -300,7 +300,7 @@ func BenchmarkMarshal(b *testing.B) { + // Marshal map[int]interface{} to CBOR map + m2 := map[int]interface{}{ //nolint:dupl + 1: true, +- 2: uint(18446744073709551615), ++ 2: uint64(18446744073709551615), + 3: -1000, + 4: -4.1, + 5: []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, 26}, +@@ -322,7 +322,7 @@ func BenchmarkMarshal(b *testing.B) { + // Marshal []interface to CBOR array. + slc := []interface{}{ + true, +- uint(18446744073709551615), ++ uint64(18446744073709551615), + -1000, + -4.1, + []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, 26}, +diff --git a/decode.go b/decode.go +index 0d5f253..9c07157 100644 +--- a/decode.go ++++ b/decode.go +@@ -272,11 +272,11 @@ type DecOptions struct { + + // MaxArrayElements specifies the max number of elements for CBOR arrays. + // Default is 128*1024=131072 and it can be set to [16, 2147483647] +- MaxArrayElements int ++ MaxArrayElements int64 + + // MaxMapPairs specifies the max number of key-value pairs for CBOR maps. + // Default is 128*1024=131072 and it can be set to [16, 2147483647] +- MaxMapPairs int ++ MaxMapPairs int64 + + // IndefLength specifies whether to allow indefinite length CBOR items. + IndefLength IndefLengthMode +@@ -384,12 +384,12 @@ func (opts DecOptions) decMode() (*decMode, error) { + if opts.MaxArrayElements == 0 { + opts.MaxArrayElements = defaultMaxArrayElements + } else if opts.MaxArrayElements < minMaxArrayElements || opts.MaxArrayElements > maxMaxArrayElements { +- return nil, errors.New("cbor: invalid MaxArrayElements " + strconv.Itoa(opts.MaxArrayElements) + " (range is [" + strconv.Itoa(minMaxArrayElements) + ", " + strconv.Itoa(maxMaxArrayElements) + "])") ++ return nil, errors.New("cbor: invalid MaxArrayElements " + strconv.FormatInt(opts.MaxArrayElements, 10) + " (range is [" + strconv.Itoa(minMaxArrayElements) + ", " + strconv.FormatInt(maxMaxArrayElements, 10) + "])") + } + if opts.MaxMapPairs == 0 { + opts.MaxMapPairs = defaultMaxMapPairs + } else if opts.MaxMapPairs < minMaxMapPairs || opts.MaxMapPairs > maxMaxMapPairs { +- return nil, errors.New("cbor: invalid MaxMapPairs " + strconv.Itoa(opts.MaxMapPairs) + " (range is [" + strconv.Itoa(minMaxMapPairs) + ", " + strconv.Itoa(maxMaxMapPairs) + "])") ++ return nil, errors.New("cbor: invalid MaxMapPairs " + strconv.FormatInt(opts.MaxMapPairs, 10) + " (range is [" + strconv.Itoa(minMaxMapPairs) + ", " + strconv.FormatInt(maxMaxMapPairs, 10) + "])") + } + if !opts.ExtraReturnErrors.valid() { + return nil, errors.New("cbor: invalid ExtraReturnErrors " + strconv.Itoa(int(opts.ExtraReturnErrors))) +@@ -433,8 +433,8 @@ type decMode struct { + dupMapKey DupMapKeyMode + timeTag DecTagMode + maxNestedLevels int +- maxArrayElements int +- maxMapPairs int ++ maxArrayElements int64 ++ maxMapPairs int64 + indefLength IndefLengthMode + tagsMd TagsMode + intDec IntDecMode +@@ -482,7 +482,7 @@ func (dm *decMode) NewDecoder(r io.Reader) *Decoder { + + type decoder struct { + data []byte +- off int // next read offset in data ++ off int64 // next read offset in data + dm *decMode + } + +@@ -1041,17 +1041,17 @@ func (d *decoder) parse(skipSelfDescribedTag bool) (interface{}, error) { //noli + func (d *decoder) parseByteString() []byte { + _, ai, val := d.getHead() + if ai != 31 { +- b := make([]byte, int(val)) +- copy(b, d.data[d.off:d.off+int(val)]) +- d.off += int(val) ++ b := make([]byte, int64(val)) ++ copy(b, d.data[d.off:d.off+int64(val)]) ++ d.off += int64(val) + return b + } + // Process indefinite length string chunks. + b := []byte{} + for !d.foundBreak() { + _, _, val = d.getHead() +- b = append(b, d.data[d.off:d.off+int(val)]...) +- d.off += int(val) ++ b = append(b, d.data[d.off:d.off+int64(val)]...) ++ d.off += int64(val) + } + return b + } +@@ -1062,8 +1062,8 @@ func (d *decoder) parseByteString() []byte { + func (d *decoder) parseTextString() ([]byte, error) { + _, ai, val := d.getHead() + if ai != 31 { +- b := d.data[d.off : d.off+int(val)] +- d.off += int(val) ++ b := d.data[d.off : d.off+int64(val)] ++ d.off += int64(val) + if !utf8.Valid(b) { + return nil, &SemanticError{"cbor: invalid UTF-8 string"} + } +@@ -1073,8 +1073,8 @@ func (d *decoder) parseTextString() ([]byte, error) { + b := []byte{} + for !d.foundBreak() { + _, _, val = d.getHead() +- x := d.data[d.off : d.off+int(val)] +- d.off += int(val) ++ x := d.data[d.off : d.off+int64(val)] ++ d.off += int64(val) + if !utf8.Valid(x) { + for !d.foundBreak() { + d.skip() // Skip remaining chunk on error +@@ -1640,7 +1640,7 @@ func (d *decoder) skip() { + + switch t { + case cborTypeByteString, cborTypeTextString: +- d.off += int(val) ++ d.off += int64(val) + case cborTypeArray: + for i := 0; i < int(val); i++ { + d.skip() +diff --git a/decode_test.go b/decode_test.go +index 1eee4bb..669bdf4 100644 +--- a/decode_test.go ++++ b/decode_test.go +@@ -107,13 +107,13 @@ var unmarshalTests = []unmarshalTest{ + { + hexDecode("1b000000e8d4a51000"), + uint64(1000000000000), +- []interface{}{uint64(1000000000000), uint(1000000000000), int64(1000000000000), int(1000000000000), float32(1000000000000), float64(1000000000000), bigIntOrPanic("1000000000000")}, ++ []interface{}{uint64(1000000000000), uint64(1000000000000), int64(1000000000000), int64(1000000000000), float32(1000000000000), float64(1000000000000), bigIntOrPanic("1000000000000")}, + []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), bigIntOrPanic("18446744073709551615")}, ++ []interface{}{uint64(18446744073709551615), uint64(18446744073709551615), float32(18446744073709551615), float64(18446744073709551615), bigIntOrPanic("18446744073709551615")}, + []reflect.Type{typeUint8, typeUint16, typeUint32, typeInt8, typeInt16, typeInt32, typeString, typeBool, typeByteArray, typeIntSlice, typeMapStringInt, typeTag, typeRawTag}, + }, + // negative integer +diff --git a/stream.go b/stream.go +index 29172b9..c59f1a9 100644 +--- a/stream.go ++++ b/stream.go +@@ -14,8 +14,8 @@ type Decoder struct { + r io.Reader + d decoder + buf []byte +- off int // next read offset in buf +- bytesRead int ++ off int64 // next read offset in buf ++ bytesRead int64 + } + + // NewDecoder returns a new decoder that reads and decodes from r using +@@ -26,7 +26,7 @@ func NewDecoder(r io.Reader) *Decoder { + + // Decode reads CBOR value and decodes it into the value pointed to by v. + func (dec *Decoder) Decode(v interface{}) error { +- if len(dec.buf) == dec.off { ++ if int64(len(dec.buf)) == dec.off { + if n, err := dec.read(); n == 0 { + return err + } +@@ -50,16 +50,16 @@ func (dec *Decoder) Decode(v interface{}) error { + } + + // NumBytesRead returns the number of bytes read. +-func (dec *Decoder) NumBytesRead() int { ++func (dec *Decoder) NumBytesRead() int64 { + return dec.bytesRead + } + + func (dec *Decoder) read() (int, error) { + // Grow buf if needed. + const minRead = 512 +- if cap(dec.buf)-len(dec.buf)+dec.off < minRead { ++ if int64(cap(dec.buf))-int64(len(dec.buf))+dec.off < minRead { + oldUnreadBuf := dec.buf[dec.off:] +- dec.buf = make([]byte, len(dec.buf)-dec.off, 2*cap(dec.buf)+minRead) ++ dec.buf = make([]byte, int64(len(dec.buf))-dec.off, 2*int64(cap(dec.buf))+minRead) + dec.overwriteBuf(oldUnreadBuf) + } + +diff --git a/stream_test.go b/stream_test.go +index 6469628..ce41d07 100644 +--- a/stream_test.go ++++ b/stream_test.go +@@ -19,7 +19,7 @@ func TestDecoder(t *testing.T) { + } + } + decoder := NewDecoder(&buf) +- bytesRead := 0 ++ bytesRead := int64(0) + for i := 0; i < 5; i++ { + for _, tc := range unmarshalTests { + var v interface{} +@@ -33,7 +33,7 @@ func TestDecoder(t *testing.T) { + } else if !reflect.DeepEqual(v, tc.emptyInterfaceValue) { + t.Errorf("Decode() = %v (%T), want %v (%T)", v, v, tc.emptyInterfaceValue, tc.emptyInterfaceValue) + } +- bytesRead += len(tc.cborData) ++ bytesRead += int64(len(tc.cborData)) + if decoder.NumBytesRead() != bytesRead { + t.Errorf("NumBytesRead() = %v, want %v", decoder.NumBytesRead(), bytesRead) + } +@@ -60,7 +60,7 @@ func TestDecoderUnmarshalTypeError(t *testing.T) { + } + } + decoder := NewDecoder(&buf) +- bytesRead := 0 ++ bytesRead := int64(0) + for i := 0; i < 5; i++ { + for _, tc := range unmarshalTests { + for _, typ := range tc.wrongTypes { +@@ -70,7 +70,7 @@ func TestDecoderUnmarshalTypeError(t *testing.T) { + } else if _, ok := err.(*UnmarshalTypeError); !ok { + t.Errorf("Decode(0x%x) returned wrong error type %T, want UnmarshalTypeError", tc.cborData, err) + } +- bytesRead += len(tc.cborData) ++ bytesRead += int64(len(tc.cborData)) + if decoder.NumBytesRead() != bytesRead { + t.Errorf("NumBytesRead() = %v, want %v", decoder.NumBytesRead(), bytesRead) + } +@@ -86,7 +86,7 @@ func TestDecoderUnmarshalTypeError(t *testing.T) { + } else if !reflect.DeepEqual(vi, tc.emptyInterfaceValue) { + t.Errorf("Decode() = %v (%T), want %v (%T)", vi, vi, tc.emptyInterfaceValue, tc.emptyInterfaceValue) + } +- bytesRead += len(tc.cborData) ++ bytesRead += int64(len(tc.cborData)) + if decoder.NumBytesRead() != bytesRead { + t.Errorf("NumBytesRead() = %v, want %v", decoder.NumBytesRead(), bytesRead) + } +diff --git a/valid.go b/valid.go +index f775afb..0ef8c26 100644 +--- a/valid.go ++++ b/valid.go +@@ -35,20 +35,20 @@ func (e *MaxNestedLevelError) Error() string { + + // MaxArrayElementsError indicates exceeded max number of elements for CBOR arrays. + type MaxArrayElementsError struct { +- maxArrayElements int ++ maxArrayElements int64 + } + + func (e *MaxArrayElementsError) Error() string { +- return "cbor: exceeded max number of elements " + strconv.Itoa(e.maxArrayElements) + " for CBOR array" ++ return "cbor: exceeded max number of elements " + strconv.FormatInt(e.maxArrayElements, 10) + " for CBOR array" + } + + // MaxMapPairsError indicates exceeded max number of key-value pairs for CBOR maps. + type MaxMapPairsError struct { +- maxMapPairs int ++ maxMapPairs int64 + } + + func (e *MaxMapPairsError) Error() string { +- return "cbor: exceeded max number of key-value pairs " + strconv.Itoa(e.maxMapPairs) + " for CBOR map" ++ return "cbor: exceeded max number of key-value pairs " + strconv.FormatInt(e.maxMapPairs, 10) + " for CBOR map" + } + + // IndefiniteLengthError indicates found disallowed indefinite length items. +@@ -70,7 +70,7 @@ func (e *TagsMdError) Error() string { + + // valid checks whether the CBOR data is complete and well-formed. + func (d *decoder) valid() error { +- if len(d.data) == d.off { ++ if int64(len(d.data)) == d.off { + return io.EOF + } + _, err := d.validInternal(0) +@@ -92,12 +92,12 @@ func (d *decoder) validInternal(depth int) (int, error) { + } + return d.validIndefiniteString(t, depth) + } +- valInt := int(val) ++ valInt := int64(val) + if valInt < 0 { + // Detect integer overflow + return 0, errors.New("cbor: " + t.String() + " length " + strconv.FormatUint(val, 10) + " is too large, causing integer overflow") + } +- if len(d.data)-d.off < valInt { // valInt+off may overflow integer ++ if int64(len(d.data))-d.off < valInt { // valInt+off may overflow integer + return 0, io.ErrUnexpectedEOF + } + d.off += valInt +@@ -114,7 +114,7 @@ func (d *decoder) validInternal(depth int) (int, error) { + return d.validIndefiniteArrayOrMap(t, depth) + } + +- valInt := int(val) ++ valInt := int64(val) + if valInt < 0 { + // Detect integer overflow + return 0, errors.New("cbor: " + t.String() + " length " + strconv.FormatUint(val, 10) + " is too large, it would cause integer overflow") +@@ -136,7 +136,7 @@ func (d *decoder) validInternal(depth int) (int, error) { + } + maxDepth := depth + for j := 0; j < count; j++ { +- for i := 0; i < valInt; i++ { ++ for i := int64(0); i < valInt; i++ { + var dpt int + if dpt, err = d.validInternal(depth); err != nil { + return 0, err +@@ -154,7 +154,7 @@ func (d *decoder) validInternal(depth int) (int, error) { + + // Scan nested tag numbers to avoid recursion. + for { +- if len(d.data) == d.off { // Tag number must be followed by tag content. ++ if int64(len(d.data)) == d.off { // Tag number must be followed by tag content. + return 0, io.ErrUnexpectedEOF + } + if cborType(d.data[d.off]&0xe0) != cborTypeTag { +@@ -178,7 +178,7 @@ func (d *decoder) validInternal(depth int) (int, error) { + func (d *decoder) validIndefiniteString(t cborType, depth int) (int, error) { + var err error + for { +- if len(d.data) == d.off { ++ if int64(len(d.data)) == d.off { + return 0, io.ErrUnexpectedEOF + } + if d.data[d.off] == 0xff { +@@ -204,9 +204,9 @@ func (d *decoder) validIndefiniteString(t cborType, depth int) (int, error) { + func (d *decoder) validIndefiniteArrayOrMap(t cborType, depth int) (int, error) { + var err error + maxDepth := depth +- i := 0 ++ i := int64(0) + for { +- if len(d.data) == d.off { ++ if int64(len(d.data)) == d.off { + return 0, io.ErrUnexpectedEOF + } + if d.data[d.off] == 0xff { +@@ -238,7 +238,7 @@ func (d *decoder) validIndefiniteArrayOrMap(t cborType, depth int) (int, error) + } + + func (d *decoder) validHead() (t cborType, ai byte, val uint64, err error) { +- dataLen := len(d.data) - d.off ++ dataLen := int64(len(d.data)) - d.off + if dataLen == 0 { + return 0, 0, 0, io.ErrUnexpectedEOF + } diff -Nru golang-github-fxamacker-cbor-2.3.0/debian/patches/series golang-github-fxamacker-cbor-2.4.0/debian/patches/series --- golang-github-fxamacker-cbor-2.3.0/debian/patches/series 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-fxamacker-cbor-2.4.0/debian/patches/series 2022-01-17 17:40:50.000000000 +0000 @@ -0,0 +1 @@ +fix-tests-on-32bit.patch diff -Nru golang-github-fxamacker-cbor-2.3.0/decode.go golang-github-fxamacker-cbor-2.4.0/decode.go --- golang-github-fxamacker-cbor-2.3.0/decode.go 2021-11-07 18:31:10.000000000 +0000 +++ golang-github-fxamacker-cbor-2.4.0/decode.go 2022-01-07 21:04:46.000000000 +0000 @@ -290,6 +290,11 @@ // ExtraReturnErrors specifies extra conditions that should be treated as errors. ExtraReturnErrors ExtraDecErrorCond + + // DefaultMapType specifies Go map type to create and decode to + // when unmarshalling CBOR into an empty interface value. + // By default, unmarshal uses map[interface{}]interface{}. + DefaultMapType reflect.Type } // DecMode returns DecMode with immutable options and no tags (safe for concurrency). @@ -389,6 +394,9 @@ if !opts.ExtraReturnErrors.valid() { return nil, errors.New("cbor: invalid ExtraReturnErrors " + strconv.Itoa(int(opts.ExtraReturnErrors))) } + if opts.DefaultMapType != nil && opts.DefaultMapType.Kind() != reflect.Map { + return nil, fmt.Errorf("cbor: invalid DefaultMapType %s", opts.DefaultMapType) + } dm := decMode{ dupMapKey: opts.DupMapKey, timeTag: opts.TimeTag, @@ -399,6 +407,7 @@ tagsMd: opts.TagsMd, intDec: opts.IntDec, extraReturnErrors: opts.ExtraReturnErrors, + defaultMapType: opts.DefaultMapType, } return &dm, nil } @@ -430,6 +439,7 @@ tagsMd TagsMode intDec IntDecMode extraReturnErrors ExtraDecErrorCond + defaultMapType reflect.Type } var defaultDecMode, _ = DecOptions{}.decMode() @@ -543,9 +553,34 @@ // and does not perform bounds checking. func (d *decoder) parseToValue(v reflect.Value, tInfo *typeInfo) error { //nolint:gocyclo - if tInfo.spclType == specialTypeIface && !v.IsNil() { - v = v.Elem() - tInfo = getTypeInfo(v.Type()) + if tInfo.spclType == specialTypeIface { + if !v.IsNil() { + // Use value type + v = v.Elem() + tInfo = getTypeInfo(v.Type()) + } else { + // Create and use registered type if CBOR data is registered tag + if d.dm.tags != nil && d.nextCBORType() == cborTypeTag { + + off := d.off + var tagNums []uint64 + for d.nextCBORType() == cborTypeTag { + _, _, tagNum := d.getHead() + tagNums = append(tagNums, tagNum) + } + d.off = off + + registeredType := d.dm.tags.getTypeFromTagNum(tagNums) + if registeredType != nil { + if registeredType.Implements(tInfo.nonPtrType) || + reflect.PtrTo(registeredType).Implements(tInfo.nonPtrType) { + v.Set(reflect.New(registeredType)) + v = v.Elem() + tInfo = getTypeInfo(registeredType) + } + } + } + } } // Create new value for the pointer v to point to if CBOR value is not nil/undefined. @@ -988,6 +1023,14 @@ case cborTypeArray: return d.parseArray() case cborTypeMap: + if d.dm.defaultMapType != nil { + m := reflect.New(d.dm.defaultMapType) + err := d.parseToValue(m, getTypeInfo(m.Elem().Type())) + if err != nil { + return nil, err + } + return m.Elem().Interface(), nil + } return d.parseMap() } return nil, nil @@ -1117,7 +1160,7 @@ return err } -func (d *decoder) parseMap() (map[interface{}]interface{}, error) { +func (d *decoder) parseMap() (interface{}, error) { _, ai, val := d.getHead() hasSize := (ai != 31) count := int(val) diff -Nru golang-github-fxamacker-cbor-2.3.0/decode_test.go golang-github-fxamacker-cbor-2.4.0/decode_test.go --- golang-github-fxamacker-cbor-2.3.0/decode_test.go 2021-11-07 18:31:10.000000000 +0000 +++ golang-github-fxamacker-cbor-2.4.0/decode_test.go 2022-01-07 21:04:46.000000000 +0000 @@ -538,8 +538,8 @@ }, { hexDecode("f98000"), - float64(-0.0), - []interface{}{float32(-0.0), float64(-0.0)}, + float64(-0.0), //nolint:staticcheck // we know -0.0 is 0.0 in Go + []interface{}{float32(-0.0), float64(-0.0)}, //nolint:staticcheck // we know -0.0 is 0.0 in Go []reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeInt16, typeInt32, typeInt64, typeByteArray, typeByteSlice, typeString, typeBool, typeIntSlice, typeMapStringInt, typeTag, typeRawTag, typeBigInt}, 0.0, }, @@ -1211,11 +1211,9 @@ // It's tested in TestUnmarshal(). // Unmarshalling to types implementing cbor.BinaryUnmarshaler is a no-op. - //{"cbor.BinaryUnmarshaler", nilBinaryUnmarshaler("hello world"), nilBinaryUnmarshaler("hello world")}, {"cbor.BinaryUnmarshaler", number(456), number(456)}, // When unmarshalling to types implementing cbor.Unmarshaler, - // UnmarshalCBOR function receives raw CBOR bytes (0xf6 or 0xf7). {"cbor.Unmarshaler", nilUnmarshaler("hello world"), nilUnmarshaler("null")}, } @@ -1710,7 +1708,7 @@ {"nested-tagged slice as map key", hexDecode("a33030306430303030d1cb4030"), "cbor: invalid map key type: cbor.Tag"}, // {-17: "0000", 17(11(h'')): -17} {"big.Int as map key", hexDecode("a13bbd3030303030303030"), "cbor: invalid map key type: big.Int"}, // {-13632449055575519281: -17} {"tagged big.Int as map key", hexDecode("a1c24901000000000000000030"), "cbor: invalid map key type: big.Int"}, // {18446744073709551616: -17} - {"tagged big.Int as map key", hexDecode("a1c34901000000000000000030"), "cbor: invalid map key type: big.Int"}, //{-18446744073709551617: -17} + {"tagged big.Int as map key", hexDecode("a1c34901000000000000000030"), "cbor: invalid map key type: big.Int"}, // {-18446744073709551617: -17} } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { @@ -5402,3 +5400,297 @@ t.Errorf("Unmarshal(0x%x) = %v, want %v", data, v2, v) } } + +type B interface { + Foo() +} + +type C struct { + Field int +} + +func (c *C) Foo() {} + +type D struct { + Field string +} + +func (d *D) Foo() {} + +type A1 struct { + Field B +} + +type A2 struct { + Fields []B +} + +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: "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 { + 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) + } + }) + } +} + +func TestDecModeInvalidDefaultMapType(t *testing.T) { + testCases := []struct { + name string + opts DecOptions + wantErrorMsg string + }{ + { + name: "byte slice", + opts: DecOptions{DefaultMapType: reflect.TypeOf([]byte(nil))}, + wantErrorMsg: "cbor: invalid DefaultMapType []uint8", + }, + { + name: "int slice", + opts: DecOptions{DefaultMapType: reflect.TypeOf([]int(nil))}, + wantErrorMsg: "cbor: invalid DefaultMapType []int", + }, + { + name: "string", + opts: DecOptions{DefaultMapType: reflect.TypeOf("")}, + wantErrorMsg: "cbor: invalid DefaultMapType string", + }, + { + name: "unnamed struct type", + opts: DecOptions{DefaultMapType: reflect.TypeOf(struct{}{})}, + wantErrorMsg: "cbor: invalid DefaultMapType struct {}", + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + _, err := tc.opts.DecMode() + if err == nil { + t.Errorf("DecMode() didn't return an error") + } else if err.Error() != tc.wantErrorMsg { + t.Errorf("DecMode() returned error %q, want %q", err.Error(), tc.wantErrorMsg) + } + }) + } +} + +func TestUnmarshalToDefaultMapType(t *testing.T) { + + cborDataMapIntInt := hexDecode("a201020304") // {1: 2, 3: 4} + cborDataMapStringInt := hexDecode("a2616101616202") // {"a": 1, "b": 2} + cborDataArrayOfMapStringint := hexDecode("82a2616101616202a2616303616404") // [{"a": 1, "b": 2}, {"c": 3, "d": 4}] + cborDataNestedMap := hexDecode("a268496e744669656c6401684d61704669656c64a2616101616202") // {"IntField": 1, "MapField": {"a": 1, "b": 2}} + + decOptionsDefault := DecOptions{} + decOptionsMapIntfIntfType := DecOptions{DefaultMapType: reflect.TypeOf(map[interface{}]interface{}(nil))} + decOptionsMapStringIntType := DecOptions{DefaultMapType: reflect.TypeOf(map[string]int(nil))} + decOptionsMapStringIntfType := DecOptions{DefaultMapType: reflect.TypeOf(map[string]interface{}(nil))} + + testCases := []struct { + name string + opts DecOptions + cborData []byte + wantValue interface{} + wantErrorMsg string + }{ + // Decode CBOR map to map[interface{}]interface{} using default options + { + name: "decode CBOR map[int]int to Go map[interface{}]interface{} (default)", + opts: decOptionsDefault, + cborData: cborDataMapIntInt, + wantValue: map[interface{}]interface{}{uint64(1): uint64(2), uint64(3): uint64(4)}, + }, + { + name: "decode CBOR map[string]int to Go map[interface{}]interface{} (default)", + opts: decOptionsDefault, + cborData: cborDataMapStringInt, + wantValue: map[interface{}]interface{}{"a": uint64(1), "b": uint64(2)}, + }, + { + name: "decode CBOR array of map[string]int to Go []map[interface{}]interface{} (default)", + opts: decOptionsDefault, + cborData: cborDataArrayOfMapStringint, + wantValue: []interface{}{ + map[interface{}]interface{}{"a": uint64(1), "b": uint64(2)}, + map[interface{}]interface{}{"c": uint64(3), "d": uint64(4)}, + }, + }, + { + name: "decode CBOR nested map to Go map[interface{}]interface{} (default)", + opts: decOptionsDefault, + cborData: cborDataNestedMap, + wantValue: map[interface{}]interface{}{ + "IntField": uint64(1), + "MapField": map[interface{}]interface{}{"a": uint64(1), "b": uint64(2)}, + }, + }, + // Decode CBOR map to map[interface{}]interface{} using default map type option + { + name: "decode CBOR map[int]int to Go map[interface{}]interface{}", + opts: decOptionsMapIntfIntfType, + cborData: cborDataMapIntInt, + wantValue: map[interface{}]interface{}{uint64(1): uint64(2), uint64(3): uint64(4)}, + }, + { + name: "decode CBOR map[string]int to Go map[interface{}]interface{}", + opts: decOptionsMapIntfIntfType, + cborData: cborDataMapStringInt, + wantValue: map[interface{}]interface{}{"a": uint64(1), "b": uint64(2)}, + }, + { + name: "decode CBOR array of map[string]int to Go []map[interface{}]interface{}", + opts: decOptionsMapIntfIntfType, + cborData: cborDataArrayOfMapStringint, + wantValue: []interface{}{ + map[interface{}]interface{}{"a": uint64(1), "b": uint64(2)}, + map[interface{}]interface{}{"c": uint64(3), "d": uint64(4)}, + }, + }, + { + name: "decode CBOR nested map to Go map[interface{}]interface{}", + opts: decOptionsMapIntfIntfType, + cborData: cborDataNestedMap, + wantValue: map[interface{}]interface{}{ + "IntField": uint64(1), + "MapField": map[interface{}]interface{}{"a": uint64(1), "b": uint64(2)}, + }, + }, + // Decode CBOR map to map[string]interface{} using default map type option + { + name: "decode CBOR map[int]int to Go map[string]interface{}", + opts: decOptionsMapStringIntfType, + cborData: cborDataMapIntInt, + wantErrorMsg: "cbor: cannot unmarshal positive integer into Go value of type string", + }, + { + name: "decode CBOR map[string]int to Go map[string]interface{}", + opts: decOptionsMapStringIntfType, + cborData: cborDataMapStringInt, + wantValue: map[string]interface{}{"a": uint64(1), "b": uint64(2)}, + }, + { + name: "decode CBOR array of map[string]int to Go []map[string]interface{}", + opts: decOptionsMapStringIntfType, + cborData: cborDataArrayOfMapStringint, + wantValue: []interface{}{ + map[string]interface{}{"a": uint64(1), "b": uint64(2)}, + map[string]interface{}{"c": uint64(3), "d": uint64(4)}, + }, + }, + { + name: "decode CBOR nested map to Go map[string]interface{}", + opts: decOptionsMapStringIntfType, + cborData: cborDataNestedMap, + wantValue: map[string]interface{}{ + "IntField": uint64(1), + "MapField": map[string]interface{}{"a": uint64(1), "b": uint64(2)}, + }, + }, + // Decode CBOR map to map[string]int using default map type option + { + name: "decode CBOR map[int]int to Go map[string]int", + opts: decOptionsMapStringIntType, + cborData: cborDataMapIntInt, + wantErrorMsg: "cbor: cannot unmarshal positive integer into Go value of type string", + }, + { + name: "decode CBOR map[string]int to Go map[string]int", + opts: decOptionsMapStringIntType, + cborData: cborDataMapStringInt, + wantValue: map[string]int{"a": 1, "b": 2}, + }, + { + name: "decode CBOR array of map[string]int to Go []map[string]int", + opts: decOptionsMapStringIntType, + cborData: cborDataArrayOfMapStringint, + wantValue: []interface{}{ + map[string]int{"a": 1, "b": 2}, + map[string]int{"c": 3, "d": 4}, + }, + }, + { + name: "decode CBOR nested map to Go map[string]int", + opts: decOptionsMapStringIntType, + cborData: cborDataNestedMap, + wantErrorMsg: "cbor: cannot unmarshal map into Go value of type int", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + decMode, _ := tc.opts.DecMode() + + var v interface{} + err := decMode.Unmarshal(tc.cborData, &v) + if err != nil { + if tc.wantErrorMsg == "" { + t.Errorf("Unmarshal(0x%x) to empty interface returned error %v", tc.cborData, err) + } else if tc.wantErrorMsg != err.Error() { + t.Errorf("Unmarshal(0x%x) error %q, want %q", tc.cborData, err.Error(), tc.wantErrorMsg) + } + } else { + if tc.wantValue == nil { + t.Errorf("Unmarshal(0x%x) = %v (%T), want error %q", tc.cborData, v, v, tc.wantErrorMsg) + } else if !reflect.DeepEqual(v, tc.wantValue) { + t.Errorf("Unmarshal(0x%x) = %v (%T), want %v (%T)", tc.cborData, v, v, tc.wantValue, tc.wantValue) + } + } + }) + } +} diff -Nru golang-github-fxamacker-cbor-2.3.0/doc.go golang-github-fxamacker-cbor-2.4.0/doc.go --- golang-github-fxamacker-cbor-2.3.0/doc.go 2021-11-07 18:31:10.000000000 +0000 +++ golang-github-fxamacker-cbor-2.4.0/doc.go 2022-01-07 21:04:46.000000000 +0000 @@ -2,10 +2,9 @@ // Licensed under the MIT License. See LICENSE in the project root for license information. /* -Package cbor is a fast & safe CBOR encoder & decoder (RFC 7049) with a -standard API + toarray & keyasint struct tags, CBOR tags, float64->32->16, -CTAP2 & Canonical CBOR, duplicate map key options, and is customizable via -simple API. +Package cbor is a modern CBOR codec (RFC 8949 & RFC 7049) with CBOR tags, +Go struct tags (toarray/keyasint/omitempty), Core Deterministic Encoding, +CTAP2, Canonical CBOR, float64->32->16, and duplicate map key detection. Encoding options allow "preferred serialization" by encoding integers and floats to their smallest forms (e.g. float16) when values fit. diff -Nru golang-github-fxamacker-cbor-2.3.0/encode_test.go golang-github-fxamacker-cbor-2.4.0/encode_test.go --- golang-github-fxamacker-cbor-2.3.0/encode_test.go 2021-11-07 18:31:10.000000000 +0000 +++ golang-github-fxamacker-cbor-2.4.0/encode_test.go 2022-01-07 21:04:46.000000000 +0000 @@ -2882,29 +2882,29 @@ var ( // qnan 32 bits variables - qnanVar0xffc00001 uint32 = qnanConst0xffc00001 - qnanVar0x7fc00001 uint32 = qnanConst0x7fc00001 - qnanVar0xffc02000 uint32 = qnanConst0xffc02000 - qnanVar0x7fc02000 uint32 = qnanConst0x7fc02000 + qnanVar0xffc00001 = qnanConst0xffc00001 + qnanVar0x7fc00001 = qnanConst0x7fc00001 + qnanVar0xffc02000 = qnanConst0xffc02000 + qnanVar0x7fc02000 = qnanConst0x7fc02000 // snan 32 bits variables - snanVar0xff800001 uint32 = snanConst0xff800001 - snanVar0x7f800001 uint32 = snanConst0x7f800001 - snanVar0xff802000 uint32 = snanConst0xff802000 - snanVar0x7f802000 uint32 = snanConst0x7f802000 + snanVar0xff800001 = snanConst0xff800001 + snanVar0x7f800001 = snanConst0x7f800001 + snanVar0xff802000 = snanConst0xff802000 + snanVar0x7f802000 = snanConst0x7f802000 // qnan 64 bits variables - qnanVar0xfff8000000000001 uint64 = qnanConst0xfff8000000000001 - qnanVar0x7ff8000000000001 uint64 = qnanConst0x7ff8000000000001 - qnanVar0xfff8000020000000 uint64 = qnanConst0xfff8000020000000 - qnanVar0x7ff8000020000000 uint64 = qnanConst0x7ff8000020000000 - qnanVar0xfffc000000000000 uint64 = qnanConst0xfffc000000000000 - qnanVar0x7ffc000000000000 uint64 = qnanConst0x7ffc000000000000 + qnanVar0xfff8000000000001 = qnanConst0xfff8000000000001 + qnanVar0x7ff8000000000001 = qnanConst0x7ff8000000000001 + qnanVar0xfff8000020000000 = qnanConst0xfff8000020000000 + qnanVar0x7ff8000020000000 = qnanConst0x7ff8000020000000 + qnanVar0xfffc000000000000 = qnanConst0xfffc000000000000 + qnanVar0x7ffc000000000000 = qnanConst0x7ffc000000000000 // snan 64 bits variables - snanVar0xfff0000000000001 uint64 = snanConst0xfff0000000000001 - snanVar0x7ff0000000000001 uint64 = snanConst0x7ff0000000000001 - snanVar0xfff0000020000000 uint64 = snanConst0xfff0000020000000 - snanVar0x7ff0000020000000 uint64 = snanConst0x7ff0000020000000 - snanVar0xfff4000000000000 uint64 = snanConst0xfff4000000000000 - snanVar0x7ff4000000000000 uint64 = snanConst0x7ff4000000000000 + snanVar0xfff0000000000001 = snanConst0xfff0000000000001 + snanVar0x7ff0000000000001 = snanConst0x7ff0000000000001 + snanVar0xfff0000020000000 = snanConst0xfff0000020000000 + snanVar0x7ff0000020000000 = snanConst0x7ff0000020000000 + snanVar0xfff4000000000000 = snanConst0xfff4000000000000 + snanVar0x7ff4000000000000 = snanConst0x7ff4000000000000 ) func TestNaNConvert(t *testing.T) { diff -Nru golang-github-fxamacker-cbor-2.3.0/.github/workflows/ci.yml golang-github-fxamacker-cbor-2.4.0/.github/workflows/ci.yml --- golang-github-fxamacker-cbor-2.3.0/.github/workflows/ci.yml 2021-11-07 18:31:10.000000000 +0000 +++ golang-github-fxamacker-cbor-2.4.0/.github/workflows/ci.yml 2022-01-07 21:04:46.000000000 +0000 @@ -1,4 +1,4 @@ -# GitHub Actions - CI for Go to build & test. See ci-go-cover.yml and linters.yml for code coverage and linters. +# GitHub Actions - CI for Go to build & test. See ci-go-cover.yml and safer-golangci-lint.yml for more. # https://github.com/fxamacker/cbor/workflows/ci.yml name: ci on: [push] @@ -10,17 +10,30 @@ runs-on: ${{ matrix.os }} strategy: matrix: - os: [macos-latest, ubuntu-latest] + os: [macos-latest, ubuntu-latest, windows-latest] + go-version: [1.15.x, 1.16.x, 1.17.x] + steps: + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go-version }} + - name: Checkout code - uses: actions/checkout@v1 + uses: actions/checkout@v2 with: fetch-depth: 1 + + - name: Print Go version + run: go version + - name: Get dependencies run: go get -v -t -d ./... + - name: Build project run: go build ./... + - name: Run tests run: | go version - go test -short -race -v ./... + go test -race -v ./... diff -Nru golang-github-fxamacker-cbor-2.3.0/.github/workflows/safer-golangci-lint.yml golang-github-fxamacker-cbor-2.4.0/.github/workflows/safer-golangci-lint.yml --- golang-github-fxamacker-cbor-2.3.0/.github/workflows/safer-golangci-lint.yml 2021-11-07 18:31:10.000000000 +0000 +++ golang-github-fxamacker-cbor-2.4.0/.github/workflows/safer-golangci-lint.yml 2022-01-07 21:04:46.000000000 +0000 @@ -7,32 +7,35 @@ # safer-golangci-lint.yml # # 100% of the script for downloading, installing, and running golangci-lint -# is embedded in this file. The embedded SHA384 is used to verify the -# downloaded golangci-lint tarball (golangci-lint-1.40.1-linux-amd64.tar.gz). +# is embedded in this file. The embedded SHA384 digest is used to verify the +# downloaded golangci-lint tarball (golangci-lint-1.42.0-linux-amd64.tar.gz). # # Why? # 1. Avoid downloading and executing unverified wrapper scripts or actions each time a workflow runs. # See https://www.securityweek.com/codecov-bash-uploader-dev-tool-compromised-supply-chain-hack -# 2. Use openssl instead of sha256sum because it's easier to change hash algo to BLAKE2s, SHA3-256, etc. -# 3. Use SHA384 instead of SHA256 to avoid debating strangers about length extension attacks and gzip file format. -# 4. Use embedded SHA384 instead of downloading CHECKSUM because CHECKSUM file isn't digitally signed. -# 5. Use binary instead of building from source because it's probably easier to detect backdoors in one binary +# 2. Use embedded SHA384 instead of downloading CHECKSUM because CHECKSUM file isn't digitally signed. +# 3. Use openssl instead of sha256sum because it's easier to change hash algo to BLAKE2s, SHA3-256, etc. +# 4. Use binary instead of building from source because it's probably easier to detect backdoors in one binary # than all the combined source code of dozens of linters and all their required 3rd-party packages. # # To use: -# Copy this file into [github_repo]/.github/workflows/ +# Step 1. Copy this file into [github_repo]/.github/workflows/ +# Step 2. There's no step 2 if you like the default settings. # -# Configure [github_repo]/.golangci.yml normally as instructed in golangci-lint docs. +# You can create and use a config file (.golangci.yml) as described in golangci-lint docs. # # To use a newer version of golangci-lint, change these values: # 1. GOLINTERS_VERSION -# 2. GOLINTERS_TGZ_HASH +# 2. GOLINTERS_TGZ_DGST # -# 2021-05-16 Created. Use golangci-lint 1.40.1, Go 1.15.x, and ubuntu-latest. -# sha256(tar.gz) is 7c133b4b39c0a46cf8d67265da651f169079d137ae71aee9b5934e2281bd18d3 -# sha384(tar.gz) is d0b9e9c0eac5c5e03b9feb546d181918fca9abc94656824badccacc77aa91bc78ab99fd22094d634d3a58a91353fb1b9 - -name: Lint +# Release v1.43.0 (Dec 5, 2021) +# - Bump Go to 1.17.x. +# - Bump golangci-lint to 1.43.0. +# - Checksum for golangci-lint-1.43.0-linux-amd64.tar.gz +# - SHA-256 is f3515cebec926257da703ba0a2b169e4a322c11dc31a8b4656b50a43e48877f4 +# - SHA-384 is 0a5e9adc3cc93fbc2e3c8f4daee061e77407fe3e702001021ef03c8bdf39a81c36c42d35e8ba970f4f09db2279c881bf +# +name: linters on: pull_request: @@ -41,9 +44,10 @@ branches: [main, master] env: - GOLINTERS_VERSION: 1.40.1 + GOLINTERS_VERSION: 1.43.0 GOLINTERS_ARCH: linux-amd64 - GOLINTERS_TGZ_DGST: d0b9e9c0eac5c5e03b9feb546d181918fca9abc94656824badccacc77aa91bc78ab99fd22094d634d3a58a91353fb1b9 + GOLINTERS_TGZ_DGST: 0a5e9adc3cc93fbc2e3c8f4daee061e77407fe3e702001021ef03c8bdf39a81c36c42d35e8ba970f4f09db2279c881bf + GOLINTERS_TIMEOUT: 5m OPENSSL_DGST_CMD: openssl dgst -sha384 -r CURL_CMD: curl --proto =https --tlsv1.2 --location --silent --show-error --fail @@ -60,7 +64,7 @@ - name: Setup Go uses: actions/setup-go@v2 with: - go-version: 1.15.x + go-version: 1.17.x - name: Install golangci-lint run: | @@ -85,12 +89,7 @@ install golangci-lint $(go env GOPATH)/bin shell: bash - # Run required linters enabled in .golangci.yml - - name: Run required linters in .golangci.yml - run: $(go env GOPATH)/bin/golangci-lint run --timeout=5m - shell: bash - - # Run noisy linters as optional (enable them using command line parameters) - - name: Run optional linters (not required to pass) - run: $(go env GOPATH)/bin/golangci-lint run --timeout=5m --issues-exit-code=0 -E dupl -E gocritic -E gosimple -E lll -E nilerr -E prealloc -E revive + # Run required linters enabled in .golangci.yml (or default linters if yml doesn't exist) + - name: Run golangci-lint + run: $(go env GOPATH)/bin/golangci-lint run --timeout="${GOLINTERS_TIMEOUT}" shell: bash diff -Nru golang-github-fxamacker-cbor-2.3.0/.golangci.yml golang-github-fxamacker-cbor-2.4.0/.golangci.yml --- golang-github-fxamacker-cbor-2.3.0/.golangci.yml 2021-11-07 18:31:10.000000000 +0000 +++ golang-github-fxamacker-cbor-2.4.0/.golangci.yml 2022-01-07 21:04:46.000000000 +0000 @@ -51,15 +51,13 @@ - govet - ineffassign - misspell + - revive - staticcheck - structcheck - typecheck - unconvert - unused - varcheck - # noisy linters such as gocritic are enabled by - # command line as optional linters inside - # .github/workflows/safer-golangci-lint.yml issues: # max-issues-per-linter default is 50. Set to 0 to disable limit. @@ -79,8 +77,3 @@ - goimports - gomnd - lll - -# golangci.com configuration -# https://github.com/golangci/golangci/wiki/Configuration -service: - golangci-lint-version: 1.23.x # use the fixed version to not introduce new linters unexpectedly diff -Nru golang-github-fxamacker-cbor-2.3.0/README.md golang-github-fxamacker-cbor-2.4.0/README.md --- golang-github-fxamacker-cbor-2.3.0/README.md 2021-11-07 18:31:10.000000000 +0000 +++ golang-github-fxamacker-cbor-2.4.0/README.md 2022-01-07 21:04:46.000000000 +0000 @@ -1,29 +1,64 @@ -# fxamacker/cbor +# CBOR Codec in Go + +[![](https://github.com/fxamacker/images/raw/master/cbor/v2.4.0/fxamacker_cbor_banner.png)](#cbor-library-in-go) [![](https://github.com/fxamacker/cbor/workflows/ci/badge.svg)](https://github.com/fxamacker/cbor/actions?query=workflow%3Aci) [![](https://github.com/fxamacker/cbor/workflows/cover%20%E2%89%A598%25/badge.svg)](https://github.com/fxamacker/cbor/actions?query=workflow%3A%22cover+%E2%89%A598%25%22) [![](https://github.com/fxamacker/cbor/workflows/linters/badge.svg)](https://github.com/fxamacker/cbor/actions?query=workflow%3Alinters) +[![CodeQL](https://github.com/fxamacker/cbor/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/fxamacker/cbor/actions/workflows/codeql-analysis.yml) +[![](https://img.shields.io/badge/fuzzing-3%2B%20billion%20execs-44c010)](#fuzzing-and-code-coverage) [![Go Report Card](https://goreportcard.com/badge/github.com/fxamacker/cbor)](https://goreportcard.com/report/github.com/fxamacker/cbor) -[![](https://github.com/fxamacker/images/raw/master/cbor/v2.3.0/release_version_badge.svg?sanitize=1)](https://github.com/fxamacker/cbor/releases) -[![](https://github.com/fxamacker/images/raw/master/cbor/v2.3.0/license_badge.svg?sanitize=1)](https://raw.githubusercontent.com/fxamacker/cbor/master/LICENSE) +[![](https://img.shields.io/badge/go-%3E%3D%201.12-blue)](#cbor-library-installation) + +[__fxamacker/cbor__](https://github.com/fxamacker/cbor) is a modern [CBOR](https://tools.ietf.org/html/rfc8949) codec in [Go](https://golang.org). It's like `encoding/json` for CBOR with time-saving features. It balances [security](https://github.com/fxamacker/cbor/#cbor-security), usability, [speed](https://github.com/fxamacker/cbor/#cbor-performance), data size, program size, and other competing factors. + +Features include CBOR tags, duplicate map key detection, float64→32→16, and Go struct tags (`toarray`, `keyasint`, `omitempty`). API is close to `encoding/json` plus predefined CBOR options like Core Deterministic Encoding, Preferred Serialization, CTAP2, etc. + +Using CBOR [Preferred Serialization](https://www.rfc-editor.org/rfc/rfc8949.html#name-preferred-serialization) with Go struct tags (`toarray`, `keyasint`, `omitempty`) reduces programming effort and creates smaller encoded data size. + +fxamacker/cbor has 98% coverage and is fuzz tested. It won't exhaust RAM decoding 9 bytes of bad CBOR data. It's used by Arm Ltd., Berlin Institute of Health at Charité, Chainlink, ConsenSys, Dapper Labs, Duo Labs (cisco), EdgeX Foundry, Mozilla, Netherlands (govt), Oasis Labs, Taurus SA, Teleport, and others. + +Install with `go get github.com/fxamacker/cbor/v2` and `import "github.com/fxamacker/cbor/v2"`. +See [Quick Start](#quick-start) to save time. + +## What is CBOR? + +[CBOR](https://tools.ietf.org/html/rfc8949) is a concise binary data format inspired by [JSON](https://www.json.org) and [MessagePack](https://msgpack.org). CBOR is defined in [RFC 8949](https://tools.ietf.org/html/rfc8949) (December 2020) which obsoletes [RFC 7049](https://tools.ietf.org/html/rfc7049) (October 2013). + +CBOR is an [Internet Standard](https://en.wikipedia.org/wiki/Internet_Standard) by [IETF](https://www.ietf.org). It's used in other standards like [WebAuthn](https://en.wikipedia.org/wiki/WebAuthn) by [W3C](https://www.w3.org), [COSE (RFC 8152)](https://tools.ietf.org/html/rfc8152), [CWT (RFC 8392)](https://tools.ietf.org/html/rfc8392), [CDDL (RFC 8610)](https://datatracker.ietf.org/doc/html/rfc8610) and [more](CBOR_GOLANG.md). + +[Reasons for choosing CBOR](https://github.com/fxamacker/cbor/wiki/Why-CBOR) vary by project. Some projects replaced protobuf, encoding/json, encoding/gob, etc. with CBOR. For example, by replacing protobuf with CBOR in gRPC. + +## Why fxamacker/cbor? -[__fxamacker/cbor__](https://github.com/fxamacker/cbor) is a CBOR library in [Go](https://golang.org). It's designed to be safe, fast, small, and easy to use. +fxamacker/cbor balances competing factors such as speed, size, safety, usability, maintainability, and etc. -Features include CBOR tags, duplicate map key detection, float64→32→16, Go struct tags (`toarray`, `keyasint`, `omitempty`), and a standard API. Each release passes hundreds of tests and 250+ million execs of coverage-guided fuzzing. +- Killer features include Go struct tags like `toarray`, `keyasint`, etc. They reduce encoded data size, improve speed, and reduce programming effort. For example, `toarray` automatically translates a Go struct to/from a CBOR array. -[CBOR](CBOR_GOLANG.md) ([RFC 7049](https://tools.ietf.org/html/rfc7049) & [RFC 8949](https://tools.ietf.org/html/rfc8949)) is a binary data format inspired by JSON and MessagePack. CBOR is an [Internet Standard](https://en.wikipedia.org/wiki/Internet_Standard) by [IETF](https://www.ietf.org) used in W3C [WebAuthn](https://en.wikipedia.org/wiki/WebAuthn), COSE ([RFC 8152](https://tools.ietf.org/html/rfc8152)), CWT ([RFC 8392 CBOR Web Token](https://tools.ietf.org/html/rfc8392)), and CDDL [(RFC 8610)](https://datatracker.ietf.org/doc/html/rfc8610). +- Modern CBOR features include Core Deterministic Encoding and Preferred Encoding. Other features include CBOR tags, big.Int, float64→32→16, an API like `encoding/json`, and more. -[CBOR Library Installation](https://github.com/x448/cbor/edit/patch-11/README.md#cbor-library-installation) shows how to install and begin using this CBOR encoder and decoder. +- Security features include the option to detect duplicate map keys and options to set various max limits. And it's designed to make concurrent use of CBOR options easy and free from side-effects. + +- To prevent crashes, it has been fuzz-tested since before release 1.0 and code coverage is kept above 98%. + +- For portability and safety, it avoids using `unsafe`, which makes it portable and protected by Go1's compatibility guidelines. + +- For performance, it uses safe optimizations. When used properly, fxamacker/cbor can be faster than CBOR codecs that rely on `unsafe`. However, speed is only one factor and should be considered together with other competing factors. ## CBOR Security -__fxamacker/cbor__ is secure. It rejects malformed CBOR data and can detect duplicate map keys. It doesn't crash when decoding bad CBOR data by having extensive tests, coverage-guided fuzzing, data validation, and avoiding Go's `unsafe` package. +__fxamacker/cbor__ is secure. It rejects malformed CBOR data and has an option to detect duplicate map keys. It doesn't crash when decoding bad CBOR data. It has extensive tests, coverage-guided fuzzing, data validation, and avoids Go's `unsafe` package. -| | fxamacker/cbor (all versions) | ugorji/go (1.1.0 - 1.1.7) | +Decoding 9 or 10 bytes of malformed CBOR data shouldn't exhaust memory. For example, +`[]byte{0x9B, 0x00, 0x00, 0x42, 0xFA, 0x42, 0xFA, 0x42, 0xFA, 0x42}` + +| | Decode bad 10 bytes to interface{} | Decode bad 10 bytes to []byte | | :--- | :------------------ | :--------------- | -| **Malformed CBOR 1** | 87.5 ns/op, 24 B/op, 2 allocs/op | :boom: fatal error: out of memory | -| **Malformed CBOR 2** | 89.5 ns/op, 24 B/op, 2 allocs/op | :boom: runtime: out of memory: cannot allocate | -| | Correctly rejected bad data in all versions.
Benchmark is from latest release. | :warning: Just 1 decode of 9 bytes can exhaust memory. | +| fxamacker/cbor
1.0-2.3 | 49.44 ns/op, 24 B/op, 2 allocs/op* | 51.93 ns/op, 32 B/op, 2 allocs/op* | +| ugorji/go 1.2.6 | ⚠️ 45021 ns/op, 262852 B/op, 7 allocs/op | 💥 runtime: out of memory: cannot allocate | +| ugorji/go 1.1-1.1.7 | 💥 runtime: out of memory: cannot allocate | 💥 runtime: out of memory: cannot allocate| + +*Speed and memory are for latest codec version listed in the row (compiled with Go 1.17.5). fxamacker/cbor CBOR safety settings include: MaxNestedLevels, MaxArrayElements, MaxMapPairs, and IndefLength. @@ -53,47 +88,48 @@ fxamacker/cbor 2.3.0 (not using `unsafe`) is faster than ugorji/go 1.2.6 (using `unsafe`). ``` +benchstat results/bench-ugorji-go-count20.txt results/bench-fxamacker-cbor-count20.txt name old time/op new time/op delta -DecodeCWTClaims-4 2.06µs ± 1% 1.25µs ± 0% -39.57% (p=0.000 n=10+9) -DecodeCOSE/128-Bit_Symmetric_Key-4 1.47µs ± 1% 0.86µs ± 0% -41.25% (p=0.000 n=9+9) -DecodeCOSE/256-Bit_Symmetric_Key-4 1.50µs ± 2% 0.88µs ± 0% -41.63% (p=0.000 n=10+10) -DecodeCOSE/ECDSA_P256_256-Bit_Key-4 2.22µs ± 2% 1.45µs ± 0% -34.65% (p=0.000 n=10+10) -DecodeWebAuthn-4 1.55µs ± 0% 1.32µs ± 0% -14.97% (p=0.000 n=9+10) -EncodeCWTClaims-4 1.46µs ± 0% 0.78µs ± 0% -46.52% (p=0.000 n=10+10) -EncodeCOSE/128-Bit_Symmetric_Key-4 1.79µs ± 1% 0.91µs ± 0% -49.38% (p=0.000 n=9+10) -EncodeCOSE/256-Bit_Symmetric_Key-4 1.79µs ± 1% 0.91µs ± 0% -49.15% (p=0.000 n=10+10) -EncodeCOSE/ECDSA_P256_256-Bit_Key-4 2.09µs ± 1% 1.14µs ± 0% -45.41% (p=0.000 n=10+10) -EncodeWebAuthn-4 981ns ± 0% 823ns ± 1% -16.05% (p=0.000 n=10+10) +DecodeCWTClaims-8 1.08µs ± 0% 0.67µs ± 0% -38.10% (p=0.000 n=16+20) +DecodeCOSE/128-Bit_Symmetric_Key-8 715ns ± 0% 501ns ± 0% -29.97% (p=0.000 n=20+19) +DecodeCOSE/256-Bit_Symmetric_Key-8 722ns ± 0% 507ns ± 0% -29.72% (p=0.000 n=19+18) +DecodeCOSE/ECDSA_P256_256-Bit_Key-8 1.11µs ± 0% 0.83µs ± 0% -25.27% (p=0.000 n=19+20) +DecodeWebAuthn-8 880ns ± 0% 727ns ± 0% -17.31% (p=0.000 n=18+20) +EncodeCWTClaims-8 785ns ± 0% 388ns ± 0% -50.51% (p=0.000 n=20+20) +EncodeCOSE/128-Bit_Symmetric_Key-8 973ns ± 0% 433ns ± 0% -55.45% (p=0.000 n=20+19) +EncodeCOSE/256-Bit_Symmetric_Key-8 974ns ± 0% 435ns ± 0% -55.37% (p=0.000 n=20+19) +EncodeCOSE/ECDSA_P256_256-Bit_Key-8 1.14µs ± 0% 0.55µs ± 0% -52.10% (p=0.000 n=19+19) +EncodeWebAuthn-8 564ns ± 0% 450ns ± 1% -20.18% (p=0.000 n=18+20) name old alloc/op new alloc/op delta -DecodeCWTClaims-4 760B ± 0% 176B ± 0% -76.84% (p=0.000 n=10+10) -DecodeCOSE/128-Bit_Symmetric_Key-4 800B ± 0% 240B ± 0% -70.00% (p=0.000 n=10+10) -DecodeCOSE/256-Bit_Symmetric_Key-4 816B ± 0% 256B ± 0% -68.63% (p=0.000 n=10+10) -DecodeCOSE/ECDSA_P256_256-Bit_Key-4 913B ± 0% 352B ± 0% -61.45% (p=0.000 n=10+10) -DecodeWebAuthn-4 1.56kB ± 0% 0.99kB ± 0% -36.41% (p=0.000 n=10+10) -EncodeCWTClaims-4 1.36kB ± 0% 0.18kB ± 0% -87.06% (p=0.000 n=10+10) -EncodeCOSE/128-Bit_Symmetric_Key-4 1.97kB ± 0% 0.22kB ± 0% -88.62% (p=0.000 n=10+10) -EncodeCOSE/256-Bit_Symmetric_Key-4 1.97kB ± 0% 0.24kB ± 0% -87.80% (p=0.000 n=10+10) -EncodeCOSE/ECDSA_P256_256-Bit_Key-4 1.97kB ± 0% 0.32kB ± 0% -83.74% (p=0.000 n=10+10) -EncodeWebAuthn-4 1.31kB ± 0% 1.09kB ± 0% -17.07% (p=0.000 n=10+10) +DecodeCWTClaims-8 744B ± 0% 160B ± 0% -78.49% (p=0.000 n=20+20) +DecodeCOSE/128-Bit_Symmetric_Key-8 792B ± 0% 232B ± 0% -70.71% (p=0.000 n=20+20) +DecodeCOSE/256-Bit_Symmetric_Key-8 816B ± 0% 256B ± 0% -68.63% (p=0.000 n=20+20) +DecodeCOSE/ECDSA_P256_256-Bit_Key-8 905B ± 0% 344B ± 0% -61.99% (p=0.000 n=20+20) +DecodeWebAuthn-8 1.56kB ± 0% 0.99kB ± 0% -36.41% (p=0.000 n=20+20) +EncodeCWTClaims-8 1.35kB ± 0% 0.18kB ± 0% -86.98% (p=0.000 n=20+20) +EncodeCOSE/128-Bit_Symmetric_Key-8 1.95kB ± 0% 0.22kB ± 0% -88.52% (p=0.000 n=20+20) +EncodeCOSE/256-Bit_Symmetric_Key-8 1.95kB ± 0% 0.24kB ± 0% -87.70% (p=0.000 n=20+20) +EncodeCOSE/ECDSA_P256_256-Bit_Key-8 1.95kB ± 0% 0.32kB ± 0% -83.61% (p=0.000 n=20+20) +EncodeWebAuthn-8 1.30kB ± 0% 1.09kB ± 0% -16.56% (p=0.000 n=20+20) name old allocs/op new allocs/op delta -DecodeCWTClaims-4 6.00 ± 0% 6.00 ± 0% ~ (all equal) -DecodeCOSE/128-Bit_Symmetric_Key-4 4.00 ± 0% 4.00 ± 0% ~ (all equal) -DecodeCOSE/256-Bit_Symmetric_Key-4 4.00 ± 0% 4.00 ± 0% ~ (all equal) -DecodeCOSE/ECDSA_P256_256-Bit_Key-4 7.00 ± 0% 7.00 ± 0% ~ (all equal) -DecodeWebAuthn-4 5.00 ± 0% 5.00 ± 0% ~ (all equal) -EncodeCWTClaims-4 4.00 ± 0% 2.00 ± 0% -50.00% (p=0.000 n=10+10) -EncodeCOSE/128-Bit_Symmetric_Key-4 6.00 ± 0% 2.00 ± 0% -66.67% (p=0.000 n=10+10) -EncodeCOSE/256-Bit_Symmetric_Key-4 6.00 ± 0% 2.00 ± 0% -66.67% (p=0.000 n=10+10) -EncodeCOSE/ECDSA_P256_256-Bit_Key-4 6.00 ± 0% 2.00 ± 0% -66.67% (p=0.000 n=10+10) -EncodeWebAuthn-4 4.00 ± 0% 2.00 ± 0% -50.00% (p=0.000 n=10+10) +DecodeCWTClaims-8 6.00 ± 0% 6.00 ± 0% ~ (all equal) +DecodeCOSE/128-Bit_Symmetric_Key-8 4.00 ± 0% 4.00 ± 0% ~ (all equal) +DecodeCOSE/256-Bit_Symmetric_Key-8 4.00 ± 0% 4.00 ± 0% ~ (all equal) +DecodeCOSE/ECDSA_P256_256-Bit_Key-8 7.00 ± 0% 7.00 ± 0% ~ (all equal) +DecodeWebAuthn-8 5.00 ± 0% 5.00 ± 0% ~ (all equal) +EncodeCWTClaims-8 4.00 ± 0% 2.00 ± 0% -50.00% (p=0.000 n=20+20) +EncodeCOSE/128-Bit_Symmetric_Key-8 6.00 ± 0% 2.00 ± 0% -66.67% (p=0.000 n=20+20) +EncodeCOSE/256-Bit_Symmetric_Key-8 6.00 ± 0% 2.00 ± 0% -66.67% (p=0.000 n=20+20) +EncodeCOSE/ECDSA_P256_256-Bit_Key-8 6.00 ± 0% 2.00 ± 0% -66.67% (p=0.000 n=20+20) +EncodeWebAuthn-8 4.00 ± 0% 2.00 ± 0% -50.00% (p=0.000 n=20+20) ``` -Benchmarks used Go 1.15.12, linux_amd64 with data from [RFC 8392 Appendix A.1](https://tools.ietf.org/html/rfc8392#appendix-A.1). Default build options were used for all CBOR libraries. Library init code was put outside the benchmark loop for all libraries compared. +Benchmarks used Go 1.17.5, linux_amd64, and data from [RFC 8392 Appendix A.1](https://tools.ietf.org/html/rfc8392#appendix-A.1). Default build options were used for all CBOR libraries. Library init code was put outside the benchmark loop for all libraries compared. -## CBOR Library API +## CBOR API __fxamacker/cbor__ is easy to use. It provides standard API and interfaces. @@ -106,10 +142,10 @@ __Predefined Encoding Options__. Encoding options are easy to use and are customizable. ```go -func CanonicalEncOptions() EncOptions {} // RFC 7049 Canonical CBOR -func CTAP2EncOptions() EncOptions {} // FIDO2 CTAP2 Canonical CBOR func CoreDetEncOptions() EncOptions {} // RFC 8949 Core Deterministic Encoding func PreferredUnsortedEncOptions() EncOptions {} // RFC 8949 Preferred Serialization +func CanonicalEncOptions() EncOptions {} // RFC 7049 Canonical CBOR +func CTAP2EncOptions() EncOptions {} // FIDO2 CTAP2 Canonical CBOR ``` fxamacker/cbor designed to simplify concurrency. CBOR options can be used without creating unintended runtime side-effects. @@ -220,10 +256,10 @@ __Predefined Encoding Options__ ```go -func CanonicalEncOptions() EncOptions {} // RFC 7049 Canonical CBOR -func CTAP2EncOptions() EncOptions {} // FIDO2 CTAP2 Canonical CBOR func CoreDetEncOptions() EncOptions {} // RFC 8949 Core Deterministic Encoding func PreferredUnsortedEncOptions() EncOptions {} // RFC 8949 Preferred Serialization +func CanonicalEncOptions() EncOptions {} // RFC 7049 Canonical CBOR +func CTAP2EncOptions() EncOptions {} // FIDO2 CTAP2 Canonical CBOR ``` The empty curly braces prevent a syntax highlighting bug on GitHub, please ignore them. @@ -242,76 +278,7 @@
-⚓ [Quick Start](#quick-start) • [Status](#current-status) • [Design Goals](#design-goals) • [Features](#features) • [Standards](#standards) • [API](#api) • [Options](#options) • [Usage](#usage) • [Fuzzing](#fuzzing-and-code-coverage) • [License](#license) - -## Current Status -Latest version is v2.3 (May 30, 2021), which has: - -* __Stable API__ – Six codec function signatures will never change. No breaking API changes for other funcs in same major version. -* __Passed all tests__ – v2.x passed all 375+ tests on amd64, arm64, ppc64le and s390x with linux. -* __Passed fuzzing__ – v2.2 passed 459+ million execs in coverage-guided fuzzing on Feb 24, 2020 (release date) -and 3.2+ billion execs on March 7, 2020. v2.3 passed 357+ million execs on May 30, 2021 (and is continuing to fuzz). - -
- -⚓ [Quick Start](#quick-start) • [Status](#current-status) • [Design Goals](#design-goals) • [Features](#features) • [Standards](#standards) • [API](#api) • [Options](#options) • [Usage](#usage) • [Fuzzing](#fuzzing-and-code-coverage) • [License](#license) - -## Design Goals -This library is designed to be a generic CBOR encoder and decoder. It was initially created for a [WebAuthn (FIDO2) server library](https://github.com/fxamacker/webauthn), because existing CBOR libraries (in Go) didn't meet certain criteria in 2019. - -This library is designed to be: - -* __Easy__ – API is like `encoding/json` plus `keyasint` and `toarray` struct tags. -* __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. Decoder settings include: `MaxNestedLevels`, `MaxArrayElements`, `MaxMapPairs`, and `IndefLength`. - -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:__ - -
- Supported CBOR Features (Highlights)

- -| | CBOR Feature | Description | -| :--- | :--- | :--- | -| ☑️ | CBOR tags | API supports built-in and user-defined tags. | -| ☑️ | Preferred serialization | Integers encode to fewest bytes. Optional float64 → float32 → float16. | -| ☑️ | Map key sorting | Unsorted, length-first (Canonical CBOR), and bytewise-lexicographic (CTAP2). | -| ☑️ | Duplicate map keys | Always forbid for encoding and option to allow/forbid for decoding. | -| ☑️ | Indefinite length data | Option to allow/forbid for encoding and decoding. | -| ☑️ | Well-formedness | Always checked and enforced. | -| ☑️ | Basic validity checks | Check UTF-8 validity and optionally check duplicate map keys. | -| ☑️ | Security considerations | Prevent integer overflow and resource exhaustion (RFC 8949 Section 10). | - -

- -
- v2.0 API Design

- -v2.0 decoupled options from CBOR encoding & decoding functions: - -* More encoding/decoding function signatures are identical to encoding/json. -* More function signatures can remain stable forever. -* More flexibility for evolving internal data types, optimizations, and concurrency. -* 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. - -

- -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. - -
- -⚓ [Quick Start](#quick-start) • [Status](#current-status) • [Design Goals](#design-goals) • [Features](#features) • [Standards](#standards) • [API](#api) • [Options](#options) • [Usage](#usage) • [Fuzzing](#fuzzing-and-code-coverage) • [License](#license) +⚓ [Quick Start](#quick-start) • [Features](#features) • [Standards](#standards) • [API](#api) • [Options](#options) • [Usage](#usage) • [Fuzzing](#fuzzing-and-code-coverage) • [License](#license) ## Features @@ -341,9 +308,9 @@ ### CBOR Tags (New in v2.1) -There are three broad categories of CBOR tags: +There are three categories of CBOR tags: -* __Default built-in CBOR tags__ currently include tag numbers 0 and 1 (Time). Additional default built-in tags in future releases may include tag numbers 2 and 3 (Bignum). +* __Default built-in CBOR tags__ currently include tag numbers 0 (Standard Date/Time), 1 (Epoch Date/Time), 2 (Unsigned Bignum), 3 (Negative Bignum), 55799 (Self-Described CBOR). * __Optional built-in CBOR tags__ may be provided in the future via build flags or optional package(s) to help reduce bloat. @@ -373,12 +340,13 @@ | EncOptions | Available Settings (defaults listed first) | :--- | :--- | -| Sort | [**SortNone**, SortLengthFirst, SortBytewiseLexical
Aliases: SortCanonical, SortCTAP2, SortCoreDeterministic | -| Time | [**TimeUnix**, TimeUnixMicro, TimeUnixDynamic, TimeRFC3339, TimeRFC3339Nano | -| TimeTag | [**EncTagNone**, EncTagRequired | -| ShortestFloat | [**ShortestFloatNone**, ShortestFloat16 | -| InfConvert | [**InfConvertFloat16**, InfConvertNone | -| NaNConvert | [**NaNConvert7e00**, NaNConvertNone, NaNConvertQuiet, NaNConvertPreserveSignal | +| Sort | **SortNone**, SortLengthFirst, SortBytewiseLexical
Aliases: SortCanonical, SortCTAP2, SortCoreDeterministic | +| Time | **TimeUnix**, TimeUnixMicro, TimeUnixDynamic, TimeRFC3339, TimeRFC3339Nano | +| TimeTag | **EncTagNone**, EncTagRequired | +| ShortestFloat | **ShortestFloatNone**, ShortestFloat16 | +| BigIntConvert | **BigIntConvertShortest**, BigIntConvertNone | +| InfConvert | **InfConvertFloat16**, InfConvertNone | +| NaNConvert | **NaNConvert7e00**, NaNConvertNone, NaNConvertQuiet, NaNConvertPreserveSignal | | IndefLength | **IndefLengthAllowed**, IndefLengthForbidden | | TagsMd | **TagsAllowed**, TagsForbidden | @@ -390,11 +358,13 @@ | :--- | :--- | | TimeTag | **DecTagIgnored**, DecTagOptional, DecTagRequired | | DupMapKey | **DupMapKeyQuiet**, DupMapKeyEnforcedAPF | +| IntDec | **IntDecConvertNone**, IntDecConvertSigned | | IndefLength | **IndefLengthAllowed**, IndefLengthForbidden | | TagsMd | **TagsAllowed**, TagsForbidden | +| ExtraReturnErrors | **ExtraDecErrorNone**, ExtraDecErrorUnknownField | | MaxNestedLevels | **32**, can be set to [4, 256] | -| MaxArrayElements | **131072**, can be set to [16, 134217728] | -| MaxMapPairs | **131072**, can be set to [16, 134217728] | +| MaxArrayElements | **131072**, can be set to [16, 2147483647] | +| MaxMapPairs | **131072**, can be set to [16, 2147483647] | See [Options](#options) section for details about each setting. @@ -403,15 +373,16 @@ * Decoder always checks for invalid UTF-8 string errors. * Decoder always decodes in-place to slices, maps, and structs. * Decoder tries case-sensitive first and falls back to case-insensitive field name match when decoding to structs. +* Decoder supports decoding registered CBOR tag data to interface types. * Both encoder and decoder support indefinite length CBOR data (["streaming"](https://tools.ietf.org/html/rfc7049#section-2.2)). * Both encoder and decoder correctly handles nil slice, map, pointer, and interface values.
-⚓ [Quick Start](#quick-start) • [Status](#current-status) • [Design Goals](#design-goals) • [Features](#features) • [Standards](#standards) • [API](#api) • [Options](#options) • [Usage](#usage) • [Fuzzing](#fuzzing-and-code-coverage) • [License](#license) +⚓ [Quick Start](#quick-start) • [Features](#features) • [Standards](#standards) • [API](#api) • [Options](#options) • [Usage](#usage) • [Fuzzing](#fuzzing-and-code-coverage) • [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: +This library is a full-featured generic CBOR [(RFC 8949)](https://tools.ietf.org/html/rfc8949) encoder and decoder. Notable CBOR features include: | | CBOR Feature | Description | | :--- | :--- | :--- | @@ -461,12 +432,12 @@
Tag Validity

-This library checks tag validity for built-in tags (currently tag numbers 0 and 1): +This library checks tag validity for built-in tags (currently tag numbers 0, 1, 2, 3, and 55799): * Inadmissible type for tag content * Inadmissible value for tag content -Unknown tag data items (not tag number 0 or 1) are handled in two ways: +Unknown tag data items (not tag number 0, 1, 2, 3, or 55799) are handled in two ways: * When decoding into an empty interface, unknown tag data item will be decoded into `cbor.Tag` data type, which contains tag number and tag content. The tag content will be decoded into the default Go data type for the CBOR data type. * When decoding into other Go types, unknown tag data item is decoded into the specified Go type. If Go type is registered with a tag number, the tag number can optionally be verified. @@ -484,10 +455,11 @@ * CBOR `Undefined` (0xf7) value decodes to Go's `nil` value. CBOR `Null` (0xf6) more closely matches Go's `nil`. * CBOR map keys with data types not supported by Go for map keys are ignored and an error is returned after continuing to decode remaining items. * When using io.Reader interface to read very large or indefinite length CBOR data, Go's `io.LimitReader` should be used to limit size. +* When decoding registered CBOR tag data to interface type, decoder creates a pointer to registered Go type matching CBOR tag number. Requiring a pointer for this is a Go limitation.


-⚓ [Quick Start](#quick-start) • [Status](#current-status) • [Design Goals](#design-goals) • [Features](#features) • [Standards](#standards) • [API](#api) • [Options](#options) • [Usage](#usage) • [Fuzzing](#fuzzing-and-code-coverage) • [License](#license) +⚓ [Quick Start](#quick-start) • [Features](#features) • [Standards](#standards) • [API](#api) • [Options](#options) • [Usage](#usage) • [Fuzzing](#fuzzing-and-code-coverage) • [License](#license) ## API Many function signatures are identical to Go's encoding/json, such as: @@ -547,10 +519,10 @@ __API for Predefined Encoding Options__ ```go -func CanonicalEncOptions() EncOptions {} // RFC 7049 Canonical CBOR -func CTAP2EncOptions() EncOptions {} // FIDO2 CTAP2 Canonical CBOR func CoreDetEncOptions() EncOptions {} // RFC 8949 Core Deterministic Encoding func PreferredUnsortedEncOptions() EncOptions {} // RFC 8949 Preferred Serialization +func CanonicalEncOptions() EncOptions {} // RFC 7049 Canonical CBOR +func CTAP2EncOptions() EncOptions {} // FIDO2 CTAP2 Canonical CBOR ``` __API for Creating & Using Decoding Modes__ @@ -614,7 +586,7 @@
-⚓ [Quick Start](#quick-start) • [Status](#current-status) • [Design Goals](#design-goals) • [Features](#features) • [Standards](#standards) • [API](#api) • [Options](#options) • [Usage](#usage) • [Fuzzing](#fuzzing-and-code-coverage) • [License](#license) +⚓ [Quick Start](#quick-start) • [Features](#features) • [Standards](#standards) • [API](#api) • [Options](#options) • [Usage](#usage) • [Fuzzing](#fuzzing-and-code-coverage) • [License](#license) ## Options @@ -636,10 +608,10 @@ ``` type myStruct struct { - MyField int64 `cbor:-1,keyasint,omitempty` - OurField string `cbor:0,keyasint,omitempty` - FooField Foo `cbor:5,keyasint,omitempty` - BarField Bar `cbor:hello,omitempty` + MyField int64 `cbor:"-1,keyasint,omitempty'` + OurField string `cbor:"0,keyasint,omitempty"` + FooField Foo `cbor:"5,keyasint,omitempty"` + BarField Bar `cbor:"hello,omitempty"` ... } ``` @@ -693,6 +665,15 @@
+| DecOptions.IntDec | Description | +| ------------------ | ----------- | +| IntDecConvertNone (default) | When decoding to Go interface{}, CBOR positive int (major type 0) decode to uint64 value, and CBOR negative int (major type 1) decode to int64 value. | +| IntDecConvertSigned | When decoding to Go interface{}, CBOR positive/negative int (major type 0 and 1) decode to int64 value. | + +If `IntDecConvertedSigned` is used and value overflows int64, UnmarshalTypeError is returned. + +
+ | DecOptions.IndefLength | Description | | ---------------------- | ----------- | |IndefLengthAllowed (default) | allow indefinite length data | @@ -707,6 +688,13 @@
+| DecOptions.ExtraReturnErrors | Description | +| ----------------- | ----------- | +|ExtraDecErrorNone (default) | no extra decoding errors. E.g. ignore unknown fields if encountered. | +|ExtraDecErrorUnknownField | return error if unknown field is encountered | + +
+ | DecOptions.MaxNestedLevels | Description | | -------------------------- | ----------- | | 32 (default) | allowed setting is [4, 256] | @@ -742,10 +730,10 @@ | --------------- | ----------- | | SortNone (default) |No sorting for map keys. | | SortLengthFirst |Length-first map key ordering. | -| SortBytewiseLexical |Bytewise lexicographic map key ordering | +| SortBytewiseLexical |Bytewise lexicographic map key ordering [(RFC 8949 Section 4.2.1)](https://datatracker.ietf.org/doc/html/rfc8949#section-4.2.1).| | 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. | +| SortCoreDeterministic |(alias) Same as SortBytewiseLexical [(RFC 8949 Section 4.2.1)](https://datatracker.ietf.org/doc/html/rfc8949#section-4.2.1). |
@@ -764,14 +752,19 @@ | 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__ - By default, undefined (zero instant) time values will encode as CBOR Null without tag number for both EncTagNone and EncTagRequired. Although CBOR Undefined might be technically more correct for EncTagRequired, CBOR Undefined might not be supported by other generic decoders and it isn't supported by JSON. Go's `time` package provides `IsZero` function, which reports whether t represents the zero time instant, January 1, year 1, 00:00:00 UTC.
+| EncOptions.BigIntConvert | Description | +| ------------------------ | ----------- | +| BigIntConvertShortest (default) | Encode big.Int as CBOR integer if value fits. | +| BigIntConvertNone | Encode big.Int as CBOR bignum (tag 2 or 3). | + +
+ __Floating-Point Options__ Encoder has 3 types of options for floating-point data: ShortestFloatMode, InfConvertMode, and NaNConvertMode. @@ -792,7 +785,7 @@ | EncOptions.NaNConvert | Description | | --------------------- | ----------- | -| NaNConvert7e00 (default) | Encode to 0xf97e00 (CBOR float16 = 0x7e00) -- used by RFC 7049 Canonical CBOR. | +| NaNConvert7e00 (default) | Encode to 0xf97e00 (CBOR float16 = 0x7e00) -- used by RFC 8949 Preferred Encoding, etc. | | 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). | @@ -831,7 +824,7 @@
-⚓ [Quick Start](#quick-start) • [Status](#current-status) • [Design Goals](#design-goals) • [Features](#features) • [Standards](#standards) • [API](#api) • [Options](#options) • [Usage](#usage) • [Fuzzing](#fuzzing-and-code-coverage) • [License](#license) +⚓ [Quick Start](#quick-start) • [Features](#features) • [Standards](#standards) • [API](#api) • [Options](#options) • [Usage](#usage) • [Fuzzing](#fuzzing-and-code-coverage) • [License](#license) ## Usage 🛡️ Use Go's `io.LimitReader` to limit size when decoding very large or indefinite size data. @@ -968,7 +961,7 @@
-⚓ [Quick Start](#quick-start) • [Status](#current-status) • [Design Goals](#design-goals) • [Features](#features) • [Standards](#standards) • [API](#api) • [Options](#options) • [Usage](#usage) • [Fuzzing](#fuzzing-and-code-coverage) • [License](#license) +⚓ [Quick Start](#quick-start) • [Features](#features) • [Standards](#standards) • [API](#api) • [Options](#options) • [Usage](#usage) • [Fuzzing](#fuzzing-and-code-coverage) • [License](#license) ## Comparisons @@ -976,11 +969,18 @@ __This library is safer__. Small malicious CBOR messages are rejected quickly before they exhaust system resources. -| | **fxamacker/cbor (1.0 - 2.x)** | **ugorji/go (1.1.0 - 1.1.7)** | +Decoding 9 or 10 bytes of malformed CBOR data shouldn't exhaust memory. For example, +`[]byte{0x9B, 0x00, 0x00, 0x42, 0xFA, 0x42, 0xFA, 0x42, 0xFA, 0x42}` + +| | Decode bad 10 bytes to interface{} | Decode bad 10 bytes to []byte | | :--- | :------------------ | :--------------- | -| **Malformed CBOR 1** | 59.8 ns/op, 32 B/op, 1 allocs/op | :boom: fatal error: out of memory | -| **Malformed CBOR 2** | 149 ns/op, 128 B/op, 3 allocs/op | :boom: runtime: out of memory: cannot allocate | -| | Correctly rejected bad data. | :warning: Only 1 decode < 10 bytes produces fatal error. | +| fxamacker/cbor
1.0-2.3 | 49.44 ns/op, 24 B/op, 2 allocs/op* | 51.93 ns/op, 32 B/op, 2 allocs/op* | +| ugorji/go 1.2.6 | ⚠️ 45021 ns/op, 262852 B/op, 7 allocs/op | 💥 runtime: out of memory: cannot allocate | +| ugorji/go 1.1.0-1.1.7 | 💥 runtime: out of memory: cannot allocate | 💥 runtime: out of memory: cannot allocate| + +*Speed and memory are for latest codec version listed in the row (compiled with Go 1.17.5). + +fxamacker/cbor CBOR safety settings include: MaxNestedLevels, MaxArrayElements, MaxMapPairs, and IndefLength. __This library is smaller__. Programs like senmlCat can be 4 MB smaller by switching to this library. Programs using more complex CBOR data types can be 9.2 MB smaller. @@ -993,16 +993,16 @@ __This library uses less memory__ for encoding and decoding CBOR Web Token (CWT) using test data from RFC 8392 A.1. -| | fxamacker/cbor 2.2 | ugorji/go 1.1.7 | +| | fxamacker/cbor 2.3 | ugorji/go 1.2.6 | | :--- | :--- | :--- | -| Encode CWT | 176 bytes/op     2 allocs/op | 1424 bytes/op     4 allocs/op | -| Decode CWT | 176 bytes/op     6 allocs/op |   568 bytes/op     6 allocs/op | +| Encode CWT | 0.18 kB/op         2 allocs/op | 1.35 kB/op         4 allocs/op | +| Decode CWT | 160 bytes/op     6 allocs/op | 744 bytes/op     6 allocs/op | -Doing your own comparisons is highly recommended. Use your most common message sizes and data types. +Running your own benchmarks is highly recommended. Use your most common data structures and data sizes.
-⚓ [Quick Start](#quick-start) • [Status](#current-status) • [Design Goals](#design-goals) • [Features](#features) • [Standards](#standards) • [API](#api) • [Options](#options) • [Usage](#usage) • [Fuzzing](#fuzzing-and-code-coverage) • [License](#license) +⚓ [Quick Start](#quick-start) • [Features](#features) • [Standards](#standards) • [API](#api) • [Options](#options) • [Usage](#usage) • [Fuzzing](#fuzzing-and-code-coverage) • [License](#license) ## Benchmarks @@ -1027,25 +1027,17 @@ ## Fuzzing and Code Coverage -__Over 375 tests__ must pass on 4 architectures before tagging a release. They include all RFC 7049 examples, bugs found by fuzzing, maliciously crafted CBOR data, and over 87 tests with malformed data. - -__Code coverage__ must not fall below 95% when tagging a release. Code coverage is 98.6% (`go test -cover`) for cbor v2.2 which is among the highest for libraries (in Go) of this type. - -__Coverage-guided fuzzing__ must pass 250+ million execs before tagging a release. Fuzzing uses [fxamacker/cbor-fuzz](https://github.com/fxamacker/cbor-fuzz). Default corpus has: +__Over 375 tests__ must pass on 4 architectures before tagging a release. They include all RFC 7049 and RFC 8949 examples, bugs found by fuzzing, maliciously crafted CBOR data, and over 87 tests with malformed data. There's some overlap in the tests but it isn't a high priority to trim tests. -* 2 files related to WebAuthn (FIDO U2F key). -* 3 files with custom struct. -* 9 files with [CWT examples (RFC 8392 Appendix A)](https://tools.ietf.org/html/rfc8392#appendix-A). -* 17 files with [COSE examples (RFC 8152 Appendix B & C)](https://github.com/cose-wg/Examples/tree/master/RFC8152). -* 81 files with [CBOR examples (RFC 7049 Appendix A) ](https://tools.ietf.org/html/rfc7049#appendix-A). It excludes 1 errata first reported in [issue #46](https://github.com/fxamacker/cbor/issues/46). +__Code coverage__ must not fall below 95% when tagging a release. Code coverage is above 98% (`go test -cover`) for cbor v2.3 which is among the highest for libraries (in Go) of this type. -Over 1,100 files (corpus) are used for fuzzing because it includes fuzz-generated corpus. +__Coverage-guided fuzzing__ must pass 1+ billion execs using a large corpus before tagging a release. Fuzzing is usually continued after the release is tagged and is manually stopped after reaching 1-3 billion execs. Fuzzing uses a customized version of [dvyukov/go-fuzz](https://github.com/dvyukov/go-fuzz). -To prevent excessive delays, fuzzing is not restarted for a release if changes are limited to docs and comments. +To prevent delays to release schedules, fuzzing is not restarted for a release if changes are limited to ci, docs, and comments.
-⚓ [Quick Start](#quick-start) • [Status](#current-status) • [Design Goals](#design-goals) • [Features](#features) • [Standards](#standards) • [API](#api) • [Options](#options) • [Usage](#usage) • [Fuzzing](#fuzzing-and-code-coverage) • [License](#license) +⚓ [Quick Start](#quick-start) • [Features](#features) • [Standards](#standards) • [API](#api) • [Options](#options) • [Usage](#usage) • [Fuzzing](#fuzzing-and-code-coverage) • [License](#license) ## Versions and API Changes This project uses [Semantic Versioning](https://semver.org), so the API is always backwards compatible unless the major version number changes. @@ -1077,7 +1069,7 @@ __Making this library better__ -* Stefan Tatschner for using this library in [sep](https://git.sr.ht/~rumpelsepp/sep), being the 1st to discover my CBOR library, requesting time.Time in issue #1, and submitting this library in a [PR to cbor.io](https://github.com/cbor/cbor.github.io/pull/56) on Aug 12, 2019. +* Stefan Tatschner for using this library in [sep](https://rumpelsepp.org/projects/sep), being the 1st to discover my CBOR library, requesting time.Time in issue #1, and submitting this library in a [PR to cbor.io](https://github.com/cbor/cbor.github.io/pull/56) on Aug 12, 2019. * Yawning Angel for using this library to [oasis-core](https://github.com/oasislabs/oasis-core), and requesting BinaryMarshaler in issue #5. * Jernej Kos for requesting RawMessage in issue #11 and offering feedback on v2.1 API for CBOR tags. * ZenGround0 for using this library in [go-filecoin](https://github.com/filecoin-project/go-filecoin), filing "toarray" bug in issue #129, and requesting @@ -1096,10 +1088,10 @@ ## License -Copyright © 2019-2021 [Faye Amacker](https://github.com/fxamacker). +Copyright © 2019-2022 [Faye Amacker](https://github.com/fxamacker). fxamacker/cbor is licensed under the MIT License. See [LICENSE](LICENSE) for the full license text.
-⚓ [Quick Start](#quick-start) • [Status](#current-status) • [Design Goals](#design-goals) • [Features](#features) • [Standards](#standards) • [API](#api) • [Options](#options) • [Usage](#usage) • [Fuzzing](#fuzzing-and-code-coverage) • [License](#license) +⚓ [Quick Start](#quick-start) • [Features](#features) • [Standards](#standards) • [API](#api) • [Options](#options) • [Usage](#usage) • [Fuzzing](#fuzzing-and-code-coverage) • [License](#license) diff -Nru golang-github-fxamacker-cbor-2.3.0/tag.go golang-github-fxamacker-cbor-2.4.0/tag.go --- golang-github-fxamacker-cbor-2.3.0/tag.go 2021-11-07 18:31:10.000000000 +0000 +++ golang-github-fxamacker-cbor-2.4.0/tag.go 2022-01-07 21:04:46.000000000 +0000 @@ -264,12 +264,6 @@ if num == selfDescribedCBORTagNum { return nil, errors.New("cbor: cannot add tag number 55799 to TagSet, it's built-in and ignored automatically") } - //if reflect.PtrTo(contentType).Implements(typeMarshaler) && opts.EncTag != EncTagNone { - //return nil, errors.New("cbor: cannot add cbor.Marshaler to TagSet with EncTag != EncTagNone") - //} - //if reflect.PtrTo(contentType).Implements(typeUnmarshaler) && opts.DecTag != DecTagIgnored { - //return nil, errors.New("cbor: cannot add cbor.Unmarshaler to TagSet with DecTag != DecTagIgnored") - //} te := tagItem{num: []uint64{num}, opts: opts, contentType: contentType} te.num = append(te.num, nestedNum...)