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