[iOS][CoreCLR] SIGSEGV in CFNumberGetValue from MacProxy: CFNumberType is passed as 32-bit, but the native type is CFIndex
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
評価
- 難易度
- 2/5
- 見積もり時間
- 1〜3時間
- 初心者へのやさしさ
- 78/100
- issue の種類
- バグ
- 明瞭さ
- 明確に書かれている
- 活発さ
- 活発
- 技術スタック
- csharp, ios
- 領域
- mobile-dev, networking
調査の方向性
src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.CFNumber.cs から始め、その宣言を CFNumber.h と比較します。SocketsHttpHandler が使用する MacProxy パスを追跡し、iOS の HTTP/HTTPS プロキシまたは PAC 構成で再現します。プロキシ解決でクラッシュが発生しなくなり、.NET 10 と同じようにリクエストが進行すれば完了です。
索引モデルが issue の本文から書いたものです。
説明
Description
On .NET 11 RC1 with CoreCLR, iOS apps crash with EXC_BAD_ACCESS (SIGSEGV) in CFNumberGetValue when SocketsHttpHandler asks HttpClient.DefaultProxy (MacProxy) for a proxy and the system configuration returns an HTTP/HTTPS proxy. The proxy can come from a PAC script or a manual proxy setting. We hit it on every launch on real devices behind a PAC proxy, about half a second after startup. More specifically, in our case we were testing our app migrating from .NET 10 to .NET 11 in Browserstack, which has a proxy.
The cause is the P/Invoke declaration in src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.CFNumber.cs:
internal enum CFNumberType { kCFNumberIntType = 9 } // int-sized
[LibraryImport(Libraries.CoreFoundationLibrary)]
private static unsafe partial int CFNumberGetValue(IntPtr handle, CFNumberType type, int* value);
Natively, CFNumberType is 64-bit (CFNumber.h):
typedef CF_ENUM(CFIndex, CFNumberType) { ... kCFNumberIntType = 9, ... };
Boolean CFNumberGetValue(CFNumberRef number, CFNumberType theType, void *valuePtr);
The managed side passes only 32 bits, so the upper half of x1 is unspecified. CFNumberGetValue uses the whole register as an index into its type table and reads far out of bounds.
The declaration has looked like this since MacProxy was written. JIT and AOT code happen to zero-extend 32-bit values, so the bug stayed hidden. The CoreCLR interpreter passes native-call arguments from 8-byte stack slots whose upper half can still hold stale data, and that exposes it.
Reproduction Steps
In an app:
- Create a net11.0-ios app. CoreCLR is the default runtime.
- At startup, make a request through
SocketsHttpHandler:
using var client = new HttpClient(new SocketsHttpHandler());
await client.GetAsync("https://example.com/");
IHttpClientFactoryclients useSocketsHttpHandlerby default, so they do this too.
Run the app on an iOS device whose Wi-Fi uses a proxy.- We use Automatic proxy configuration with a PAC URL. A PAC file that returns a proxy is enough, for example
function FindProxyForURL(url, host) { return "PROXY 10.0.0.1:8080"; }. - The proxy doesn't have to exist. The crash happens while the proxy URI is being built, before any connection is made.
- A PAC script that returns DIRECT does not crash, because no port is read.
- We use Automatic proxy configuration with a PAC URL. A PAC file that returns a proxy is enough, for example
- The app crashes about half a second after launch.
Expected behavior
The proxy is resolved (for the PAC example above, http://10.0.0.1:8080/) and the request continues. That's what happens on .NET 10 (Mono) and with CoreCLR on Android and macOS.
Actual behavior
The process terminates with a segmentation fault in CFNumberGetValue.
Device crash report (iPhone 16, iOS 18.6):
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x000000059dd335c2
Termination: Segmentation fault: 11 (namespace SIGNAL, code 11), by exc handler
Triggered by Thread: 17 (name: ".NET TP Worker")
0 CoreFoundation + 0x224c (CFNumberGetValue + 192)
1 libcoreclr + 0x328bdc
2 libcoreclr + 0x28d9c8
3 libcoreclr + 0x290658
4 libcoreclr + 0x1fbd8c
5 libcoreclr + 0x3275d8
6 libcoreclr + 0x328ab0
7 libcoreclr + 0x28e1c4
8 libcoreclr + 0x292260
9 libcoreclr + 0x1fbd8c
10 libcoreclr + 0x3275d8
11 CFNetwork + 0x1a59ac (PAC::rlsPerform(void*) + 80)
12 CoreFoundation + 0xf92c (__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 28)
...
16 CoreFoundation + 0x11adc (CFRunLoopRunSpecific + 572)
17 libcoreclr + 0x328bdc
... (interpreted MacProxy / SocketsHttpHandler frames on a thread-pool worker)
| Register | Value | Meaning |
|---|---|---|
| 0x | 0x9cfc0aa3eede9a4b | A valid tagged-pointer CFNumber (bit 63 set) |
| 0x1 | 0x0000000200000009 | kCFNumberIntType (9), with stale 0x2 in the upper 32 bits |
| 0x2 | 0x0000000126500858 | &value, on the interpreter stack |
The fault address is exactly the type table plus 2 × x1. The table is at CoreFoundation + 0x21d5b0 (base 0x19db16000), and 0x19dd335b0 + 2 × 0x200000009 = 0x59dd335c2.
The same crash on the iOS simulator with the RC1 iossimulator-arm64 runtime pack gives a symbolicated version of the device stack above, frame for frame. It faults at x1 = 0x100000009 and 0x3805e4312:
CoreFoundation CFNumberGetValue
libcoreclr CallJittedMethodRetI8
libcoreclr InvokeUnmanagedMethodWithTransition
libcoreclr InterpExecMethod
libcoreclr ExecuteInterpretedMethod
libcoreclr InterpreterStubRetVoid
libcoreclr CallJittedMethodRetVoid
libcoreclr InvokeCalliStub
libcoreclr InterpExecMethod
libcoreclr ExecuteInterpretedMethod
libcoreclr InterpreterStubRetVoid
CFNetwork PAC::rlsPerform(void*)
CoreFoundation __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__
Regression?
Yes, compared with .NET 10.
The same app works on the same devices with .NET 10 (Mono, AOT) and with .NET 11 on Android (CoreCLR, JIT).
The declaration bug itself is old. What changed in .NET 11 is that this code now runs on the CoreCLR interpreter, which doesn't zero the upper half of 32-bit arguments. The ABI doesn't require it to.
Known Workarounds
Keep MacProxy out of the request path before any SocketsHttpHandler-based client is created:
// No proxy for SocketsHttpHandler clients.
HttpClient.DefaultProxy = new WebProxy();
// Move IHttpClientFactory clients to HttpClientHandler (NSUrlSessionHandler), which resolves proxies natively.
services.ConfigureHttpClientDefaults(http =>
http.ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler()));
With the first line, SocketsHttpHandler clients and ClientWebSocket ignore the device's proxy and connect directly.
Configuration
- .NET: SDK 11.0.100-rc.1.26425.128 (runtime 11.0.0-rc.1.26425.128).
- Workload set 11.0.100-rc.1.26458.5 (Microsoft.iOS.Sdk.net11.0_26.5 26.5.12193-net11-rc.1).
- MAUI 11.0.0-rc.1.26451.6.
- CoreCLR (the default for net11.0-ios), with the interpreter and composite R2R.
- Built with dotnet publish -f net11.0-ios -p:RuntimeIdentifier=ios-arm64 using Xcode 26.6.
- OS: iOS 18.6 (22G86) on iPhone 16 (iPhone17,3). Also reproduced on the iOS 26.3 simulator with the iossimulator-arm64 11.0.0-rc.1.26425.128 runtime pack.
- Architecture: ARM64.
- Specific to this configuration? Yes. It only happens where System.Net.Http runs on the CoreCLR interpreter. It doesn't reproduce with the JIT (macOS, Android) or Mono AOT (.NET 10).
- Blazor: the app is a MAUI Blazor Hybrid app (BlazorWebView), but Blazor isn't involved. The crash is in SocketsHttpHandler's proxy lookup.
Other information
No response
- 主要言語
- C#
- スター
- 18.3k
- フォーク
- 5.6k
- 平均マージ
- 2日 17時間
- マージ済み PR(30日)
- 615
環境構築
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
dotnet/runtime のほかの issue
-
area-Infrastructure-coreclr os-ios os-maccatalyst os-tvos untriaged
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
dotnet/runtime#134766 · コメント 3 件 ·
メンテナーはふだん 1 日以内に返信
-
area-System.Linq untriaged
難易度 2/5 1〜3時間 初心者へのやさしさ 88/100
dotnet/runtime#134736 · コメント 3 件 ·
メンテナーはふだん 1 日以内に返信
-
area-System.Numerics.Tensors untriaged
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
dotnet/runtime#134691 · コメント 2 件 ·
メンテナーはふだん 1 日以内に返信
-
area-System.Threading blocking-clean-ci Known Build Error untriaged
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
dotnet/runtime#134679 · コメント 4 件 ·
メンテナーはふだん 1 日以内に返信
-
ARM64: conditional compare rejects negative immediates the emitter can already encode as `ccmn`オープンarea-CodeGen-coreclr performance
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
dotnet/runtime#134663 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
似ている issue
-
area-ai untriaged
難易度 2/5 1〜3時間 初心者へのやさしさ 85/100
dotnet/extensions#7790 ·
メンテナーはふだん 1 日以内に返信
-
P2 testing
難易度 1/5 1時間未満 初心者へのやさしさ 90/100
メンテナーはふだん 1 日以内に返信
-
0 - Backlog Bug
難易度 2/5 1〜3時間 初心者へのやさしさ 88/100
BrighterCommand/Brighter#4444 ·
メンテナーはふだん 1 日以内に返信
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 88/100
メンテナーはふだん 1 日以内に返信
-
area:frontend bug FE P3
難易度 2/5 1〜3時間 初心者へのやさしさ 86/100
klasolsson81/jobbliggaren#1915 ·
メンテナーはふだん 1 日以内に返信