summaryrefslogtreecommitdiff
path: root/lib/libc
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2005-08-09 03:22:07 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2005-08-09 03:22:07 +0000
commitea9360cd901a644039d864bec59eb393c782c450 (patch)
tree56c32135da0ddfb59ec1f3a4443623cc90e50874 /lib/libc
parent7d22d3cdc9c0a03158f550c35a6a26417869ee92 (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.c62
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)