From 4195ac606945e0589736460ecae11a2b870a2e46 Mon Sep 17 00:00:00 2001 From: Kim Topley Date: Wed, 11 Oct 2017 07:59:21 -0700 Subject: [PATCH] Fixes overflow trap when creating DispatchTime objects with large uptimeNanoseconds values. --- src/swift/Time.swift | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/swift/Time.swift b/src/swift/Time.swift index b6cd33cbf..538cd42fb 100644 --- a/src/swift/Time.swift +++ b/src/swift/Time.swift @@ -59,9 +59,13 @@ public struct DispatchTime : Comparable { 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 struct DispatchTime : Comparable { 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