Skip to content

Commit 59d62f5

Browse files
authored
Merge pull request #753 from fxamacker/fxamacker/small-bugfixes
Small bugfixes, defensive checks, and improvements
2 parents 46bc977 + cfc9720 commit 59d62f5

8 files changed

Lines changed: 34 additions & 7 deletions

File tree

cache.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ func (x *bytewiseFieldSorter) Swap(i, j int) {
175175
}
176176

177177
func (x *bytewiseFieldSorter) Less(i, j int) bool {
178-
return bytes.Compare(x.fields[i].cborName, x.fields[j].cborName) <= 0
178+
return bytes.Compare(x.fields[i].cborName, x.fields[j].cborName) < 0
179179
}
180180

181181
type lengthFirstFieldSorter struct {
@@ -194,7 +194,7 @@ func (x *lengthFirstFieldSorter) Less(i, j int) bool {
194194
if len(x.fields[i].cborName) != len(x.fields[j].cborName) {
195195
return len(x.fields[i].cborName) < len(x.fields[j].cborName)
196196
}
197-
return bytes.Compare(x.fields[i].cborName, x.fields[j].cborName) <= 0
197+
return bytes.Compare(x.fields[i].cborName, x.fields[j].cborName) < 0
198198
}
199199

200200
func getEncodingStructType(t reflect.Type) (*encodingStructType, error) {

decode.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1832,6 +1832,13 @@ func (d *decoder) parseToTime() (time.Time, bool, error) {
18321832
return time.Time{}, true, nil
18331833
}
18341834
seconds, fractional := math.Modf(f)
1835+
if seconds > math.MaxInt64 || seconds < math.MinInt64 {
1836+
return time.Time{}, false, &UnmarshalTypeError{
1837+
CBORType: t.String(),
1838+
GoType: typeTime.String(),
1839+
errorMsg: fmt.Sprintf("%v overflows Go's int64", f),
1840+
}
1841+
}
18351842
return time.Unix(int64(seconds), int64(fractional*1e9)), true, nil
18361843

18371844
default:

decode_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4376,6 +4376,18 @@ func TestDecodeInvalidTagTime(t *testing.T) {
43764376
decodeToTypes: []reflect.Type{typeIntf, typeTime},
43774377
wantErrorMsg: "cbor: cannot unmarshal negative integer into Go value of type time.Time (-18446744073709551616 overflows Go's int64)",
43784378
},
4379+
{
4380+
name: "tag 1 with positive float64 overflow",
4381+
data: mustHexDecode("c1fb4415af1d78b58c40"), // 1(1e+20)
4382+
decodeToTypes: []reflect.Type{typeIntf, typeTime},
4383+
wantErrorMsg: "overflows Go's int64",
4384+
},
4385+
{
4386+
name: "tag 1 with negative float64 overflow",
4387+
data: mustHexDecode("c1fbc415af1d78b58c40"), // 1(-1e+20)
4388+
decodeToTypes: []reflect.Type{typeIntf, typeTime},
4389+
wantErrorMsg: "overflows Go's int64",
4390+
},
43794391
{
43804392
name: "tag 1 with string content",
43814393
data: mustHexDecode("c174323031332d30332d32315432303a30343a30305a"),

diagnose.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -605,7 +605,7 @@ func (di *diagnose) encodeTextString(val string, quote byte) error {
605605

606606
c, size := utf8.DecodeRuneInString(val[i:])
607607
switch {
608-
case c == utf8.RuneError:
608+
case c == utf8.RuneError && size == 1:
609609
return &SemanticError{"cbor: invalid UTF-8 string"}
610610

611611
case c < utf16SurrSelf:

diagnose_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,12 @@ func TestDiagnoseTextString(t *testing.T) {
607607
ByteStringText: true,
608608
},
609609
},
610+
{
611+
name: "valid U+FFFD replacement character in text string",
612+
data: mustHexDecode("63efbfbd"),
613+
wantDiag: `"\ufffd"`,
614+
opts: &DiagOptions{},
615+
},
610616
{
611617
name: "indefinite-length text string with no chunks",
612618
data: mustHexDecode("7fff"),

encode.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1431,7 +1431,7 @@ func (x *bytewiseKeyValueSorter) Swap(i, j int) {
14311431

14321432
func (x *bytewiseKeyValueSorter) Less(i, j int) bool {
14331433
kvi, kvj := x.kvs[i], x.kvs[j]
1434-
return bytes.Compare(x.data[kvi.offset:kvi.valueOffset], x.data[kvj.offset:kvj.valueOffset]) <= 0
1434+
return bytes.Compare(x.data[kvi.offset:kvi.valueOffset], x.data[kvj.offset:kvj.valueOffset]) < 0
14351435
}
14361436

14371437
type lengthFirstKeyValueSorter struct {
@@ -1452,7 +1452,7 @@ func (x *lengthFirstKeyValueSorter) Less(i, j int) bool {
14521452
if keyLengthDifference := (kvi.valueOffset - kvi.offset) - (kvj.valueOffset - kvj.offset); keyLengthDifference != 0 {
14531453
return keyLengthDifference < 0
14541454
}
1455-
return bytes.Compare(x.data[kvi.offset:kvi.valueOffset], x.data[kvj.offset:kvj.valueOffset]) <= 0
1455+
return bytes.Compare(x.data[kvi.offset:kvi.valueOffset], x.data[kvj.offset:kvj.valueOffset]) < 0
14561456
}
14571457

14581458
var keyValuePool = sync.Pool{}

stream.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,9 @@ type RawMessage []byte
272272
// MarshalCBOR returns m or CBOR nil if m is nil.
273273
func (m RawMessage) MarshalCBOR() ([]byte, error) {
274274
if len(m) == 0 {
275-
return cborNil, nil
275+
b := make([]byte, len(cborNil))
276+
copy(b, cborNil)
277+
return b, nil
276278
}
277279
return m, nil
278280
}

structfields.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ func (x *indexFieldSorter) Less(i, j int) bool {
4848
return iIdx[k] < jIdx[k]
4949
}
5050
}
51-
return len(iIdx) <= len(jIdx)
51+
return len(iIdx) < len(jIdx)
5252
}
5353

5454
// nameLevelAndTagFieldSorter sorts fields by field name, idx depth, and presence of tag.

0 commit comments

Comments
 (0)