python mktime fails with overflow (same call works in other environments)

YONETANI Tomokazu qhwt+dfly at les.ath.cx
Thu Sep 25 21:12:53 PDT 2008


On Thu, Sep 25, 2008 at 03:48:37PM -0500, Aran Cox wrote:
> It seems that if the TZ environment is set (I tested America/Chicago and
> GMT) the c/python/perl programs all work.  If unset, (even though
> localtime exists, and corresponds to America/Chicago) all three
> programs fail to call mtime.  
> 
> I think may have been setting TZ and confused the issue slightly when
> testing the c and perl programs.  

My timezone is set to JST and TZ is usually unset.  And in fact
if I run the script with TZ set to America/Chicago, mktime() returned -1.
So I tried the C version with TZ=America/Chicago on a few machines which
also have the timezone set to JST:

  FreeBSD 4.9-RELEASE: NG
  FreeBSD 5.4-RELEASE: OK

According to FreeBSD CVSweb, FreeBSD 5.4-RELEASE has experienced
a vendor import of tzcode:
  http://www.freebsd.org/cgi/cvsweb.cgi/src/lib/libc/stdtime/localtime.c?sortby=date#rev1.39

I think the essential part of the change that fixes mktime() is something
like attached to this message.  I'm using patched libc on my -DEVELOPMENT
machine and it seems to work with TZ=America/Chicago now.  But probably we
want to catch other fixes from FreeBSD.

Cheers.
--- localtime.c.orig	2008-08-28 12:26:09 +0900
+++ localtime.c	2008-09-26 12:52:26 +0900
@@ -1349,9 +1349,9 @@
 }
 
 static time_t
-time2(struct tm * const tmp,
+time2sub(struct tm * const tmp,
       void (* const funcp)(const time_t *, long, struct tm *),
-      const long offset, int * const okayp)
+      const long offset, int * const okayp, const int do_norm_secs)
 {
 	const struct state *	sp;
 	int			dir;
@@ -1364,6 +1364,12 @@
 
 	*okayp = FALSE;
 	yourtm = *tmp;
+	if (do_norm_secs) {
+		if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
+		    SECSPERMIN)) {
+			return WRONG;
+		}
+	}
 	if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
 		return WRONG;
 	if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
@@ -1493,6 +1499,23 @@
 }
 
 static time_t
+time2(struct tm * const tmp,
+      void (* const funcp)(const time_t *, long, struct tm *),
+      const long offset, int * const okayp)
+{
+	time_t	t;
+
+	/*
+	** First try without normalization of seconds
+	** (in case tm_sec contains a value associated with a leap second).
+	** If that fails, try with normalization of seconds.
+	*/
+	t = time2sub(tmp, funcp, offset, okayp, FALSE);
+	return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE);
+}
+
+
+static time_t
 time1(struct tm * const tmp,
       void (* const funcp)(const time_t *, long, struct tm *),
       const long offset)




More information about the Users mailing list