[tor-commits] [tor/master] Avoid overflow in tor_timegm on 32 bit platforms due to year 2038

nickm at torproject.org nickm at torproject.org
Thu Mar 24 14:24:22 UTC 2016


commit e71e8e005a533ad519d6b226541ede115e0a5b79
Author: teor (Tim Wilson-Brown) <teor2345 at gmail.com>
Date:   Thu Feb 25 11:02:39 2016 +0800

    Avoid overflow in tor_timegm on 32 bit platforms due to year 2038
---
 changes/bug18479  |  5 +++++
 src/common/util.c | 23 ++++++++++++++++++++---
 2 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/changes/bug18479 b/changes/bug18479
new file mode 100644
index 0000000..d7a935b
--- /dev/null
+++ b/changes/bug18479
@@ -0,0 +1,5 @@
+  o Minor bugfixes (time parsing):
+    - Avoid overflow in tor_timegm when parsing dates in and after 2038
+      on platforms with 32-bit time_t.
+      Fixes bug 18479; bugfix on 3c4b4c8ca in tor-0.0.2pre14.
+      Patch by "teor".
diff --git a/src/common/util.c b/src/common/util.c
index fda5993..6e90f25 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -1475,9 +1475,19 @@ tor_timegm(const struct tm *tm, time_t *time_out)
 {
   /* This is a pretty ironclad timegm implementation, snarfed from Python2.2.
    * It's way more brute-force than fiddling with tzset().
-   */
-  time_t year, days, hours, minutes, seconds;
+   *
+   * We use int64_t rather than time_t to avoid overflow on multiplication on
+   * platforms with 32-bit time_t. Since year is clipped to INT32_MAX, and
+   * since 365 * 24 * 60 * 60 is approximately 31 million, it's not possible
+   * for INT32_MAX years to overflow int64_t when converted to seconds. */
+  int64_t year, days, hours, minutes, seconds;
   int i, invalid_year, dpm;
+
+  /* Initialize time_out to 0 for now, to avoid bad usage in case this function
+     fails and the caller ignores the return value. */
+  tor_assert(time_out);
+  *time_out = 0;
+
   /* avoid int overflow on addition */
   if (tm->tm_year < INT32_MAX-1900) {
     year = tm->tm_year + 1900;
@@ -1516,7 +1526,14 @@ tor_timegm(const struct tm *tm, time_t *time_out)
 
   minutes = hours*60 + tm->tm_min;
   seconds = minutes*60 + tm->tm_sec;
-  *time_out = seconds;
+  /* Check that "seconds" will fit in a time_t. On platforms where time_t is
+   * 32-bit, this check will fail for dates in and after 2038.
+   * "seconds" can't be negative, because "year" >= 1970. */
+  if (seconds < TIME_MIN || seconds > TIME_MAX) {
+    log_warn(LD_BUG, "Result does not fit in tor_timegm");
+    return -1;
+  }
+  *time_out = (time_t)seconds;
   return 0;
 }
 





More information about the tor-commits mailing list