diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2005-08-09 03:22:07 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2005-08-09 03:22:07 +0000 |
commit | ea9360cd901a644039d864bec59eb393c782c450 (patch) | |
tree | 56c32135da0ddfb59ec1f3a4443623cc90e50874 /lib/libc | |
parent | 7d22d3cdc9c0a03158f550c35a6a26417869ee92 (diff) |
Back out a change from tzcode2005c that can cause an infinite loop in mktime().
Diffstat (limited to 'lib/libc')
-rw-r--r-- | lib/libc/time/localtime.c | 62 |
1 files changed, 20 insertions, 42 deletions
diff --git a/lib/libc/time/localtime.c b/lib/libc/time/localtime.c index 5245de78bbe..77ee0461a85 100644 --- a/lib/libc/time/localtime.c +++ b/lib/libc/time/localtime.c @@ -1,4 +1,4 @@ -/* $OpenBSD: localtime.c,v 1.28 2005/08/09 03:21:14 millert Exp $ */ +/* $OpenBSD: localtime.c,v 1.29 2005/08/09 03:22:06 millert Exp $ */ /* ** This file is in the public domain, so clarified as of ** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov). @@ -1539,11 +1539,10 @@ const int do_norm_secs; { register const struct state * sp; register int dir; + register int bits; register int i, j; register int saved_seconds; register long li; - register time_t lo; - register time_t hi; long y; time_t newt; time_t t; @@ -1617,49 +1616,28 @@ const int do_norm_secs; yourtm.tm_sec = 0; } /* - ** Do a binary search (this works whatever time_t's type is). + ** Divide the search space in half + ** (this works whether time_t is signed or unsigned). */ - if (!TYPE_SIGNED(time_t)) { - lo = 0; - hi = lo - 1; - } else if (!TYPE_INTEGRAL(time_t)) { - if (sizeof(time_t) > sizeof(float)) - hi = (time_t) DBL_MAX; - else hi = (time_t) FLT_MAX; - lo = -hi; - } else { - lo = 1; - for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i) - lo *= 2; - hi = -(lo + 1); - } + bits = TYPE_BIT(time_t) - 1; + /* + ** If time_t is signed, then 0 is just above the median, + ** assuming two's complement arithmetic. + ** If time_t is unsigned, then (1 << bits) is just above the median. + */ + t = TYPE_SIGNED(time_t) ? 0 : (((unsigned long) 1) << bits); for ( ; ; ) { - t = lo / 2 + hi / 2; - if (t < lo) - t = lo; - else if (t > hi) - t = hi; - if ((*funcp)(&t, offset, &mytm) == NULL) { - /* - ** Assume that t is too extreme to be represented in - ** a struct tm; arrange things so that it is less - ** extreme on the next pass. - */ - dir = (t > 0) ? 1 : -1; - } else dir = tmcomp(&mytm, &yourtm); + if ((*funcp)(&t, offset, &mytm) == NULL) + return WRONG; /* XXX probably wrong */ + dir = tmcomp(&mytm, &yourtm); if (dir != 0) { - if (t == lo) { - ++t; - ++lo; - } else if (t == hi) { - --t; - --hi; - } - if (lo > hi) + if (bits-- < 0) return WRONG; - if (dir > 0) - hi = t; - else lo = t; + if (bits < 0) + --t; /* may be needed if new t is minimal */ + else if (dir > 0) + t -= ((long) 1) << bits; + else t += ((long) 1) << bits; continue; } if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst) |