]> granicus.if.org Git - neomutt/commitdiff
Prevent an integer overflow in mutt_mktime() (closes #3880)
authorKevin McCarthy <kevin@8t8.us>
Sun, 23 Oct 2016 20:43:56 +0000 (13:43 -0700)
committerKevin McCarthy <kevin@8t8.us>
Sun, 23 Oct 2016 20:43:56 +0000 (13:43 -0700)
Check to make sure the year passed in isn't bigger than can be
represented using time_t on the platform.

Also add a (time_t) cast to an intermediate "years * 365" calculation
to prevent an overflow there.

Thanks to TAKAHASHI Tamotsu for his patch, and to Vincent Lefèvre for
his improvement.  I merely took their code and commited it.

date.c

diff --git a/date.c b/date.c
index c173fe6525549be8999dd6f9e1f8114f2ac53af5..6fd7eaf9311c80deddf4ea2227f52a0e31d2407a 100644 (file)
--- a/date.c
+++ b/date.c
@@ -63,6 +63,10 @@ time_t mutt_local_tz (time_t t)
   return (compute_tz (t, &utc));
 }
 
+/* theoretically time_t can be float but it is integer on most (if not all) systems */
+#define TIME_T_MAX ((((time_t) 1 << (sizeof(time_t) * 8 - 2)) - 1) * 2 + 1)
+#define TM_YEAR_MAX (1970 + (((((TIME_T_MAX - 59) / 60) - 59) / 60) - 23) / 24 / 366)
+
 /* converts struct tm to time_t, but does not take the local timezone into
    account unless ``local'' is nonzero */
 time_t mutt_mktime (struct tm *t, int local)
@@ -73,6 +77,10 @@ time_t mutt_mktime (struct tm *t, int local)
     0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
   };
 
+  /* Prevent an integer overflow */
+  if (t->tm_year > TM_YEAR_MAX)
+    return TIME_T_MAX;
+
   /* Compute the number of days since January 1 in the same year */
   g = AccumDaysPerMonth [t->tm_mon % 12];
 
@@ -84,7 +92,7 @@ time_t mutt_mktime (struct tm *t, int local)
   t->tm_yday = g;
 
   /* Compute the number of days since January 1, 1970 */
-  g += (t->tm_year - 70) * 365;
+  g += (t->tm_year - 70) * (time_t)365;
   g += (t->tm_year - 69) / 4;
 
   /* Compute the number of hours */