diff --git a/.golangci.yml b/.golangci.yml index 8a3b3bf..31480c7 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -6,6 +6,8 @@ linters: - depguard - funlen - gomoddirectives + - gomodguard + - gomodguard_v2 - godox - exhaustruct - nlreturn diff --git a/duration.go b/duration.go index f2ab7ff..4725903 100644 --- a/duration.go +++ b/duration.go @@ -174,6 +174,9 @@ func ParseDuration(s string) (time.Duration, error) { scale float64 = 1 // value = v + f/scale ) s = strings.TrimLeftFunc(s, unicode.IsSpace) + if s == "" { + break + } // The next character must be 0-9.] if s[0] != '.' && ('0' > s[0] || s[0] > '9') { diff --git a/duration_test.go b/duration_test.go index 5052ee9..ae4f206 100644 --- a/duration_test.go +++ b/duration_test.go @@ -5,6 +5,9 @@ package strfmt import ( "fmt" + "iter" + "slices" + "strings" "testing" "time" @@ -395,6 +398,14 @@ func TestIssue169FractionalDuration(t *testing.T) { Input: "314159. d", ExpectError: true, }, + { + Input: " ", + ExpectError: true, + }, + { + Input: " 1s ", + Expected: "1s", + }, } { fractionalDuration := tt @@ -424,3 +435,30 @@ func TestIssue169FractionalDuration(t *testing.T) { }) } } + +func FuzzParseDuration(f *testing.F) { + // initial seed + cumulated := make([]string, 0, 100) + for generator := range durationGenerators() { + f.Add(generator) + + cumulated = append(cumulated, generator) + f.Add(strings.Join(cumulated, "")) + } + + f.Fuzz(func(t *testing.T, input string) { + require.NotPanics(t, func() { + _ = IsDuration(input) + }) + }) +} + +func durationGenerators() iter.Seq[string] { + return slices.Values([]string{ + "x", + "", + "1s", + " ", + " 1s ", + }) +}