Skip to content

Commit 9feb50e

Browse files
authored
BindStringToObject() allows silent overflow of narrower-than-64-bit numeric types (#740)
Closes: #739 Co-authored-by: Daniel Price <dp@coros.net>
1 parent d0d975a commit 9feb50e

2 files changed

Lines changed: 45 additions & 1 deletion

File tree

bindstring.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,20 @@ func BindStringToObject(src string, dst interface{}) error {
6363
var val int64
6464
val, err = strconv.ParseInt(src, 10, 64)
6565
if err == nil {
66-
v.SetInt(val)
66+
if v.OverflowInt(val) {
67+
err = fmt.Errorf("value '%s' overflows destination of type: %s", src, t.Kind())
68+
}
69+
if err == nil {
70+
v.SetInt(val)
71+
}
6772
}
6873
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
6974
var val uint64
7075
val, err = strconv.ParseUint(src, 10, 64)
7176
if err == nil {
77+
if v.OverflowUint(val) {
78+
err = fmt.Errorf("value '%s' overflows destination of type: %s", src, t.Kind())
79+
}
7280
v.SetUint(val)
7381
}
7482
case reflect.String:
@@ -78,6 +86,9 @@ func BindStringToObject(src string, dst interface{}) error {
7886
var val float64
7987
val, err = strconv.ParseFloat(src, 64)
8088
if err == nil {
89+
if v.OverflowFloat(val) {
90+
err = fmt.Errorf("value '%s' overflows destination of type: %s", src, t.Kind())
91+
}
8192
v.SetFloat(val)
8293
}
8394
case reflect.Bool:

bindstring_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
package runtime
1515

1616
import (
17+
"fmt"
18+
"math"
1719
"testing"
1820
"time"
1921

@@ -37,39 +39,56 @@ func TestBindStringToObject(t *testing.T) {
3739
var i8 int8
3840
assert.NoError(t, BindStringToObject("12", &i8))
3941
assert.Equal(t, int8(12), i8)
42+
assert.NoError(t, BindStringToObject("-12", &i8))
43+
assert.Equal(t, int8(-12), i8)
4044

4145
assert.Error(t, BindStringToObject("5.7", &i8))
4246
assert.Error(t, BindStringToObject("foo", &i8))
4347
assert.Error(t, BindStringToObject("1,2,3", &i8))
48+
assert.Error(t, BindStringToObject(fmt.Sprintf("%d", math.MinInt8-1), &i8))
49+
assert.Error(t, BindStringToObject(fmt.Sprintf("%d", math.MaxInt8+1), &i8))
4450

4551
var i16 int16
4652
assert.NoError(t, BindStringToObject("12", &i16))
4753
assert.Equal(t, int16(12), i16)
54+
assert.NoError(t, BindStringToObject("-12", &i16))
55+
assert.Equal(t, int16(-12), i16)
4856

4957
assert.Error(t, BindStringToObject("5.7", &i16))
5058
assert.Error(t, BindStringToObject("foo", &i16))
5159
assert.Error(t, BindStringToObject("1,2,3", &i16))
60+
assert.Error(t, BindStringToObject(fmt.Sprintf("%d", math.MinInt16-1), &i16))
61+
assert.Error(t, BindStringToObject(fmt.Sprintf("%d", math.MaxInt16+1), &i16))
5262

5363
var i32 int32
5464
assert.NoError(t, BindStringToObject("12", &i32))
5565
assert.Equal(t, int32(12), i32)
66+
assert.NoError(t, BindStringToObject("-12", &i32))
67+
assert.Equal(t, int32(-12), i32)
5668

5769
assert.Error(t, BindStringToObject("5.7", &i32))
5870
assert.Error(t, BindStringToObject("foo", &i32))
5971
assert.Error(t, BindStringToObject("1,2,3", &i32))
72+
assert.Error(t, BindStringToObject(fmt.Sprintf("%d", math.MinInt32-1), &i32))
73+
assert.Error(t, BindStringToObject(fmt.Sprintf("%d", math.MaxInt32+1), &i32))
6074

6175
var i64 int64
6276
assert.NoError(t, BindStringToObject("124", &i64))
6377
assert.Equal(t, int64(124), i64)
78+
assert.NoError(t, BindStringToObject("-124", &i64))
79+
assert.Equal(t, int64(-124), i64)
6480

6581
assert.Error(t, BindStringToObject("5.7", &i64))
6682
assert.Error(t, BindStringToObject("foo", &i64))
6783
assert.Error(t, BindStringToObject("1,2,3", &i64))
84+
assert.Error(t, BindStringToObject("-9223372036854775809", &i64))
85+
assert.Error(t, BindStringToObject("9223372036854775808", &i64)) // 1<<63
6886

6987
var u uint
7088
assert.NoError(t, BindStringToObject("5", &u))
7189
assert.Equal(t, uint(5), u)
7290

91+
assert.Error(t, BindStringToObject("-5", &u))
7392
assert.Error(t, BindStringToObject("5.7", &u))
7493
assert.Error(t, BindStringToObject("foo", &u))
7594
assert.Error(t, BindStringToObject("1,2,3", &u))
@@ -78,33 +97,41 @@ func TestBindStringToObject(t *testing.T) {
7897
assert.NoError(t, BindStringToObject("12", &u8))
7998
assert.Equal(t, uint8(12), u8)
8099

100+
assert.Error(t, BindStringToObject("-5", &u8))
81101
assert.Error(t, BindStringToObject("5.7", &u8))
82102
assert.Error(t, BindStringToObject("foo", &u8))
83103
assert.Error(t, BindStringToObject("1,2,3", &u8))
104+
assert.Error(t, BindStringToObject(fmt.Sprintf("%d", math.MaxUint8+1), &i8))
84105

85106
var u16 uint16
86107
assert.NoError(t, BindStringToObject("12", &u16))
87108
assert.Equal(t, uint16(12), u16)
88109

110+
assert.Error(t, BindStringToObject("-5", &u16))
89111
assert.Error(t, BindStringToObject("5.7", &u16))
90112
assert.Error(t, BindStringToObject("foo", &u16))
91113
assert.Error(t, BindStringToObject("1,2,3", &u16))
114+
assert.Error(t, BindStringToObject(fmt.Sprintf("%d", math.MaxUint16+1), &i16))
92115

93116
var u32 uint32
94117
assert.NoError(t, BindStringToObject("12", &u32))
95118
assert.Equal(t, uint32(12), u32)
96119

120+
assert.Error(t, BindStringToObject("-5", &u32))
97121
assert.Error(t, BindStringToObject("5.7", &u32))
98122
assert.Error(t, BindStringToObject("foo", &u32))
99123
assert.Error(t, BindStringToObject("1,2,3", &u32))
124+
assert.Error(t, BindStringToObject(fmt.Sprintf("%d", math.MaxUint32+1), &i32))
100125

101126
var u64 uint64
102127
assert.NoError(t, BindStringToObject("124", &u64))
103128
assert.Equal(t, uint64(124), u64)
104129

130+
assert.Error(t, BindStringToObject("-5", &u64))
105131
assert.Error(t, BindStringToObject("5.7", &u64))
106132
assert.Error(t, BindStringToObject("foo", &u64))
107133
assert.Error(t, BindStringToObject("1,2,3", &u64))
134+
assert.Error(t, BindStringToObject("18446744073709551616", &i64)) // 1<<64
108135

109136
var b bool
110137
assert.NoError(t, BindStringToObject("True", &b))
@@ -113,6 +140,10 @@ func TestBindStringToObject(t *testing.T) {
113140
assert.Equal(t, true, b)
114141
assert.NoError(t, BindStringToObject("1", &b))
115142
assert.Equal(t, true, b)
143+
assert.NoError(t, BindStringToObject("0", &b))
144+
assert.Equal(t, false, b)
145+
assert.Error(t, BindStringToObject("-1", &b))
146+
assert.Error(t, BindStringToObject("hello", &b))
116147

117148
var f64 float64
118149
assert.NoError(t, BindStringToObject("1.25", &f64))
@@ -127,6 +158,8 @@ func TestBindStringToObject(t *testing.T) {
127158

128159
assert.Error(t, BindStringToObject("foo", &f32))
129160
assert.Error(t, BindStringToObject("1,2,3", &f32))
161+
assert.NoError(t, BindStringToObject(fmt.Sprintf("%f", math.MaxFloat32), &f32))
162+
assert.Error(t, BindStringToObject(fmt.Sprintf("%f", math.MaxFloat32*2), &f32))
130163

131164
// This checks whether binding works through a type alias.
132165
type SomeType int

0 commit comments

Comments
 (0)