Skip to content

Commit

Permalink
Merge pull request #355 from immesys/immesys/increase-nested-levels
Browse files Browse the repository at this point in the history
Allow MaxNestedLevels to be up to 65535
  • Loading branch information
fxamacker committed Jul 4, 2022
2 parents d99d9d4 + d356e3f commit ab3392f
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 9 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ See [Options](#options) section for details about each setting.
| IndefLength | **IndefLengthAllowed**, IndefLengthForbidden |
| TagsMd | **TagsAllowed**, TagsForbidden |
| ExtraReturnErrors | **ExtraDecErrorNone**, ExtraDecErrorUnknownField |
| MaxNestedLevels | **32**, can be set to [4, 256] |
| MaxNestedLevels | **32**, can be set to [4, 65535] |
| MaxArrayElements | **131072**, can be set to [16, 2147483647] |
| MaxMapPairs | **131072**, can be set to [16, 2147483647] |

Expand Down Expand Up @@ -697,7 +697,7 @@ If `IntDecConvertedSigned` is used and value overflows int64, UnmarshalTypeError

| DecOptions.MaxNestedLevels | Description |
| -------------------------- | ----------- |
| 32 (default) | allowed setting is [4, 256] |
| 32 (default) | allowed setting is [4, 65535] |

<br>

Expand Down
7 changes: 4 additions & 3 deletions decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,8 @@ type DecOptions struct {
TimeTag DecTagMode

// MaxNestedLevels specifies the max nested levels allowed for any combination of CBOR array, maps, and tags.
// Default is 32 levels and it can be set to [4, 256].
// Default is 32 levels and it can be set to [4, 65535]. Note that higher maximum levels of nesting can
// require larger amounts of stack to deserialize. Don't increase this higher than you require.
MaxNestedLevels int

// MaxArrayElements specifies the max number of elements for CBOR arrays.
Expand Down Expand Up @@ -402,8 +403,8 @@ func (opts DecOptions) decMode() (*decMode, error) {
}
if opts.MaxNestedLevels == 0 {
opts.MaxNestedLevels = 32
} else if opts.MaxNestedLevels < 4 || opts.MaxNestedLevels > 256 {
return nil, errors.New("cbor: invalid MaxNestedLevels " + strconv.Itoa(opts.MaxNestedLevels) + " (range is [4, 256])")
} else if opts.MaxNestedLevels < 4 || opts.MaxNestedLevels > 65535 {
return nil, errors.New("cbor: invalid MaxNestedLevels " + strconv.Itoa(opts.MaxNestedLevels) + " (range is [4, 65535])")
}
if opts.MaxArrayElements == 0 {
opts.MaxArrayElements = defaultMaxArrayElements
Expand Down
46 changes: 42 additions & 4 deletions decode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3131,6 +3131,44 @@ func TestUnmarshalIntoMapError(t *testing.T) {
}
}

func TestUnmarshalDeepNesting(t *testing.T) {
// Construct this object rather than embed such a large constant in the code
type TestNode struct {
Value int
Child *TestNode
}
n := &TestNode{Value: 0}
root := n
for i := 0; i < 65534; i++ {
child := &TestNode{Value: i}
n.Child = child
n = child
}
em, err := EncOptions{}.EncMode()
if err != nil {
t.Errorf("EncMode() returned error %v", err)
}
cborData, err := em.Marshal(root)
if err != nil {
t.Errorf("Marshal() deeply nested object returned error %v", err)
}

// Try unmarshal it
dm, err := DecOptions{MaxNestedLevels: 65535}.DecMode()
if err != nil {
t.Errorf("DecMode() returned error %v", err)
}
var readback TestNode
err = dm.Unmarshal(cborData, &readback)
if err != nil {
t.Errorf("Unmarshal() of deeply nested object returned error: %v", err)
}
if !reflect.DeepEqual(root, &readback) {
t.Errorf("Unmarshal() of deeply nested object did not match\nGot: %#v\n Want: %#v\n",
&readback, root)
}
}

func TestStructToArrayError(t *testing.T) {
type coseHeader struct {
Alg int `cbor:"1,keyasint,omitempty"`
Expand Down Expand Up @@ -3291,12 +3329,12 @@ func TestDecModeInvalidMaxNestedLevel(t *testing.T) {
{
name: "MaxNestedLevels < 4",
opts: DecOptions{MaxNestedLevels: 1},
wantErrorMsg: "cbor: invalid MaxNestedLevels 1 (range is [4, 256])",
wantErrorMsg: "cbor: invalid MaxNestedLevels 1 (range is [4, 65535])",
},
{
name: "MaxNestedLevels > 256",
opts: DecOptions{MaxNestedLevels: 257},
wantErrorMsg: "cbor: invalid MaxNestedLevels 257 (range is [4, 256])",
name: "MaxNestedLevels > 65535",
opts: DecOptions{MaxNestedLevels: 65536},
wantErrorMsg: "cbor: invalid MaxNestedLevels 65536 (range is [4, 65535])",
},
}
for _, tc := range testCases {
Expand Down

0 comments on commit ab3392f

Please sign in to comment.