From d18b137640222fe29a22568077c4799d213fdf96 Mon Sep 17 00:00:00 2001 From: George Barnett Date: Thu, 25 Jul 2024 09:56:51 +0100 Subject: [PATCH] Change 'unsafeDowncast' to 'as!' (#495) Motivation: The 'unsafeDowncast' can cause a miscompile leading to unexpected runtime behaviour. Modifications: - Use 'as!' instead Result: No miscompiles on 5.10 --- Sources/ConnectionPoolModule/NIOLock.swift | 29 +++++++++++----------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/Sources/ConnectionPoolModule/NIOLock.swift b/Sources/ConnectionPoolModule/NIOLock.swift index dbc7dbe9..13a9df4a 100644 --- a/Sources/ConnectionPoolModule/NIOLock.swift +++ b/Sources/ConnectionPoolModule/NIOLock.swift @@ -52,12 +52,12 @@ extension LockOperations { debugOnly { pthread_mutexattr_settype(&attr, .init(PTHREAD_MUTEX_ERRORCHECK)) } - + let err = pthread_mutex_init(mutex, &attr) precondition(err == 0, "\(#function) failed in pthread_mutex with error \(err)") #endif } - + @inlinable static func destroy(_ mutex: UnsafeMutablePointer) { mutex.assertValidAlignment() @@ -69,7 +69,7 @@ extension LockOperations { precondition(err == 0, "\(#function) failed in pthread_mutex with error \(err)") #endif } - + @inlinable static func lock(_ mutex: UnsafeMutablePointer) { mutex.assertValidAlignment() @@ -81,7 +81,7 @@ extension LockOperations { precondition(err == 0, "\(#function) failed in pthread_mutex with error \(err)") #endif } - + @inlinable static func unlock(_ mutex: UnsafeMutablePointer) { mutex.assertValidAlignment() @@ -125,49 +125,50 @@ extension LockOperations { // See also: https://github.com/apple/swift/pull/40000 @usableFromInline final class LockStorage: ManagedBuffer { - + @inlinable static func create(value: Value) -> Self { let buffer = Self.create(minimumCapacity: 1) { _ in return value } - let storage = unsafeDowncast(buffer, to: Self.self) - + // Avoid 'unsafeDowncast' as there is a miscompilation on 5.10. + let storage = buffer as! Self + storage.withUnsafeMutablePointers { _, lockPtr in LockOperations.create(lockPtr) } - + return storage } - + @inlinable func lock() { self.withUnsafeMutablePointerToElements { lockPtr in LockOperations.lock(lockPtr) } } - + @inlinable func unlock() { self.withUnsafeMutablePointerToElements { lockPtr in LockOperations.unlock(lockPtr) } } - + @inlinable deinit { self.withUnsafeMutablePointerToElements { lockPtr in LockOperations.destroy(lockPtr) } } - + @inlinable func withLockPrimitive(_ body: (UnsafeMutablePointer) throws -> T) rethrows -> T { try self.withUnsafeMutablePointerToElements { lockPtr in return try body(lockPtr) } } - + @inlinable func withLockedValue(_ mutate: (inout Value) throws -> T) rethrows -> T { try self.withUnsafeMutablePointers { valuePtr, lockPtr in @@ -192,7 +193,7 @@ extension LockStorage: @unchecked Sendable { } struct NIOLock { @usableFromInline internal let _storage: LockStorage - + /// Create a new lock. @inlinable init() {