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) {