diff --git a/cmd/kurl/main.go b/cmd/kurl/main.go index 0b56c49..9da738a 100644 --- a/cmd/kurl/main.go +++ b/cmd/kurl/main.go @@ -5,6 +5,7 @@ import ( "context" "encoding/json" "fmt" + "math" "os" "strconv" "strings" @@ -498,6 +499,9 @@ func parseTimeout(value string) (time.Duration, error) { } if seconds, err := strconv.ParseFloat(value, 64); err == nil { + if math.IsNaN(seconds) || math.IsInf(seconds, 0) || seconds*float64(time.Second) >= float64(math.MaxInt64) { + return 0, fmt.Errorf("invalid timeout %q: must be finite and fit in a duration", value) + } if seconds < 0 { return 0, fmt.Errorf("invalid timeout %q: must not be negative", value) } diff --git a/cmd/kurl/timeout_range_test.go b/cmd/kurl/timeout_range_test.go new file mode 100644 index 0000000..f5fcadd --- /dev/null +++ b/cmd/kurl/timeout_range_test.go @@ -0,0 +1,21 @@ +package main + +import ( + "testing" + "time" +) + +func TestTimeoutRejectsNonFiniteAndOverflowSeconds(t *testing.T) { + for _, value := range []string{"NaN", "Inf", "+Inf", "-Inf", "1e100", "9223372037", "9223372036.854776"} { + t.Run(value, func(t *testing.T) { + if got, err := parseTimeout(value); err == nil { + t.Fatalf("parseTimeout(%q) = %s without error", value, got) + } + }) + } + for value, want := range map[string]time.Duration{"0": 0, "0.5": 500 * time.Millisecond, "30": 30 * time.Second, "9223372036": 9223372036 * time.Second, "500ms": 500 * time.Millisecond} { + if got, err := parseTimeout(value); err != nil || got != want { + t.Errorf("parseTimeout(%q) = %s, %v; want %s", value, got, err, want) + } + } +}