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