Fix GetPreviousOccurrence returning a day in a disallowed month

When the time-of-day search rolls back past the 1st of the month, dayLimit
(and maxDay) can drop below the first valid day of month. The day-of-month
'*' fast path in TryGetPreviousDay returned actualDay = 0, and
DateTimeToTicks(year, month, 0, ...) underflowed into the last day of the
previous month, which is not re-validated against the month field. Guard
against maxDay below the first day of month so the caller advances to the
previous allowed month instead.
This commit is contained in:
dualfroz committed 2026-09-04 09:32:17 +02:00
1 parent 9daaf8b304
commit e055ee7ac6
3 files changed
+160

No files matched your search

+14
View File
@@ -995,6 +995,20 @@ namespace Cronos
var lastDayOfMonth = CalendarHelper.GetDaysInMonth(year, month);
var maxDay = dayLimit > lastDayOfMonth ? lastDayOfMonth : dayLimit;
// When the time-of-day search rolls back past the 1st of the month, dayLimit
// (and therefore maxDay) can drop below the first valid day of month. In that
// case there is no matching day left in this month, so the caller must move to
// the previous month. Without this guard the day-of-month "*" fast path below
// would return actualDay = 0, and DateTimeToTicks(year, month, 0, ...) would
// silently underflow into the last day of the previous month, producing an
// occurrence in a month that is not allowed by the month field.
if (maxDay < CronField.DaysOfMonth.First)
{
day = default;
actualDay = default;
return false;
}
if (HasFlag(CronExpressionFlag.NearestWeekday))
{
day = HasFlag(CronExpressionFlag.DayOfMonthLast)