DF-2957 / fix.diff
--- a/sys/kern/subr_fattime.c 2026-06-29 12:51:19.000000000 +0000 +++ b/sys/kern/subr_fattime.c 2026-10-26 00:25:42.813042622 +0000 @@ -222,21 +222,39 @@ { unsigned day; - /* Unpack time fields */ - tsp->tv_sec = (dt & 0x1f) << 1; - tsp->tv_sec += ((dt & 0x7e0) >> 5) * 60; - tsp->tv_sec += ((dt & 0xf800) >> 11) * 3600; - tsp->tv_sec += dh / 100; - tsp->tv_nsec = (dh % 100) * 10000000; + /* Unpack time fields (clamped: on-disk values may be out of range) */ + { + unsigned ss = (dt & 0x1f) << 1; + unsigned mm = (dt & 0x7e0) >> 5; + unsigned hh = (dt & 0xf800) >> 11; + unsigned idx = (dd >> 5) & 0x3f; + unsigned mon = idx & 0x0f; - /* Day of month */ - day = (dd & 0x1f) - 1; + if (ss > 59) + ss = 59; + if (mm > 59) + mm = 59; + if (hh > 23) + hh = 23; + if (mon < 1) + mon = 1; + if (mon > 12) + mon = 12; + tsp->tv_sec = ss; + tsp->tv_sec += mm * 60; + tsp->tv_sec += hh * 3600; + tsp->tv_sec += dh / 100; + tsp->tv_nsec = (dh % 100) * 10000000; - /* Full leap-year cycles */ - day += LYC * ((dd >> 11) & 0x1f); + /* Day of month */ + day = (dd & 0x1f) - 1; - /* Month offset from leap-year cycle */ - day += daytab[(dd >> 5) & 0x3f]; + /* Full leap-year cycles */ + day += LYC * ((dd >> 11) & 0x1f); + + /* Month offset from leap-year cycle */ + day += daytab[(idx & 0x30) | mon]; + } /* * 2100 is not a leap year. |