Merge pull request #33 from mcos/bugfix/uint-handling
Don't decode negative numbers to overflowed uints
diff --git a/mapstructure.go b/mapstructure.go
index 381ba5d..9fceaef 100644
--- a/mapstructure.go
+++ b/mapstructure.go
@@ -51,6 +51,7 @@
// - string to bool (accepts: 1, t, T, TRUE, true, True, 0, f, F,
// FALSE, false, False. Anything else is an error)
// - empty array = empty map and vice versa
+ // - negative numbers to overflowed uint values (base 10)
//
WeaklyTypedInput bool
@@ -319,11 +320,21 @@
switch {
case dataKind == reflect.Int:
- val.SetUint(uint64(dataVal.Int()))
+ i := dataVal.Int()
+ if i < 0 && !d.config.WeaklyTypedInput {
+ return fmt.Errorf("cannot parse '%s', %d overflows uint",
+ name, i)
+ }
+ val.SetUint(uint64(i))
case dataKind == reflect.Uint:
val.SetUint(dataVal.Uint())
case dataKind == reflect.Float32:
- val.SetUint(uint64(dataVal.Float()))
+ f := dataVal.Float()
+ if f < 0 && !d.config.WeaklyTypedInput {
+ return fmt.Errorf("cannot parse '%s', %f overflows uint",
+ name, f)
+ }
+ val.SetUint(uint64(f))
case dataKind == reflect.Bool && d.config.WeaklyTypedInput:
if dataVal.Bool() {
val.SetUint(1)
diff --git a/mapstructure_test.go b/mapstructure_test.go
index 036e6b5..1444b13 100644
--- a/mapstructure_test.go
+++ b/mapstructure_test.go
@@ -658,6 +658,42 @@
if derr.Errors[0] != "'Vstring' expected type 'string', got unconvertible type 'int'" {
t.Errorf("got unexpected error: %s", err)
}
+
+ inputNegIntUint := map[string]interface{}{
+ "vuint": -42,
+ }
+
+ err = Decode(inputNegIntUint, &result)
+ if err == nil {
+ t.Fatal("error should exist")
+ }
+
+ derr, ok = err.(*Error)
+ if !ok {
+ t.Fatalf("error should be kind of Error, instead: %#v", err)
+ }
+
+ if derr.Errors[0] != "cannot parse 'Vuint', -42 overflows uint" {
+ t.Errorf("got unexpected error: %s", err)
+ }
+
+ inputNegFloatUint := map[string]interface{}{
+ "vuint": -42.0,
+ }
+
+ err = Decode(inputNegFloatUint, &result)
+ if err == nil {
+ t.Fatal("error should exist")
+ }
+
+ derr, ok = err.(*Error)
+ if !ok {
+ t.Fatalf("error should be kind of Error, instead: %#v", err)
+ }
+
+ if derr.Errors[0] != "cannot parse 'Vuint', -42.000000 overflows uint" {
+ t.Errorf("got unexpected error: %s", err)
+ }
}
func TestMetadata(t *testing.T) {