Browse Source

Do not accept plain ints into time.Duration.

It used to work in v2, but that's very error prone as it's easy to say,
for example, 10 meaning 10 seconds, but it's really 10 nanoseconds.

Closes #200.
Gustavo Niemeyer 7 years ago
parent
commit
9e322716c2
2 changed files with 14 additions and 4 deletions
  1. 7 4
      decode.go
  2. 7 0
      decode_test.go

+ 7 - 4
decode.go

@@ -555,24 +555,27 @@ func (d *decoder) scalar(n *Node, out reflect.Value) bool {
 		}
 		}
 		return true
 		return true
 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		// This used to work in v2, but it's very unfriendly.
+		isDuration := out.Type() == durationType
+
 		switch resolved := resolved.(type) {
 		switch resolved := resolved.(type) {
 		case int:
 		case int:
-			if !out.OverflowInt(int64(resolved)) {
+			if !isDuration && !out.OverflowInt(int64(resolved)) {
 				out.SetInt(int64(resolved))
 				out.SetInt(int64(resolved))
 				return true
 				return true
 			}
 			}
 		case int64:
 		case int64:
-			if !out.OverflowInt(resolved) {
+			if !isDuration && !out.OverflowInt(resolved) {
 				out.SetInt(resolved)
 				out.SetInt(resolved)
 				return true
 				return true
 			}
 			}
 		case uint64:
 		case uint64:
-			if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
+			if !isDuration && resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
 				out.SetInt(int64(resolved))
 				out.SetInt(int64(resolved))
 				return true
 				return true
 			}
 			}
 		case float64:
 		case float64:
-			if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
+			if !isDuration && resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
 				out.SetInt(int64(resolved))
 				out.SetInt(int64(resolved))
 				return true
 				return true
 			}
 			}

+ 7 - 0
decode_test.go

@@ -809,6 +809,13 @@ func (s *S) TestUnmarshalNaN(c *C) {
 	c.Assert(math.IsNaN(value["notanum"].(float64)), Equals, true)
 	c.Assert(math.IsNaN(value["notanum"].(float64)), Equals, true)
 }
 }
 
 
+func (s *S) TestUnmarshalDurationInt(c *C) {
+	// Don't accept plain ints as durations as it's unclear (issue #200).
+	var d time.Duration
+	err := yaml.Unmarshal([]byte("123"), &d)
+	c.Assert(err, ErrorMatches, "(?s).* line 1: cannot unmarshal !!int `123` into time.Duration")
+}
+
 var unmarshalErrorTests = []struct {
 var unmarshalErrorTests = []struct {
 	data, error string
 	data, error string
 }{
 }{