From d50bec7bf527c22d482c63328aff22e23b702187 Mon Sep 17 00:00:00 2001 From: Faye Amacker <33205765+fxamacker@users.noreply.github.com> Date: Sun, 8 Sep 2024 10:24:43 -0500 Subject: [PATCH] Reduce DecOptions.MaxNestedLevels default (tinygo) Currently, tests panic if compiled with tinygo v0.33 when decoding data with 24+ nested levels. This commit reduces default MaxNestedLevels to 16 (was 32). To allow testing, etc. the user configurable limits are unchanged (allows up to 65535). --- decode.go | 4 ---- decode_not_tinygo.go | 6 ++++++ decode_test.go | 4 ++-- decode_tinygo.go | 6 ++++++ valid_not_tinygo_test.go | 34 ++++++++++++++++++++++++++++++++++ valid_test.go | 21 +++++++++++---------- 6 files changed, 59 insertions(+), 16 deletions(-) create mode 100644 valid_not_tinygo_test.go diff --git a/decode.go b/decode.go index f25f22e..074df74 100644 --- a/decode.go +++ b/decode.go @@ -960,10 +960,6 @@ const ( defaultMaxMapPairs = 131072 minMaxMapPairs = 16 maxMaxMapPairs = 2147483647 - - defaultMaxNestedLevels = 32 - minMaxNestedLevels = 4 - maxMaxNestedLevels = 65535 ) var defaultSimpleValues = func() *SimpleValueRegistry { diff --git a/decode_not_tinygo.go b/decode_not_tinygo.go index 35e5fef..e5bf18b 100644 --- a/decode_not_tinygo.go +++ b/decode_not_tinygo.go @@ -7,6 +7,12 @@ 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.PointerTo(concreteType).Implements(interfaceType) diff --git a/decode_test.go b/decode_test.go index 36b4abf..855b80a 100644 --- a/decode_test.go +++ b/decode_test.go @@ -4995,8 +4995,8 @@ func TestDecModeDefaultMaxNestedLevel(t *testing.T) { t.Errorf("DecMode() returned error %v", err) } else { maxNestedLevels := dm.DecOptions().MaxNestedLevels - if maxNestedLevels != 32 { - t.Errorf("DecOptions().MaxNestedLevels = %d, want %v", maxNestedLevels, 32) + if maxNestedLevels != defaultMaxNestedLevels { + t.Errorf("DecOptions().MaxNestedLevels = %d, want %v", maxNestedLevels, defaultMaxNestedLevels) } } } diff --git a/decode_tinygo.go b/decode_tinygo.go index 48366f7..8af3cef 100644 --- a/decode_tinygo.go +++ b/decode_tinygo.go @@ -7,6 +7,12 @@ 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(). // diff --git a/valid_not_tinygo_test.go b/valid_not_tinygo_test.go new file mode 100644 index 0000000..7f65e08 --- /dev/null +++ b/valid_not_tinygo_test.go @@ -0,0 +1,34 @@ +// 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) + } + }) + } +} diff --git a/valid_test.go b/valid_test.go index f4637b8..bf6997e 100644 --- a/valid_test.go +++ b/valid_test.go @@ -5,6 +5,7 @@ package cbor import ( "bytes" + "strconv" "testing" ) @@ -102,11 +103,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"))) - {"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"))) + {"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"))) } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { @@ -145,31 +146,31 @@ func TestDepthError(t *testing.T) { name: "33-level array", data: hexDecode("8201818181818181818181818181818181818181818181818181818181818181818101"), opts: DecOptions{}, - wantErrorMsg: "cbor: exceeded max nested level 32", + wantErrorMsg: "cbor: exceeded max nested level " + strconv.Itoa(defaultMaxNestedLevels), }, { name: "33-level indefinite length array", data: hexDecode("9f01818181818181818181818181818181818181818181818181818181818181818101ff"), opts: DecOptions{}, - wantErrorMsg: "cbor: exceeded max nested level 32", + wantErrorMsg: "cbor: exceeded max nested level " + strconv.Itoa(defaultMaxNestedLevels), }, { name: "33-level map", data: hexDecode("a101818181818181818181818181818181818181818181818181818181818181818101"), opts: DecOptions{}, - wantErrorMsg: "cbor: exceeded max nested level 32", + wantErrorMsg: "cbor: exceeded max nested level " + strconv.Itoa(defaultMaxNestedLevels), }, { name: "33-level indefinite length map", data: hexDecode("bf01818181818181818181818181818181818181818181818181818181818181818101ff"), opts: DecOptions{}, - wantErrorMsg: "cbor: exceeded max nested level 32", + wantErrorMsg: "cbor: exceeded max nested level " + strconv.Itoa(defaultMaxNestedLevels), }, { name: "33-level tag", data: hexDecode("d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d864d86474323031332d30332d32315432303a30343a30305a"), opts: DecOptions{}, - wantErrorMsg: "cbor: exceeded max nested level 32", + wantErrorMsg: "cbor: exceeded max nested level " + strconv.Itoa(defaultMaxNestedLevels), }, } for _, tc := range testCases {