Subject: pkg/18777: perl's POSIX::strftime() routinely gets gmtoff and zone wrong
To: None <gnats-bugs@gnats.netbsd.org>
From: Andrew Brown <atatat@atatdot.net>
List: netbsd-bugs
Date: 10/22/2002 18:51:30
>Number:         18777
>Category:       pkg
>Synopsis:       perl's POSIX::strftime() routinely gets gmtoff and zone wrong
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    pkg-manager
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue Oct 22 15:52:00 PDT 2002
>Closed-Date:
>Last-Modified:
>Originator:     TheMan
>Release:        1.6I (2002/09/06-current)
>Organization:
none
>Environment:
	
System: NetBSD this 1.6I NetBSD 1.6I (THAT) #136: Thu Oct 10 14:50:15 EDT 2002     andrew@this:/usr/src/sys/arch/i386/compile/THAT i386
perl-5.6.1nb7       Practical Extraction and Report Language

>Description:

perl, in its monolithic attempts at converting lists of things to
arbitrarily sized lists of numbers, fudges things just a tad too much
when dealing with strftime().

>How-To-Repeat:

correct output (from date):

% sh -c 'for t in 1000 900 800 700 600; do \
	date -r $(($t*1000000)) +"%c %z %Z"; done'
Sat Sep  8 21:46:40 2001 -0400 EDT
Thu Jul  9 12:00:00 1998 -0400 EDT
Tue May  9 02:13:20 1995 -0400 EDT
Sat Mar  7 15:26:40 1992 -0500 EST
Thu Jan  5 05:40:00 1989 -0500 EST

incorrect output (from perl):

% perl -MPOSIX -e 'foreach $t (1000,900,800,700,600) { \
	@tm=localtime($t*1000000);print(strftime("%c %z %Z%n",@tm));}'
Sat Sep  8 21:46:40 2001 -0400 EDT
Thu Jul  9 12:00:00 1998 -0400 EDT
Tue May  9 02:13:20 1995 -0400 EDT
Sat Mar  7 15:26:40 1992 -0400 EDT		<- wrong tz, gmtoff
Thu Jan  5 05:40:00 1989 -0400 EDT		<- wrong tz, gmtoff

corrected output (from perl):

Sat Sep  8 21:46:40 2001 -0400 EDT
Thu Jul  9 12:00:00 1998 -0400 EDT
Tue May  9 02:13:20 1995 -0400 EDT
Sat Mar  7 15:26:40 1992 -0500 EST		<- now correct
Thu Jan  5 05:40:00 1989 -0500 EST		<- now correct

>Fix:

the patch below, though some people might not like it (especially
since it would cause a PKGREVISION bump in the perl pkg :).  actually,
it's really not that bad.  someone who was truly evil could simply
*build* the new perl pkg, install the new POSIX.so file, and tweak the
existing checksum in the +CONTENTS file.  hmm...perhaps that's just a
tad *too* evil.

$NetBSD$

Use the libc functions to ensure that the time zone string and the
GMT offset are set correctly.  If not, they get stuck in whatever
they are for this instant (ie, DST is ignored for future and past
times).

--- ext/POSIX/POSIX.xs.orig	Fri Apr  6 00:38:46 2001
+++ ext/POSIX/POSIX.xs	Tue Oct 22 18:12:05 2002
@@ -3846,8 +3846,8 @@
 	{
 	    char tmpbuf[128];
 	    struct tm mytm;
+	    time_t t;
 	    int len;
-	    init_tm(&mytm);	/* XXX workaround - see init_tm() above */
 	    mytm.tm_sec = sec;
 	    mytm.tm_min = min;
 	    mytm.tm_hour = hour;
@@ -3857,7 +3857,9 @@
 	    mytm.tm_wday = wday;
 	    mytm.tm_yday = yday;
 	    mytm.tm_isdst = isdst;
-	    mini_mktime(&mytm);
+	    /* use libc to normalize the thing -- @@@ */
+	    t = mktime(&mytm);
+	    mytm = *localtime(&t);
 	    len = strftime(tmpbuf, sizeof tmpbuf, fmt, &mytm);
 	    /*
 	    ** The following is needed to handle to the situation where 
>Release-Note:
>Audit-Trail:
>Unformatted: