diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2012-03-16 03:18:12 -0700 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2012-05-23 14:36:25 -0700 |
commit | f8591f8049a401c898737ca843d87872b93e6ccc (patch) | |
tree | 7e2072a606a199ae8646d8e9a00f2d905f13e8d3 | |
parent | 94c7d826c97ec1ae6ced9f83fe1fe6cfcc235edb (diff) | |
download | glibc-f8591f8049a401c898737ca843d87872b93e6ccc.tar.gz glibc-f8591f8049a401c898737ca843d87872b93e6ccc.tar.xz glibc-f8591f8049a401c898737ca843d87872b93e6ccc.zip |
mktime: avoid signed integer overflow
* time/mktime.c (__mktime_internal): Do not mishandle the case where diff == INT_MIN.
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | time/mktime.c | 8 |
2 files changed, 8 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog index e795eca881..71045dbd47 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2012-05-23 Paul Eggert <eggert@cs.ucla.edu> + mktime: avoid signed integer overflow + * time/mktime.c (__mktime_internal): Do not mishandle the case + where diff == INT_MIN. + mktime: simplify computation of average * time/mktime.c (ranged_convert): Use new time_t_avg function instead of rolling our own (probably-slower) code. diff --git a/time/mktime.c b/time/mktime.c index f4d9cf1528..e1fbf9ea19 100644 --- a/time/mktime.c +++ b/time/mktime.c @@ -445,7 +445,7 @@ __mktime_internal (struct tm *tp, int approx_biennia = SHR (t0, ALOG2_SECONDS_PER_BIENNIUM); int diff = approx_biennia - approx_requested_biennia; - int abs_diff = diff < 0 ? - diff : diff; + int approx_abs_diff = diff < 0 ? -1 - diff : diff; /* IRIX 4.0.5 cc miscalculates TIME_T_MIN / 3: it erroneously gives a positive value of 715827882. Setting a variable @@ -456,15 +456,15 @@ __mktime_internal (struct tm *tp, time_t overflow_threshold = (time_t_max / 3 - time_t_min / 3) >> ALOG2_SECONDS_PER_BIENNIUM; - if (overflow_threshold < abs_diff) + if (overflow_threshold < approx_abs_diff) { /* Overflow occurred. Try repairing it; this might work if the time zone offset is enough to undo the overflow. */ time_t repaired_t0 = -1 - t0; approx_biennia = SHR (repaired_t0, ALOG2_SECONDS_PER_BIENNIUM); diff = approx_biennia - approx_requested_biennia; - abs_diff = diff < 0 ? - diff : diff; - if (overflow_threshold < abs_diff) + approx_abs_diff = diff < 0 ? -1 - diff : diff; + if (overflow_threshold < approx_abs_diff) return -1; guessed_offset += repaired_t0 - t0; t0 = repaired_t0; |