diff --git a/pkg/validation/strfmt/duration.go b/pkg/validation/strfmt/duration.go index 04545296b..f555abe1a 100644 --- a/pkg/validation/strfmt/duration.go +++ b/pkg/validation/strfmt/duration.go @@ -52,7 +52,8 @@ var ( "w": 7 * 24 * time.Hour, } - durationMatcher = regexp.MustCompile(`((\d+)\s*([A-Za-zµ]+))`) + durationValidator = regexp.MustCompile(`^\s*(?:\d+\s*[A-Za-zµ]+\s*)+$`) + durationMatcher = regexp.MustCompile(`((\d+)\s*([A-Za-zµ]+))`) ) // IsDuration returns true if the provided string is a valid duration @@ -90,6 +91,10 @@ func ParseDuration(cand string) (time.Duration, error) { return dur, nil } + if !durationValidator.MatchString(cand) { + return 0, fmt.Errorf("unable to parse %s as duration", cand) + } + var dur time.Duration ok := false for _, match := range durationMatcher.FindAllStringSubmatch(cand, -1) { diff --git a/pkg/validation/strfmt/duration_test.go b/pkg/validation/strfmt/duration_test.go index eeb4ff35d..ad9a80bb7 100644 --- a/pkg/validation/strfmt/duration_test.go +++ b/pkg/validation/strfmt/duration_test.go @@ -80,6 +80,24 @@ func TestIsDuration_Failed(t *testing.T) { assert.False(t, e) } +func TestDurationInvalidToken(t *testing.T) { + badDurations := []string{ + "1s invalid", + "invalid 1s", + "1s invalid", + "invalid 1s", + "1s 2m invalid", + "1s invalid 2m", + } + for _, d := range badDurations { + t.Run(d, func(t *testing.T) { + assert.False(t, IsDuration(d), "Expected IsDuration(%q) to be false", d) + _, err := ParseDuration(d) + assert.Error(t, err, "Expected ParseDuration(%q) to return an error", d) + }) + } +} + func TestDurationParser(t *testing.T) { testcases := map[string]time.Duration{ @@ -138,6 +156,14 @@ func TestDurationParser(t *testing.T) { "1 hour": 1 * time.Hour, "1 day": 24 * time.Hour, "1 week": 7 * 24 * time.Hour, + + // parse composite durations, without spaces + "1w2s": 7*24*time.Hour + 2*time.Second, + "1d2h3m5s": 24*time.Hour + 2*time.Hour + 3*time.Minute + 5*time.Second, + + // parse composite durations, with spaces + "1s 2m": 2*time.Minute + 1*time.Second, + "1w 2d 3h 4m": 7*24*time.Hour + 2*24*time.Hour + 3*time.Hour + 4*time.Minute, } for str, dur := range testcases {