fs: reject NaN durations instead of wrapping

strconv.ParseFloat accepts "NaN", and NaN compares false with every
bound, so it got past the overflow check added for 300y and was then
converted to a time.Duration, which gives the minimum int64 on amd64.
--max-age NaN or --min-age NaNM silently became about -292 years,
which moves the filter's ModTimeFrom into the future and excludes every
file, instead of being rejected.
This commit is contained in:
Soujas K authored and Nick Craig-Wood committed 2026-10-31 15:18:08 +00:00
1 parent 0a0661ade0
commit a89766467e
2 files changed
+6

No files matched your search

+3
View File
@@ -61,6 +61,9 @@ func parseDurationSuffixes(age string) (time.Duration, error) {
if err != nil {
return time.Duration(0), err
}
if math.IsNaN(period) {
return time.Duration(0), fmt.Errorf("duration %q is not a number", age)
}
period *= float64(ageSuffix.Multiplier)
if math.Abs(period) >= math.MaxInt64 {
return time.Duration(0), fmt.Errorf("duration %q is too long", age)
+3
View File
@@ -58,6 +58,9 @@ func TestParseDuration(t *testing.T) {
{"300y", 0, true},
{"-300y", 0, true},
{"1e10d", 0, true},
{"NaN", 0, true},
{"NaNd", 0, true},
{"-NaNM", 0, true},
{"2001-02-03", now.Sub(time.Date(2001, 2, 3, 0, 0, 0, 0, time.Local)), false},
{"2001-02-03 10:11:12", now.Sub(time.Date(2001, 2, 3, 10, 11, 12, 0, time.Local)), false},
{"2001-08-03 10:11:12", now.Sub(time.Date(2001, 8, 3, 10, 11, 12, 0, time.Local)), false},