Skip to content

Commit 608d8c5

Browse files
author
Carson Ip
committed
Fix parseInt overflow check false negative
1 parent 09bcf22 commit 608d8c5

File tree

2 files changed

+30
-18
lines changed

2 files changed

+30
-18
lines changed

bytes.go

+18-18
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
package jsonparser
22

3-
import (
4-
bio "bytes"
5-
)
6-
7-
// minInt64 '-9223372036854775808' is the smallest representable number in int64
8-
const minInt64 = `9223372036854775808`
3+
const absMinInt64 = 1 << 63
4+
const maxInt64 = 1<<63 - 1
5+
const maxUint64 = 1<<64 - 1
96

107
// About 2x faster then strconv.ParseInt because it only supports base 10, which is enough for JSON
118
func parseInt(bytes []byte) (v int64, ok bool, overflow bool) {
@@ -19,29 +16,32 @@ func parseInt(bytes []byte) (v int64, ok bool, overflow bool) {
1916
bytes = bytes[1:]
2017
}
2118

22-
var b int64 = 0
19+
var n uint64 = 0
2320
for _, c := range bytes {
24-
if c >= '0' && c <= '9' {
25-
b = (10 * v) + int64(c-'0')
26-
} else {
21+
if c < '0' || c > '9' {
2722
return 0, false, false
2823
}
29-
if overflow = (b < v); overflow {
30-
break
24+
if n > maxUint64/10 {
25+
return 0, false, true
26+
}
27+
n *= 10
28+
n1 := n + uint64(c-'0')
29+
if n1 < n {
30+
return 0, false, true
3131
}
32-
v = b
32+
n = n1
3333
}
3434

35-
if overflow {
36-
if neg && bio.Equal(bytes, []byte(minInt64)) {
37-
return b, true, false
35+
if n > maxInt64 {
36+
if neg && n == absMinInt64 {
37+
return -absMinInt64, true, false
3838
}
3939
return 0, false, true
4040
}
4141

4242
if neg {
43-
return -v, true, false
43+
return -int64(n), true, false
4444
} else {
45-
return v, true, false
45+
return int64(n), true, false
4646
}
4747
}

bytes_test.go

+12
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,18 @@ var parseIntTests = []ParseIntTest{
8686
in: "9223372036854775807x",
8787
isErr: true,
8888
},
89+
{
90+
in: "27670116110564327410",
91+
out: 0,
92+
isErr: true,
93+
isOverflow: true,
94+
},
95+
{
96+
in: "-27670116110564327410",
97+
out: 0,
98+
isErr: true,
99+
isOverflow: true,
100+
},
89101
}
90102

91103
func TestBytesParseInt(t *testing.T) {

0 commit comments

Comments
 (0)