From 71ea08beeda2a618ad8eb339e3b02b36233a1627 Mon Sep 17 00:00:00 2001 From: Mattt Zmuda Date: Wed, 28 Oct 2026 12:58:45 -0700 Subject: [PATCH] swift: write inside withUnsafeBytes in OutgoingConnection.send The data pointer escaped withUnsafeBytes before write used it, which could send incorrect bytes for short messages in optimized builds. Perform the write inside the closure to keep the pointer valid. Fixes tailscale/tailscale#22025 Signed-off-by: Mattt Zmuda --- swift/TailscaleKit/OutgoingConnection.swift | 4 +++- swift/TailscaleKitXCTests/TailscaleKitTests.swift | 11 +++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/swift/TailscaleKit/OutgoingConnection.swift b/swift/TailscaleKit/OutgoingConnection.swift index 97195f9..dc86aa5 100644 --- a/swift/TailscaleKit/OutgoingConnection.swift +++ b/swift/TailscaleKit/OutgoingConnection.swift @@ -101,7 +101,9 @@ public actor OutgoingConnection { throw TailscaleError.connectionClosed } - let bytesWritten = Darwin.write(conn, data.withUnsafeBytes { $0.baseAddress! }, data.count) + let bytesWritten = data.withUnsafeBytes { bytes in + Darwin.write(conn, bytes.baseAddress, bytes.count) + } if bytesWritten != data.count { throw TailscaleError.shortWrite diff --git a/swift/TailscaleKitXCTests/TailscaleKitTests.swift b/swift/TailscaleKitXCTests/TailscaleKitTests.swift index 8713f98..9c19cf8 100644 --- a/swift/TailscaleKitXCTests/TailscaleKitTests.swift +++ b/swift/TailscaleKitXCTests/TailscaleKitTests.swift @@ -37,10 +37,13 @@ final class TailscaleKitTests: XCTestCase { try await runConnectionTests(for: .v6) } - func runConnectionTests(for netType: IPAddrType) async throws { - let logger = BlackholeLogger() + func testSendShortMessage() async throws { + try await runConnectionTests(for: .v4, message: Data("ping".utf8)) + } - let want = "Hello Tailscale".data(using: .utf8)! + func runConnectionTests(for netType: IPAddrType, + message want: Data = Data("Hello Tailscale".utf8)) async throws { + let logger = BlackholeLogger() do { let ts1 = try TailscaleNode(config: mockConfig(), logger: logger) @@ -95,7 +98,7 @@ final class TailscaleKitTests: XCTestCase { let got = try await inbound.receiveMessage(timeout: 2) print("got \(got)") - XCTAssert(got == want) + XCTAssertEqual(got, want) msgReceived.fulfill() }