Repository navigation
sudoers: fix leap year calculation in getdate() - #595
Merged
Merged
Conversation
get_date() counts the days between EPOCH and the requested year with Julian += 365 + (i % 4 == 0); which treats every year divisible by 4 as a leap year. Century years that are not divisible by 400 (2100, 2200, 2300, ...) are therefore counted with an extra day. Any date in a later year is then computed too large by one day for every such year that has passed, e.g. "Jan 1, 2101" is returned as Jan 2, and "Jan 1, 2300" is off by two days. Use the full Gregorian rule, as is already done for DaysInMonth[1]. The generated getdate.c contains a copy of the same function, so update it as well. Fixes: sudo-project#446 Signed-off-by: mahailiang <[email protected]>
millert
approved these changes
Nov 12, 2026
millert
left a comment
Collaborator
There was a problem hiding this comment.
Looks correct. I guess this counts as "future-proofing".
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.
Summary
get_date()(inplugins/sudoers/getdate.y) counts the days betweenEPOCH and the requested year with:
Every year divisible by 4 is treated as a leap year. Century years not
divisible by 400 (2100, 2200, 2300, ...) are counted with one extra day,
so dates in later years are computed too large by one day per such year
that has passed. For example:
The
DaysInMonth[1]calculation a few lines above already uses the fullGregorian rule; the day-count loop was missed.
Fix
Use the same rule for the year loop:
getdate.cis a generated file but is checked in, and it carries a copyof
Convert(), so both files are updated identically.This function is used by
sudoreplayto parsefromdate/todate.Testing
Built
sudofrom this branch in a mock UOS 25 x86_64 chroot withgcc 12.3.1 (
configure --disable-nls --disable-python && make -j),with no new warnings.
For a behavior test, a small harness was linked against the generated
getdate.oand the old implementation (the singlei % 4 == 0expression) was compiled side by side. Results with
TZ=UTC, comparedwith GNU
date -u:The old values are exactly one day (86400 s) too large per non-leap
century year; the patched values match GNU date. Note that 2100 itself
is still correct in the old code because the loop only counts years
before the requested one; the error starts with 2101, when 2100 is
included in the sum.
Fixes #446