-
Notifications
You must be signed in to change notification settings - Fork 752
[iOS 26] Systematic EXC_BAD_ACCESS (KERN_PROTECTION_FAILURE) crash on physical devices — PAC pointer authentication incompatibility #1966
Description
Hi Hermes team,
Thank you for your work on Hermes. We're reporting a critical issue affecting all React Native / Expo apps on physical iOS 26 devices. We hope this detailed report helps identify and prioritize a fix.
[iOS 26] Systematic crash on physical devices — PAC pointer authentication incompatibility
Bug Description
Hermes crashes systematically (100% reproduction rate) on every physical iOS 26 device at app launch. The crash signature points to ARM64 Pointer Authentication Codes (PAC) enforcement that iOS 26 has hardened on physical hardware.
This is NOT intermittent. Every cold start on a physical iOS 26 device crashes. Simulators work fine (no PAC hardware enforcement in emulation).
Crash signature:
Exception Type: EXC_BAD_ACCESS (SIGBUS / SIGSEGV)
Exception Subtype: KERN_PROTECTION_FAILURE
Thread: com.facebook.react.runtime.JavaScript
0 hermesvm JSObject::getNamedDescriptorUnsafe(...)
1 hermesvm HiddenClass::findProperty(...)
The KERN_PROTECTION_FAILURE subtype (as opposed to KERN_INVALID_ADDRESS seen in #1896) is the specific kernel signal for PAC validation failure — the CPU detected an unsigned or incorrectly signed pointer being dereferenced.
Root Cause Analysis
iOS 26 hardened PAC (Pointer Authentication Codes, ARMv8.3 / arm64e) enforcement on physical devices. PAC cryptographically signs pointers and verifies them before use. Unsigned or manipulated pointers now cause an immediate KERN_PROTECTION_FAILURE crash.
Hermes performs raw pointer arithmetic in its VM internals — particularly in the HiddenClass property lookup chain (HiddenClass::findProperty -> JSObject::getNamedDescriptorUnsafe). These operations (pointer casting, offset arithmetic, vtable dispatch) invalidate PAC signatures, causing the CPU to reject the pointer on dereference.
Why simulators are unaffected: iOS simulators run on x86_64 or emulated arm64 without hardware PAC enforcement. The crash only manifests on physical ARM64 devices running iOS 26+.
All Configurations Tested
We exhaustively tested every viable combination:
| Configuration | Hermes | Architecture | Result |
|---|---|---|---|
| Expo SDK 55 + RN 0.83 | V2 (0.14.1, default) | New Arch | CRASH |
| Expo SDK 55 + RN 0.83 | V1 (override 0.10) | Old Arch | CRASH |
| Expo SDK 55 + RN 0.83 | V1 | Old Arch + minimal JS layout | OK (too little JS to trigger) |
| Expo SDK 55 + RN 0.83 | V2 | New Arch + UI framework | CRASH |
| Expo SDK 54 + JSC | N/A | Old Arch | BUILD FAIL (Reanimated/Worklets require Hermes) |
| Build from source (RCT_BUILD_HERMES_FROM_SOURCE) | V2 | New Arch | BUILD FAIL (glog config.h) |
Key observation: A minimal JS layout (near-empty app) does not crash — the crash requires enough JS object property lookups to trigger the HiddenClass chain traversal. This confirms it is the pointer arithmetic in HiddenClass/property resolution, not initialization code.
Steps To Reproduce
- Create any non-trivial Expo/React Native app (more than a blank screen — needs object property access patterns)
- Build for iOS with Hermes enabled (default)
- Deploy to a physical iPhone running iOS 26+ (tested: iPhone 13 mini, iOS 26.3.1)
- Launch the app -> immediate crash within ~200ms
Simulator: Works fine on any iOS 26 simulator (no PAC enforcement)
Device: 100% crash rate on physical iOS 26 device
Note: We are preparing a minimal reproduction repository and a full Xcode crash report (with register state and ESR). We will attach them in a follow-up comment shortly.
Environment
| Field | Value |
|---|---|
| Hermes versions tested | V1 (0.10.x) and V2 (0.14.1) |
| React Native versions tested | 0.81.5, 0.83.x |
| Expo SDK versions tested | 54, 55 |
| iOS version | 26.3.1 |
| Device | iPhone 13 mini (arm64) |
| Platform | arm64 physical device |
| Xcode | 26.x |
| macOS | 26.x |
Impact
This is a complete blocker for any React Native / Expo app targeting physical iOS 26 devices. There is no configuration workaround — both Hermes V1 and V2, Old and New Architecture, all crash. JSC is not a viable fallback due to ecosystem dependencies requiring Hermes.
As iOS 26 adoption grows, this will affect every React Native app in production.
Suggested Fix Direction
Hermes VM internals may need to be compiled with PAC support and use Apple pointer authentication intrinsics (ptrauth_sign_unauthenticated, ptrauth_auth_data, etc.) or LLVM __ptrauth qualifiers for pointer operations in:
- HiddenClass property chain traversal
- JSObject named descriptor lookups
- GC pointer scanning and handle management
- Any vtable or function pointer dispatch
Related Issues
- [iOS] Crash in HiddenClass::addProperty during runtime initialization (bindNativePerformanceNow) #1896 — Similar crash location (HiddenClass::addProperty) but intermittent on iOS 18, different exception subtype (KERN_INVALID_ADDRESS = null pointer, not PAC)
- [iOS 26] App crashes on startup with TurboModule performVoidMethodInvocation - SIGABRT react-native#54859 — TurboModule SIGABRT on iOS 26 (different crash, exception handling issue)
- Getting Crash In Ios Device react-native#55337 — HiddenClass::addProperty crash on iOS device (similar area, but attributed to NSException bridging)
These are distinct issues. Our crash is deterministic, PAC-specific (KERN_PROTECTION_FAILURE), and affects all non-trivial apps on physical iOS 26 hardware.
Thank you for looking into this. We understand this may require significant changes in the VM internals. We're happy to provide any additional information, test builds, or help validate fixes on our physical iOS 26 devices.