Skip to content

Commit

Permalink
Return error on decoding unsupported CBOR neg int
Browse files Browse the repository at this point in the history
CBOR negative integers like -18446744073709551616 are unsupported
because they cannot fit into Go's int64.

Instead of returning 0 with err=nil, cbor.Unmarshal now returns
cbor.UnmarshalTypeError when trying to decode these values.

Closes Issue #14.
  • Loading branch information
fxamacker committed Nov 4, 2019
1 parent 1a29187 commit 47055e7
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 1 deletion.
6 changes: 6 additions & 0 deletions decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,9 @@ func (d *decodeState) parse(v reflect.Value) (err error) {
case cborTypePositiveInt:
return fillPositiveInt(t, val, v)
case cborTypeNegativeInt:
if val > math.MaxInt64 {
return &UnmarshalTypeError{Value: t.String(), Type: v.Type(), errMsg: "-1-" + strconv.FormatUint(val, 10) + " overflows Go's int64"}
}
nValue := int64(-1) ^ int64(val)
return fillNegativeInt(t, nValue, v)
case cborTypeTag:
Expand Down Expand Up @@ -321,6 +324,9 @@ func (d *decodeState) parseInterface() (_ interface{}, err error) {
case cborTypePositiveInt:
return val, nil
case cborTypeNegativeInt:
if val > math.MaxInt64 {
return nil, &UnmarshalTypeError{Value: t.String(), Type: reflect.TypeOf([]interface{}(nil)).Elem(), errMsg: "-1-" + strconv.FormatUint(val, 10) + " overflows Go's int64"}
}
nValue := int64(-1) ^ int64(val)
return nValue, nil
case cborTypeTag:
Expand Down
21 changes: 20 additions & 1 deletion decode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ var unmarshalTests = []unmarshalTest{
[]interface{}{int16(-1000), int32(-1000), int64(-1000), int(-1000)},
[]reflect.Type{typeUint8, typeUint16, typeUint32, typeUint64, typeInt8, typeFloat32, typeFloat64, typeString, typeBool, typeIntSlice, typeMapStringInt},
},
//{"3bffffffffffffffff", int64(-18446744073709551616)}, // value overflows int64
//{"3bffffffffffffffff", int64(-18446744073709551616)}, // CBOR value -18446744073709551616 overflows Go's int64, see TestNegIntOverflow
// byte string
{
hexDecode("40"),
Expand Down Expand Up @@ -708,6 +708,25 @@ func TestUnmarshalFloat(t *testing.T) {
}
}

func TestNegIntOverflow(t *testing.T) {
testCases := []struct {
cborData []byte
v interface{}
}{
{hexDecode("3bffffffffffffffff"), new(interface{})},
{hexDecode("3bffffffffffffffff"), new(int64)},
}
for _, tc := range testCases {
if err := cbor.Unmarshal(tc.cborData, tc.v); err == nil {
t.Errorf("Unmarshal(0x%0x) returns no error, %v (%T), want (*cbor.UnmarshalTypeError)", tc.cborData, tc.v, tc.v)
} else if _, ok := err.(*cbor.UnmarshalTypeError); !ok {
t.Errorf("Unmarshal(0x%0x) returns wrong error %T, want (*cbor.UnmarshalTypeError)", tc.cborData, err)
} else if !strings.Contains(err.Error(), "cannot unmarshal") {
t.Errorf("Unmarshal(0x%0x) returns error %s, want error containing %q", tc.cborData, err, "cannot unmarshal")
}
}
}

func TestUnmarshalIntoPointer(t *testing.T) {
cborDataNil := []byte{0xf6} // nil
cborDataInt := []byte{0x18, 0x18} // 24
Expand Down

0 comments on commit 47055e7

Please sign in to comment.