Skip to content

Commit

Permalink
Change 'unsafeDowncast' to 'as!' (#495)
Browse files Browse the repository at this point in the history
Motivation:

The 'unsafeDowncast' can cause a miscompile leading to unexpected runtime behaviour.

Modifications:

- Use 'as!' instead

Result:

No miscompiles on 5.10
  • Loading branch information
glbrntt authored Jul 25, 2024
1 parent 200a94a commit d18b137
Showing 1 changed file with 15 additions and 14 deletions.
29 changes: 15 additions & 14 deletions Sources/ConnectionPoolModule/NIOLock.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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<LockPrimitive>) {
mutex.assertValidAlignment()
Expand All @@ -69,7 +69,7 @@ extension LockOperations {
precondition(err == 0, "\(#function) failed in pthread_mutex with error \(err)")
#endif
}

@inlinable
static func lock(_ mutex: UnsafeMutablePointer<LockPrimitive>) {
mutex.assertValidAlignment()
Expand All @@ -81,7 +81,7 @@ extension LockOperations {
precondition(err == 0, "\(#function) failed in pthread_mutex with error \(err)")
#endif
}

@inlinable
static func unlock(_ mutex: UnsafeMutablePointer<LockPrimitive>) {
mutex.assertValidAlignment()
Expand Down Expand Up @@ -125,49 +125,50 @@ extension LockOperations {
// See also: https://github.com/apple/swift/pull/40000
@usableFromInline
final class LockStorage<Value>: ManagedBuffer<Value, LockPrimitive> {

@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<T>(_ body: (UnsafeMutablePointer<LockPrimitive>) throws -> T) rethrows -> T {
try self.withUnsafeMutablePointerToElements { lockPtr in
return try body(lockPtr)
}
}

@inlinable
func withLockedValue<T>(_ mutate: (inout Value) throws -> T) rethrows -> T {
try self.withUnsafeMutablePointers { valuePtr, lockPtr in
Expand All @@ -192,7 +193,7 @@ extension LockStorage: @unchecked Sendable { }
struct NIOLock {
@usableFromInline
internal let _storage: LockStorage<Void>

/// Create a new lock.
@inlinable
init() {
Expand Down

0 comments on commit d18b137

Please sign in to comment.