summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorteor (Tim Wilson-Brown) <teor2345@gmail.com>2016-02-25 11:02:39 +0800
committerNick Mathewson <nickm@torproject.org>2016-03-24 10:17:48 -0400
commite71e8e005a533ad519d6b226541ede115e0a5b79 (patch)
tree803860ef330d1d83fdfe9b57c110d949773df69b
parente019e11e61c2c57c84505aaf2559966bddd4a10d (diff)
downloadtor-e71e8e005a533ad519d6b226541ede115e0a5b79.tar.gz
tor-e71e8e005a533ad519d6b226541ede115e0a5b79.zip
Avoid overflow in tor_timegm on 32 bit platforms due to year 2038
-rw-r--r--changes/bug184795
-rw-r--r--src/common/util.c23
2 files changed, 25 insertions, 3 deletions
diff --git a/changes/bug18479 b/changes/bug18479
new file mode 100644
index 0000000000..d7a935b055
--- /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 fda5993edf..6e90f25c8a 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;
}