Fix infinite loop in nextDate() for impossible day-of-month/month combinations - #38
Open
mrvonkalus wants to merge 1 commit into
Open
Fix infinite loop in nextDate() for impossible day-of-month/month combinations#38mrvonkalus wants to merge 1 commit into
mrvonkalus wants to merge 1 commit into
Conversation
…binations For an unbounded (*) year field, CronosYearsField.nextYear() pushed fromYear unconditionally, with no maxValidYear ceiling (the range/step branch already applies it). When no allowed month can contain any allowed day-of-month (e.g. "0 0 31 4 *" = April 31), _nextMonth() returns null for every year, so _nextYear()'s only exit is never taken and the year counter increments without bound: nextDate() pins a CPU core and never returns. Bound the any-branch by maxValidYear, matching the range/step branch, so the search terminates (scan to year 275759, then null). Adds regression tests: impossible combinations return null quickly; valid controls (May 31, leap-year Feb 29) still resolve. Co-authored-by: Cursor <cursoragent@cursor.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #37.
What
nextDate()never returns for expressions where no allowed month can contain any allowed day-of-month (0 0 31 4 *= April 31,0 0 30 2 *= February 30, etc.) when the year field is unbounded — the default for every standard 5-field expression. Full analysis and reproduction in #37.Root cause
CronosYearsField.nextYear()pushedfromYearunconditionally for*(any) year fields, with nomaxValidYearceiling — the range/step branch right below already applies it. On an impossible date,_nextYear()'s only exit (nextYear() === null) is therefore never taken, and the year counter increments without bound (observed past year 42,000,000 under instrumentation).Fix
One line: bound the
anybranch by the samemaxValidYearceiling the range/step branch already uses.The search now terminates after the bounded scan (to year 275759) and returns
null.Tests
Five regression tests in
tests/api.test.ts("Impossible day-of-month/month combinations"):0 0 31 4 *,0 0 30 2 *,0 0 31 2,4,6 *→null(each completes in ~0.3–1.1s; without the fix they never complete, so these fail by timeout on unfixed code)0 0 31 4,5 *→ 2029-05-31,0 0 29 2 *→ 2032-02-29 (leap year)Verification
tests/api.test.ts: 18/18 pass, including the 5 new testsmaster(timezone/DST environment-dependent tests intimezone.test.ts; pre-existing, untouched by this change)Disclosure
Found by differential fuzzing against a brute-force reference oracle; analysis, fix and verification produced by AI agents working under my direction, reviewed and run by me before filing. Details in #37.
Made with Cursor