[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#266438: zdump -v causes core dump on IA64 Linux



Package: libc6.1
Version: 2.2.5-11.2

$ zdump -v est
Segmentation fault

The zdump -v command will core dump with a SIGSEGV. The problem has also been reproduced with RH AW 2.1, RH AS 2.1, and RH AW 3.0.

The problem could NOT be reproduced on any IA32 platform.

To reproduce:

/usr/bin/zdump -v random-string # Debian IA64 Linux
/usr/sbin/zdump -v random-string # Red Hat IA64

The random-string can be any value.

An ia32 platform displays this:

$ zdump -v est
est Fri Dec 13 20:45:52 1901 UTC = Fri Dec 13 20:45:52 1901 est isdst=0 gmtoff=0 est Sat Dec 14 20:45:52 1901 UTC = Sat Dec 14 20:45:52 1901 est isdst=0 gmtoff=0 est Mon Jan 18 03:14:07 2038 UTC = Mon Jan 18 03:14:07 2038 est isdst=0 gmtoff=0 est Tue Jan 19 03:14:07 2038 UTC = Tue Jan 19 03:14:07 2038 est isdst=0 gmtoff=0

Attached is a patch which barely "papers over" the problem. It should not be interpreted as a fix.

--
Darrin

--- glibc-2.2.5-prepatch/timezone/zdump.c	Tue Mar 20 11:47:32 2001
+++ glibc-2.2.5/timezone/zdump.c	Fri Jul  2 14:17:16 2004
@@ -152,6 +152,7 @@
 	time_t			hibit;
 	struct tm		tm;
 	struct tm		newtm;
+        struct tm		*tm_p;
 
 	INITIALIZE(cuttime);
 #if HAVE_GETTEXT - 0
@@ -176,6 +177,33 @@
 				argv[0], argv[0]);
 			(void) exit(EXIT_FAILURE);
 	}
+	(void) time(&now);
+	longest = 0;
+	for (i = optind; i < argc; ++i)
+		if (strlen(argv[i]) > longest)
+			longest = strlen(argv[i]);
+	for (hibit = 1; (hibit << 1) != 0; hibit <<= 1)
+		continue;
+        /* 
+        ** If time_t is 64-bit and int is 32-bit, the maximally negative
+        ** time_t will overflow struct tm.  So, check for that, and reduce
+        ** hibit to the maximal value struct tm can handle. 
+        */
+        tm_p = gmtime(&hibit);
+        if (tm_p == NULL) {
+            for (i = 1; (i << 1) != 0; i <<= 1)
+                continue;
+            hibit = (time_t)i * DAYSPERNYEAR;
+            tm_p = gmtime(&hibit);
+            while (tm_p == NULL) {
+                hibit++;
+                tm_p = gmtime(&hibit);
+            }
+
+            /* Also set a cutoff year if none is set. */
+            if (cutoff == NULL)
+                cutoff = "2037";
+        }
 	if (cutoff != NULL) {
 		int	y;
 
@@ -185,13 +213,7 @@
 			cuttime += DAYSPERNYEAR + isleap(y);
 		cuttime *= SECSPERHOUR * HOURSPERDAY;
 	}
-	(void) time(&now);
-	longest = 0;
-	for (i = optind; i < argc; ++i)
-		if (strlen(argv[i]) > longest)
-			longest = strlen(argv[i]);
-	for (hibit = 1; (hibit << 1) != 0; hibit <<= 1)
-		continue;
+
 	{
 		register int	from;
 		register int	to;

Reply to: