[tz] Fiji change exposed Y2038 bug in localtime.c
Paul Eggert
eggert at cs.ucla.edu
Thu Oct 1 09:30:43 UTC 2015
The recent change to the Pacific/Fiji data added a transition from +1300 to
+1200 at 2018-01-17 03:00 local time, which is just before the maximum 32-bit
signed time_t value. Previously, that transition was just after the 32-bit
boundary.
This change exposed a curious bug in the interaction between zic and localtime.c
on platforms with signed 32-bit time_t. For the benefit of older systems, zic
outputs explicit transitions for years in the range 1900 through 2037, relying
on the POSIX-TZ-style string (for Pacific/Fiji, "FJT-12FJST,M11.1.0,M1.3.0/3")
at the end of the tzfile for transitions outside that range. Although newer
versions of localtime.c should use the POSIX-TZ-style string for time stamps in
the year 2038, if time_t is a signed 32-bit integer these localtime.c versions
mishandle Fijian time stamps from 2038-01-16 14:00:00 through 2038-01-19
03:14:07 UTC. This bug is fixed by the attached patch.
I discovered this bug during release testing, and will squeeze the attached
patch into the next tz release which I plan to make shortly. It strikes me,
though, that perhaps zic should be changed too, to better accommodate buggy
localtime implementations. If the zic cutoff for old-style transitions is at
2038-01-19 03:14:08 UTC, rather than at 2038-01-01, buggy localtime code should
do the right thing. I don't want to install such a change into zic without some
thought and/or discussion and/or testing, though; it can wait until a later release.
-------------- next part --------------
From 6d00980f1ff2ac665f3de027c79faacf4f26d1b0 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert at cs.ucla.edu>
Date: Thu, 1 Oct 2015 01:43:59 -0700
Subject: [PATCH] Fix signed 32-bit time_t localtime bug on Fiji
* localtime.c (tzloadbody): When on a host with signed 32-bit
time_t, don't skip reading the 64-bit tables, as skipping caused
the code to mishandle Pacific/Fiji in the year 2038. With the
recent changes for Fiji, there is a transition from +1300 to +1200
at 2018-01-17 03:00 local time. Since this transition is after
2037, zic omits the explicit transition, which must be calculated
from the POSIX-TZ-style string "FJT-12FJST,M11.1.0,M1.3.0/3" at
the end of the file. If the code skips reading the 64-bit tables,
it doesn't get to the proper position to see the POSIX-TZ-style
string.
---
localtime.c | 5 -----
1 file changed, 5 deletions(-)
diff --git a/localtime.c b/localtime.c
index be10749..e3bc763 100644
--- a/localtime.c
+++ b/localtime.c
@@ -556,11 +556,6 @@ tzloadbody(char const *name, struct state *sp, bool doextend,
break;
nread -= p - up->buf;
memmove(up->buf, p, nread);
- /*
- ** If this is a signed narrow time_t system, we're done.
- */
- if (TYPE_SIGNED(time_t) && stored >= (int) sizeof(time_t))
- break;
}
if (doextend && nread > 2 &&
up->buf[0] == '\n' && up->buf[nread - 1] == '\n' &&
--
2.1.4
More information about the tz
mailing list