kern/97786: fs/udf: incorrect timestamps
Andriy Gapon
avg at topspin.kiev.ua
Wed May 24 12:20:24 UTC 2006
>Number: 97786
>Category: kern
>Synopsis: fs/udf: incorrect timestamps
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Wed May 24 12:20:20 GMT 2006
>Closed-Date:
>Last-Modified:
>Originator: Andriy Gapon
>Release: FreeBSD 6.1-RELEASE i386
>Organization:
>Environment:
System: FreeBSD 6.1-RELEASE i386
>Description:
Thanks to Bruce Evans for discovering this bug and sharing his patch.
To the best of my knowledge this was not filed as a PR before, so I am
doing it now to share the knowledge with community.
Badically, existing code doesn't take into account that day- and month-
numbering starts with 1, not zero. Month number is not validated.
Also, for timestamps before 2000 it can report only three values
(Jan 1 1980, Jan 1 1990, Jan 1 2000), becaus of a bug in "fast-forwarding"
optimization.
>How-To-Repeat:
>Fix:
--- datetime.patch begins here ---
--- sys/fs/udf/udf_vnops.c 23 Jun 2004 21:49:03 -0000 1.37
+++ sys/fs/udf/udf_vnops.c 19 Apr 2005 06:42:17 -0000
@@ -265,7 +268,11 @@
t->tv_nsec = 0;
- /* DirectCD seems to like using bogus year values */
+ /*
+ * DirectCD seems to like using bogus year values.
+ * Distrust time->month especially, since it will be used for an
+ * array index.
+ */
year = le16toh(time->year);
- if (year < 1970) {
+ if (year < 1970 || time->month > 12) {
t->tv_sec = 0;
return;
@@ -276,19 +283,12 @@
t->tv_sec += time->minute * 60;
t->tv_sec += time->hour * 3600;
- t->tv_sec += time->day * 3600 * 24;
+ t->tv_sec += (time->day - 1) * 3600 * 24;
/* Calculate the month */
lpyear = udf_isaleapyear(year);
for (i = 1; i < time->month; i++)
- t->tv_sec += mon_lens[lpyear][i] * 3600 * 24;
+ t->tv_sec += mon_lens[lpyear][i - 1] * 3600 * 24;
- /* Speed up the calculation */
- if (year > 1979)
- t->tv_sec += 315532800;
- if (year > 1989)
- t->tv_sec += 315619200;
- if (year > 1999)
- t->tv_sec += 315532800;
- for (i = 2000; i < year; i++) {
+ for (i = 1970; i < year; i++) {
daysinyear = udf_isaleapyear(i) + 365 ;
t->tv_sec += daysinyear * 3600 * 24;
--- datetime.patch ends here ---
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list