Skip to content

fix: MacProxy crash in CFNumberGetValue on iOS - #134619

Closed
nwestfall wants to merge 1 commit into
dotnet:mainfrom
nwestfall:fix-macproxy-cfnumbertype
Closed

nwestfall wants to merge 1 commit into
dotnet:mainfrom
nwestfall:fix-macproxy-cfnumbertype

Conversation

@nwestfall

Copy link
Copy Markdown

Fixes #134617

On iOS with CoreCLR, MacProxy crashes with EXC_BAD_ACCESS in CFNumberGetValue when the system proxy configuration returns an HTTP/HTTPS proxy, whether from a PAC script or a manual setting. SocketsHttpHandler goes through this path whenever it consults HttpClient.DefaultProxy. This was discovered while moving from .NET 10 to .NET 11 and testing with Browserstack (see issue for details).

Cause

  • Natively, CFNumberType is declared as CF_ENUM(CFIndex, CFNumberType), so it's 64-bit. The P/Invoke in Interop.CoreFoundation.CFNumber.cs passes it as an int-sized enum, which leaves the upper 32 bits of x1 unspecified.
  • CFNumberGetValue uses the whole register as an index into its type table (ldrh w9, [x9, x20, lsl #1]), so it reads far out of bounds.
  • JIT and AOT code happen to zero-extend 32-bit values, which kept this latent.
  • The CoreCLR interpreter loads native-call arguments from 8-byte stack slots whose upper half can still hold stale data. On iOS that turns the bad declaration into a crash.

Changes

  • Interop.CoreFoundation.CFNumber.cs: the P/Invoke now takes CFIndex. A wrapper keeps the typed enum for callers.
  • MacProxy.cs: GetProxy(Uri) now calls a new internal GetProxy(Uri, SafeCFDictionaryHandle) overload that takes the proxy settings, so tests can supply their own. Behavior is unchanged.
  • System.Net.Http.Unit.Tests: on Apple targets, the project now compiles the real MacProxy and its interop instead of the fake, and adds MacProxyTest.
    • The tests create proxy settings in-process, in the format CFNetworkCopySystemProxySettings returns, so they don't depend on the machine's proxy configuration.

Testing

Please note, this does removes the existing Fakes/MacProxy.cs file as we need to use the real one for testing. I'm unsure if this is the best approach, but it got me to first replicate the failure I was encountering on an actual device.

The new tests can only fail where this code runs on the interpreter. Results on the iOS simulator with the 11.0 RC1 CoreCLR runtime pack:

Test Before After
GetProxy_HttpProxy_ReturnsProxyUri SIGSEGV pass
GetProxy_ProxyAutoConfigurationScript_ReturnsProxyUri SIGSEGV pass
GetProxy_ProxyAutoConfigurationScriptReturnsDirect_ReturnsNull pass pass
GetProxy_NoProxy_ReturnsNull pass pass

GetProxy_ProxyAutoConfigurationScriptReturnsDirect_ReturnsNull goes through the same PAC callback without reading a port, which shows the callback isn't the problem.

Other runs, all against the 11.0 RC1 runtime using this branch's System.Net.Http and test builds:

  • System.Net.Http.Unit.Tests, full suite: passes on macOS and on the iOS simulator (interpreter).
  • System.Net.Http.Functional.Tests, full inner-loop suite: passes on macOS, with results identical to the unfixed build.
  • The unit test project builds for all eight of its target frameworks with no warnings.

Copilot AI lite review requested due to automatic review settings September 24, 2026 21:12
@dotnet-policy-service dotnet-policy-service Bot added the community-contribution Indicates that the PR has been added by a community member label Sep 24, 2026
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 4 pipeline(s).
12 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @karelz, @dotnet/ncl
See info in area-owners.md if you want to be subscribed.

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.

Copilot review overview

🟢 Approval recommended

No unresolved issues were identified that would block approval.

Review effort: Lite
Findings: None

What changed in this PR

Fixes the Apple CFNumberGetValue ABI mismatch that can crash CoreCLR’s interpreter when resolving proxies.

Changes:

  • Passes CFNumberType as pointer-sized CFIndex.
  • Adds injectable proxy settings for deterministic testing.
  • Replaces the fake proxy with real Apple interop tests.
File Description
src/​libraries/​System.Net.Http/​tests/​UnitTests/​System.Net.Http.Unit.Tests.csproj Updated as part of this pull request.
src/​libraries/​System.Net.Http/​tests/​UnitTests/​MacProxyTest.cs Updated as part of this pull request.
src/​libraries/​System.Net.Http/​tests/​UnitTests/​Fakes/​MacProxy.cs Updated as part of this pull request.
src/​libraries/​System.Net.Http/​src/​System/​Net/​Http/​SocketsHttpHandler/​MacProxy.cs Updated as part of this pull request.
src/​libraries/​Common/​src/​Interop/​OSX/​Interop.CoreFoundation.CFNumber.cs Updated as part of this pull request.

@nwestfall

Copy link
Copy Markdown
Author

Closing in favor of #135089

@nwestfall nwestfall closed this Oct 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-System.Net.Http community-contribution Indicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[iOS][CoreCLR] SIGSEGV in CFNumberGetValue from MacProxy: CFNumberType is passed as 32-bit, but the native type is CFIndex

2 participants