From: David 'Digit' Turner Date: Thu, 10 Sep 2009 00:41:59 +0000 (-0700) Subject: Fix an infinite loop in time2sub. X-Git-Tag: android-x86-2.2~145^2~13^2 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=2093d350be21ff086f9e145404877941b9a42c5c;p=android-x86%2Fbionic.git Fix an infinite loop in time2sub. The problem is that time_t is signed, and the original code relied on the fact that (X + c < X) in case of overflow for c >= 0. Unfortunately, this condition is only guaranteed by the standard for unsigned arithmetic, and the gcc 4.4.0 optimizer did completely remove the corresponding test from the code. This resulted in a missing boundary check, and an infinite loop. The problem is solved by testing explicitely for TIME_T_MIN and TIME_T_MAX in the loop that uses this. Also fix increment_overflow and long_increment_overflow which were buggy for exactly the same reasons. Note: a similar fix is needed for system/core/libcutils --- diff --git a/libc/tzcode/localtime.c b/libc/tzcode/localtime.c index 9c5f2188a..83c101162 100644 --- a/libc/tzcode/localtime.c +++ b/libc/tzcode/localtime.c @@ -75,6 +75,31 @@ static __inline__ void _tzUnlock(void) pthread_mutex_unlock(&_tzMutex); } +/* Complex computations to determine the min/max of time_t depending + * on TYPE_BIT / TYPE_SIGNED / TYPE_INTEGRAL. + * These macros cannot be used in pre-processor directives, so we + * let the C compiler do the work, which makes things a bit funky. + */ +static const time_t TIME_T_MAX = + TYPE_INTEGRAL(time_t) ? + ( TYPE_SIGNED(time_t) ? + ~((time_t)1 << (TYPE_BIT(time_t)-1)) + : + ~(time_t)0 + ) + : /* if time_t is a floating point number */ + ( sizeof(time_t) > sizeof(float) ? (time_t)DBL_MAX : (time_t)FLT_MAX ); + +static const time_t TIME_T_MIN = + TYPE_INTEGRAL(time_t) ? + ( TYPE_SIGNED(time_t) ? + ((time_t)1 << (TYPE_BIT(time_t)-1)) + : + 0 + ) + : + ( sizeof(time_t) > sizeof(float) ? (time_t)DBL_MIN : (time_t)FLT_MIN ); + #ifndef WILDABBR /* ** Someone might make incorrect use of a time zone abbreviation: @@ -1683,11 +1708,16 @@ increment_overflow(number, delta) int * number; int delta; { - int number0; + unsigned number0 = (unsigned)*number; + unsigned number1 = (unsigned)(number0 + delta); + + *number = (int)number1; - number0 = *number; - *number += delta; - return (*number < number0) != (delta < 0); + if (delta >= 0) { + return ((int)number1 < (int)number0); + } else { + return ((int)number1 > (int)number0); + } } static int @@ -1695,11 +1725,16 @@ long_increment_overflow(number, delta) long * number; int delta; { - long number0; + unsigned long number0 = (unsigned long)*number; + unsigned long number1 = (unsigned long)(number0 + delta); + + *number = (long)number1; - number0 = *number; - *number += delta; - return (*number < number0) != (delta < 0); + if (delta >= 0) { + return ((long)number1 < (long)number0); + } else { + return ((long)number1 > (long)number0); + } } static int @@ -1868,14 +1903,14 @@ const int do_norm_secs; } else dir = tmcomp(&mytm, &yourtm); if (dir != 0) { if (t == lo) { - ++t; - if (t <= lo) + if (t == TIME_T_MAX) return WRONG; + ++t; ++lo; } else if (t == hi) { - --t; - if (t >= hi) + if (t == TIME_T_MIN) return WRONG; + --t; --hi; } if (lo > hi)