Merge pull request #311 from apple/dispatch-timebase-overflow

Fixes overflow trap when creating DispatchTime objects with large upt…
diff --git a/src/swift/Time.swift b/src/swift/Time.swift
index b6cd33c..538cd42 100644
--- a/src/swift/Time.swift
+++ b/src/swift/Time.swift
@@ -59,9 +59,13 @@
 	public init(uptimeNanoseconds: UInt64) {
 		var rawValue = uptimeNanoseconds
 #if HAVE_MACH
-		if (DispatchTime.timebaseInfo.numer != DispatchTime.timebaseInfo.denom) {
-			rawValue = (rawValue * UInt64(DispatchTime.timebaseInfo.denom) 
-				+ UInt64(DispatchTime.timebaseInfo.numer - 1)) / UInt64(DispatchTime.timebaseInfo.numer)
+		// UInt64.max means distantFuture. Do not try to scale it.
+		if rawValue != UInt64.max && DispatchTime.timebaseInfo.numer != DispatchTime.timebaseInfo.denom {
+			var (result, overflow) = rawValue.multipliedReportingOverflow(by: UInt64(DispatchTime.timebaseInfo.denom))
+			if !overflow {
+				(result, overflow) = result.addingReportingOverflow(UInt64(DispatchTime.timebaseInfo.numer - 1))
+			}
+			rawValue = overflow ? UInt64.max : result / UInt64(DispatchTime.timebaseInfo.numer)
 		}
 #endif
 		self.rawValue = dispatch_time_t(rawValue)
@@ -70,8 +74,12 @@
 	public var uptimeNanoseconds: UInt64 {
 		var result = self.rawValue
 #if HAVE_MACH
-		if (DispatchTime.timebaseInfo.numer != DispatchTime.timebaseInfo.denom) {
-			result = result * UInt64(DispatchTime.timebaseInfo.numer) / UInt64(DispatchTime.timebaseInfo.denom)
+		var overflow: Bool
+
+		// UInt64.max means distantFuture. Do not try to scale it.
+		if rawValue != UInt64.max && DispatchTime.timebaseInfo.numer != DispatchTime.timebaseInfo.denom {
+			(result, overflow) = result.multipliedReportingOverflow(by: UInt64(DispatchTime.timebaseInfo.numer))
+			result = overflow ? UInt64.max : result / UInt64(DispatchTime.timebaseInfo.denom)
 		}
 #endif
 		return result