You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Date.valid_commercial? accepts out-of-range week numbers, and Date.commercial then returns a wrong date #180
This is not a single unlucky value: sweeping w over a +-500 window around that value, 52 of the 1001 candidates are accepted.
Cause: c_valid_commercial_p (ext/date/date_core.c) computes rjd2 + w * 7 in int arithmetic with w taken straight from the caller, so w * 7 wraps. That alone would be harmless, because the function ends with a round-trip check. The problem is that the negative branch replaces the caller's value before that check runs:
if (w<0) {
intrjd2;
c_commercial_to_jd(y+1, 1, 1, sg, &rjd2, &ns2);
c_jd_to_commercial(rjd2+w*7, sg, &ry2, &rw2, &rd2); /* w * 7 wraps */if (ry2!=y)
return0;
w=rw2; /* caller value discarded */
}
c_commercial_to_jd(y, w, d, sg, rjd, ns);
c_jd_to_commercial(*rjd, sg, &ry2, rw, rd);
if (y!=ry2||w!=*rw||d!=*rd) /* compares the replaced w */return0;
return1;
So the final guard compares the normalised week against itself and passes. Because 7 is invertible modulo 2**32, values that land back inside year y can be constructed rather than found by chance.
Two independent things would each stop it: rejecting w whose magnitude cannot be meaningful (a year has at most 53 weeks) before the multiplication, and keeping the caller's w for the final comparison instead of overwriting it.
The same overflow reaches c_gregorian_civil_to_jd; note that ns_jd_in_range() guards only the jd -> civil direction, not this one.
Tested: ruby 3.4.5 / date 3.5.1, and ruby 4.1.0dev (master) / date 3.5.1. Same result on both. Ordinal and civil dates were checked too and are not affected: those functions compare against the caller's original value, and a 200k random sweep over the full int range accepted none.
Filing publicly as a correctness bug. The effect is a wrong return value from a validity predicate; there is no memory-safety impact.
Activity
Validate the commercial week range before conversion
[ruby/date] Validate the commercial week range before conversion