[tz] [PROPOSED PATCH 1/5] Port to platforms with leap seconds and unsigned time_t.
Paul Eggert
eggert at cs.ucla.edu
Tue Aug 19 19:52:38 UTC 2014
* localtime.c (tzload): On platforms where time_t is unsigned,
don't mishandle zones that contain leap seconds but no ordinary
transitions after 1970. This problem can be reproduced by running
'zdump -v right/Asia/Dubai' on a platform where time_t is an
unsigned 32-bit integer.
---
localtime.c | 28 ++++++++++++++--------------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/localtime.c b/localtime.c
index 8a66650..a1e6601 100644
--- a/localtime.c
+++ b/localtime.c
@@ -395,28 +395,28 @@ tzload(register const char *name, register struct state *const sp,
ttisstdcnt + /* ttisstds */
ttisgmtcnt) /* ttisgmts */
goto oops;
+
+ /* Read transitions, discarding those out of time_t range.
+ But pretend the last transition before time_t_min
+ occurred at time_t_min. */
timecnt = 0;
for (i = 0; i < sp->timecnt; ++i) {
int_fast64_t at
= stored == 4 ? detzcode(p) : detzcode64(p);
- sp->types[i] = ((TYPE_SIGNED(time_t)
- ? time_t_min <= at
- : 0 <= at)
- && at <= time_t_max);
+ sp->types[i] = at <= time_t_max;
if (sp->types[i]) {
- if (i && !timecnt && at != time_t_min) {
- /*
- ** Keep the earlier record, but tweak
- ** it so that it starts with the
- ** minimum time_t value.
- */
- sp->types[i - 1] = 1;
- sp->ats[timecnt++] = time_t_min;
- }
- sp->ats[timecnt++] = at;
+ time_t attime
+ = ((TYPE_SIGNED(time_t) ? at < time_t_min : at < 0)
+ ? time_t_min : at);
+ if (timecnt && sp->ats[timecnt - 1] == attime) {
+ sp->types[i - 1] = 0;
+ timecnt--;
+ }
+ sp->ats[timecnt++] = attime;
}
p += stored;
}
+
timecnt = 0;
for (i = 0; i < sp->timecnt; ++i) {
unsigned char typ = *p++;
--
1.9.1
More information about the tz
mailing list