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: