summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2016-03-24 10:18:00 -0400
committerNick Mathewson <nickm@torproject.org>2016-03-24 10:18:00 -0400
commit6256c61d959dc2aa84752ac7903b827fffd53583 (patch)
tree154f0567d326f25d80f3b1949417db287ad87a06 /src/common
parent424af93ded7e1d9d98733ed17b2b6fee143262b9 (diff)
parent19fb86a2dc0a95c6b009f977c35a01b7a2211546 (diff)
downloadtor-6256c61d959dc2aa84752ac7903b827fffd53583.tar.gz
tor-6256c61d959dc2aa84752ac7903b827fffd53583.zip
Merge branch 'timegm_overflow_squashed'
Diffstat (limited to 'src/common')
-rw-r--r--src/common/util.c23
1 files changed, 20 insertions, 3 deletions
diff --git a/src/common/util.c b/src/common/util.c
index 056817e696..820e8672ec 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;
}