From 7e168abccbb353afc763249c72fc9c986d7b688b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexis=20Laferri=C3=A8re?= Date: Tue, 9 Dec 2025 16:47:03 -0800 Subject: [PATCH] Fix potential memory corruption from CachedCompilation.Iterator The new experimental compiler feature `CheckImplementationOnly` enables type-checking the use of `@_implementationOnly` imports when building without library-evolution. I tried enabling this check on the driver project and it reported one potential issue that I hope to fix here. The issue is a property in a struct with the static type of `CSwiftScan.swiftscan_cached_compilation_t` where `CSwiftScan` is `@_implementationOnly` imported. This means that clients using this structs wouldn't see the right memory layout information unless they import `CSwiftScan` too. This may not have been an issue in practice if the type was used only within the same module. I'm suggesting a fix here. Keeping a reference to `CachedCompilation` should be safe as it's a class that hides the memory layout from the clients. We should adopt `CheckImplementationOnly` in the driver once it's completed, some early versions of it were too strict. --- Sources/SwiftDriver/SwiftScan/SwiftScanCAS.swift | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Sources/SwiftDriver/SwiftScan/SwiftScanCAS.swift b/Sources/SwiftDriver/SwiftScan/SwiftScanCAS.swift index 188c26ed9..cbb0db6b7 100644 --- a/Sources/SwiftDriver/SwiftScan/SwiftScanCAS.swift +++ b/Sources/SwiftDriver/SwiftScan/SwiftScanCAS.swift @@ -78,19 +78,18 @@ extension CachedCompilation: Sequence { public struct Iterator: IteratorProtocol { public typealias Element = CachedOutput let limit: UInt32 - let ptr: swiftscan_cached_compilation_t - let lib: SwiftScan + let sequence: CachedCompilation var idx: UInt32 = 0 public mutating func next() -> CachedOutput? { guard idx < self.limit else { return nil } - let output = self.lib.api.swiftscan_cached_compilation_get_output(self.ptr, idx) + let output = self.sequence.lib.api.swiftscan_cached_compilation_get_output(self.sequence.ptr, idx) idx += 1 // output can never be nil. - return CachedOutput(output!, lib: self.lib) + return CachedOutput(output!, lib: self.sequence.lib) } } public func makeIterator() -> Iterator { - return Iterator(limit: self.count, ptr: self.ptr, lib: self.lib) + return Iterator(limit: self.count, sequence: self) } }