mktime: avoid signed integer overflow
authorPaul Eggert <eggert@cs.ucla.edu>
Fri, 16 Mar 2012 10:18:12 +0000 (03:18 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Wed, 23 May 2012 21:36:25 +0000 (14:36 -0700)
* time/mktime.c (__mktime_internal): Do not mishandle the case
where diff == INT_MIN.

ChangeLog
time/mktime.c

index e795eca..71045db 100644 (file)
--- 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.
index f4d9cf1..e1fbf9e 100644 (file)
@@ -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;