@@ -7,9 +7,10 @@ import (
77)
88
99type ParseIntTest struct {
10- in string
11- out int64
12- isErr bool
10+ in string
11+ out int64
12+ isErr bool
13+ isOverflow bool
1314}
1415
1516var parseIntTests = []ParseIntTest {
@@ -34,18 +35,37 @@ var parseIntTests = []ParseIntTest{
3435 out : - 12345 ,
3536 },
3637 {
37- in : "9223372036854775807" ,
38+ in : "9223372036854775807" , // = math.MaxInt64
3839 out : 9223372036854775807 ,
3940 },
4041 {
41- in : "-9223372036854775808" ,
42+ in : "-9223372036854775808" , // = math.MinInt64
4243 out : - 9223372036854775808 ,
4344 },
4445 {
45- in : "18446744073709551616" , // = 2^64; integer overflow is not detected
46- out : 0 ,
46+ in : "-92233720368547758081" ,
47+ out : 0 ,
48+ isErr : true ,
49+ isOverflow : true ,
50+ },
51+ {
52+ in : "18446744073709551616" , // = 2^64
53+ out : 0 ,
54+ isErr : true ,
55+ isOverflow : true ,
56+ },
57+ {
58+ in : "9223372036854775808" , // = math.MaxInt64 - 1
59+ out : 0 ,
60+ isErr : true ,
61+ isOverflow : true ,
62+ },
63+ {
64+ in : "-9223372036854775809" , // = math.MaxInt64 - 1
65+ out : 0 ,
66+ isErr : true ,
67+ isOverflow : true ,
4768 },
48-
4969 {
5070 in : "" ,
5171 isErr : true ,
@@ -70,7 +90,10 @@ var parseIntTests = []ParseIntTest{
7090
7191func TestBytesParseInt (t * testing.T ) {
7292 for _ , test := range parseIntTests {
73- out , ok := parseInt ([]byte (test .in ))
93+ out , ok , overflow := parseInt ([]byte (test .in ))
94+ if overflow != test .isOverflow {
95+ t .Errorf ("Test '%s' error return did not overflow expectation (obtained %t, expected %t)" , test .in , overflow , test .isOverflow )
96+ }
7497 if ok != ! test .isErr {
7598 t .Errorf ("Test '%s' error return did not match expectation (obtained %t, expected %t)" , test .in , ! ok , test .isErr )
7699 } else if ok && out != test .out {
@@ -93,3 +116,37 @@ func BenchmarkParseIntUnsafeSlower(b *testing.B) {
93116 strconv .ParseInt (* (* string )(unsafe .Pointer (& bytes )), 10 , 64 )
94117 }
95118}
119+
120+ // Old implementation that did not check for overflows.
121+ func BenchmarkParseIntOverflows (b * testing.B ) {
122+ bytes := []byte ("123" )
123+ for i := 0 ; i < b .N ; i ++ {
124+ parseIntOverflows (bytes )
125+ }
126+ }
127+
128+ func parseIntOverflows (bytes []byte ) (v int64 , ok bool ) {
129+ if len (bytes ) == 0 {
130+ return 0 , false
131+ }
132+
133+ var neg bool = false
134+ if bytes [0 ] == '-' {
135+ neg = true
136+ bytes = bytes [1 :]
137+ }
138+
139+ for _ , c := range bytes {
140+ if c >= '0' && c <= '9' {
141+ v = (10 * v ) + int64 (c - '0' )
142+ } else {
143+ return 0 , false
144+ }
145+ }
146+
147+ if neg {
148+ return - v , true
149+ } else {
150+ return v , true
151+ }
152+ }
0 commit comments