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

    From Darrin Thompson@1:229/2 to All on Tue Aug 17 23:40:10 2004
    XPost: linux.debian.maint.glibc
    From: [email protected]

    This is a multi-part message in MIME format.
    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 = gmt