Skip to content

fix(apple/ios): don't require hard link to __res_9_state - #10143

Merged
jamilbk merged 2 commits into
mainfrom
fix/apple-ios-res9
Aug 5, 2025
Merged

jamilbk merged 2 commits into
mainfrom
fix/apple-ios-res9

Conversation

@jamilbk

@jamilbk jamilbk commented Aug 5, 2025 •

Copy link
Copy Markdown
Member

In Xcode 16, how the compiler determines the size of C structs changed.

In Xcode 15 and below, when the compiler saw __res_9_state(), it thought, "This is a C struct. I know its size and layout from the system's header files. I will generate code to allocate that much memory and zero it out." This was a type-based operation; it only needed the "blueprint" for the struct.

In Xcode 16 and later, the compiler sees __res_9_state() and thinks, "This is a C struct. To initialize it, I need to link to the actual symbol named ___res_9_state inside the libresolv library." This became a symbol-based operation, creating a direct dependency that didn't exist before.

To fix this, we initialize a raw pointer with a manual type specification to the zeroed-out struct, which reverts to the prior behavior.

Has been tested on iPhone 12, iOS 17.

Fixes #10108

Copilot AI review requested due to automatic review settings August 5, 2025 19:39
@vercel

vercel Bot commented Aug 5, 2025 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
firezone ✅ Ready (Inspect) Visit Preview 💬 Add feedback Aug 5, 2025 7:44pm

@jamilbk
jamilbk requested review from thomaseizinger and removed request for Copilot August 5, 2025 19:39

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR fixes a compilation issue in Xcode 16 related to resolving DNS servers by changing how the __res_9_state struct is handled. The change works around a compiler behavior change where Xcode 16 requires hard linking to the __res_9_state symbol, while Xcode 15 and below only needed the struct type definition.

  • Refactored BindResolvers from a class to an enum with static methods
  • Implemented manual memory allocation for __res_9_state to avoid direct symbol linking
  • Integrated the getnameinfo function directly into the server retrieval process

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
BindResolvers.swift Complete refactor from class-based to static enum-based implementation with manual memory management for __res_9_state
Adapter.swift Updated method calls to use the new static API

// filter is to remove the erroneous empty entry when there's no real servers
return Array(servers[0..<found]).filter { $0.sin.sin_len > 0 }
// 4. Get the servers.
var servers = [res_9_sockaddr_union](repeating: res_9_sockaddr_union(), count: 10)

Copilot AI Aug 5, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The magic number 10 for maximum servers should be extracted to a named constant to improve maintainability and make it easier to change if needed.

Suggested change
var servers = [res_9_sockaddr_union](repeating: res_9_sockaddr_union(), count: 10)
var servers = [res_9_sockaddr_union](repeating: res_9_sockaddr_union(), count: maxServers)

Copilot uses AI. Check for mistakes.
return Array(servers[0..<found]).filter { $0.sin.sin_len > 0 }
// 4. Get the servers.
var servers = [res_9_sockaddr_union](repeating: res_9_sockaddr_union(), count: 10)
let foundCount = Int(res_9_getservers(statePtr, &servers, Int32(servers.count)))

Copilot AI Aug 5, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function doesn't handle potential errors from res_9_getservers. Consider checking if the return value is negative (indicating an error) and logging an appropriate warning message.

Suggested change
let foundCount = Int(res_9_getservers(statePtr, &servers, Int32(servers.count)))
let foundCount = Int(res_9_getservers(statePtr, &servers, Int32(servers.count)))
if foundCount < 0 {
Log.warning("Failed to get resolver servers (res_9_getservers returned \(foundCount))")
return []
}

Copilot uses AI. Check for mistakes.
@sentry

sentry Bot commented Aug 5, 2025

Copy link
Copy Markdown

Sentry Issue: APPLE-CLIENT-7D

@thomaseizinger thomaseizinger left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What on earth. Were we doing this "wrong" before? I can't believe Apple just breaks compatibility with older versions like that.

@jamilbk

jamilbk commented Aug 5, 2025

Copy link
Copy Markdown
Member Author

What on earth. Were we doing this "wrong" before? I can't believe Apple just breaks compatibility with older versions like that.

Technically this is in "internal" API, or Unix API which they discourage but support. Maybe we should go back to Objective-C.

@jamilbk
jamilbk added this pull request to the merge queue Aug 5, 2025
Merged via the queue into main with commit b96ee52 Aug 5, 2025

This branch was successfully deployed

1 active deployment
Preview — 3ea0c121 Deployed Aug 5, 2025 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Can't sign in on iOS 17 and below

3 participants