mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[concurrency] Fix an off by one error in generic handling in local capture checking code.
Otherwise, we break memory safety by accessing a generic parameter that does not exist resulting in undefined behavior. rdar://150351351
This commit is contained in:
@@ -3040,7 +3040,7 @@ namespace {
|
||||
// If the local function is generic and this is one of its generic
|
||||
// parameters, ignore it.
|
||||
if (genericSig.getNextDepth() > 0 &&
|
||||
genericDepth < genericSig.getNextDepth() - 1)
|
||||
genericDepth >= genericSig.getNextDepth())
|
||||
continue;
|
||||
|
||||
if (type->isTypeParameter() && innermostGenericDC)
|
||||
|
||||
65
test/Concurrency/metatype_crasher.swift
Normal file
65
test/Concurrency/metatype_crasher.swift
Normal file
@@ -0,0 +1,65 @@
|
||||
// RUN: %target-typecheck-verify-swift -swift-version 6
|
||||
|
||||
// REQUIRES: concurrency
|
||||
|
||||
struct MyType<T: Sendable> : Sendable {
|
||||
enum MyError: Error {
|
||||
case error
|
||||
}
|
||||
|
||||
public init(_ h: T) { self.handler = h }
|
||||
|
||||
public var handler: T
|
||||
|
||||
public func handle<OperationInput, OperationOutput>(
|
||||
forOperation operationID: String,
|
||||
using handlerMethod: @Sendable @escaping (T)
|
||||
-> ((OperationInput) async throws -> OperationOutput),
|
||||
deserializer: @Sendable @escaping (
|
||||
) throws -> OperationInput,
|
||||
serializer: @Sendable @escaping (OperationOutput) throws
|
||||
-> ()
|
||||
) async throws -> () where OperationInput: Sendable,
|
||||
OperationOutput: Sendable
|
||||
{
|
||||
@Sendable
|
||||
func wrappingErrors<R>(
|
||||
work: () async throws -> R,
|
||||
mapError: (any Error) -> any Error
|
||||
) async throws -> R {
|
||||
fatalError()
|
||||
}
|
||||
@Sendable
|
||||
func makeError(
|
||||
input: OperationInput? = nil,
|
||||
output: OperationOutput? = nil,
|
||||
error: any Error
|
||||
) -> any Error {
|
||||
fatalError()
|
||||
}
|
||||
var next: @Sendable () async throws // expected-warning {{}}
|
||||
-> () = {
|
||||
let input: OperationInput = try await wrappingErrors {
|
||||
try deserializer()
|
||||
} mapError: { error in
|
||||
makeError(error: error)
|
||||
}
|
||||
let output: OperationOutput = try await wrappingErrors {
|
||||
let method = handlerMethod(handler)
|
||||
return try await wrappingErrors {
|
||||
try await method(input)
|
||||
} mapError: { error in
|
||||
MyError.error
|
||||
}
|
||||
} mapError: { error in
|
||||
makeError(input: input, error: error)
|
||||
}
|
||||
return try await wrappingErrors {
|
||||
try serializer(output)
|
||||
} mapError: { error in
|
||||
makeError(input: input, output: output, error: error)
|
||||
}
|
||||
}
|
||||
return try await next()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user