Skip to content

[iOS] Fabric: SIGABRT on tab press when tab key contains non-ASCII characters (kCFStringEncodingUTF8 passed to -cStringUsingEncoding:) #560

Description

@nahooni0511

Before submitting a new issue

  • I tested using the latest version of the library, as the bug might be already fixed.
  • I tested using a supported version of react native.
  • I checked for possible duplicate issues, with possible answers.

Bug summary

On the New Architecture (Fabric), pressing (or long-pressing) a tab whose key contains any non-ASCII character — Korean, Japanese, Chinese, Cyrillic, emoji, accented Latin, … — crashes the app instantly with SIGABRT.

RCTTabViewComponentView.mm builds the event payloads like this (L241, L250):

eventEmitter->onPageSelected(RNCTabViewEventEmitter::OnPageSelected{
  .key = [key cStringUsingEncoding:kCFStringEncodingUTF8]
});

The problem: -cStringUsingEncoding: expects an NSStringEncoding (NSUTF8StringEncoding = 4), but the code passes kCFStringEncodingUTF8, which is a CFStringEncoding constant with the value 0x08000100. That value is not a valid NSStringEncoding (converting between the two families requires CFStringConvertEncodingToNSStringEncoding()).

What happens at runtime:

  • For pure-ASCII keys the call happens to return a valid pointer (internal 8-bit buffer fast path), so the bug goes unnoticed in English-only apps.
  • For keys containing non-ASCII characters, the conversion fails and cStringUsingEncoding: returns NULL (its documented behavior when the receiver cannot be converted to the given encoding). The generated OnPageSelected / OnTabLongPress structs declare key as std::string, and constructing a std::string from NULL is undefined behavior → abort().

This affects every app using @bottom-tabs/react-navigation with non-ASCII screen names: react-navigation derives the route key from the screen name (a screen named 메시지 gets a route key like 메시지-AbC12xyz), and that route key is exactly what is passed to onPageSelectedWithKey: / onLongPressWithKey:. Tapping such a tab crashes immediately. Standalone TabView usage with non-ASCII navigationState route keys crashes the same way.

The old architecture is not affected (the whole file is #ifdef RCT_NEW_ARCH_ENABLED).

Library version

1.4.0 (latest release; the code is unchanged on current main — see permalinks above)

Environment info

System:
  OS: macOS 26.6.1
Binaries:
  Node: 22.22.1
npmPackages:
  react: 19.1.0
  react-native: 0.81.5
  expo: ~54.0.0
  react-native-bottom-tabs: 1.4.0
  @bottom-tabs/react-navigation: 1.4.0
  @react-navigation/native: 7.3.14
Settings:
  newArchEnabled: true (Fabric)
Tested on: iPhone Simulator (iOS 26)

Steps to reproduce

  1. Create a React Native 0.81 app with the New Architecture enabled and install react-native-bottom-tabs + @bottom-tabs/react-navigation.
  2. Add a tab screen whose name contains non-ASCII characters, e.g. 메시지 (Korean).
  3. Run the app on iOS and tap that tab (long-press also triggers it via onTabLongPress).
  4. The app aborts immediately — SIGABRT from the std::string constructor being fed NULL in RCTTabViewComponentView.mm.

Reproducible sample code

import { NavigationContainer } from '@react-navigation/native';
import { createNativeBottomTabNavigator } from '@bottom-tabs/react-navigation';
import { Text, View } from 'react-native';

const Tab = createNativeBottomTabNavigator();

const Screen = () => (
  <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
    <Text>Hello</Text>
  </View>
);

export default function App() {
  return (
    <NavigationContainer>
      <Tab.Navigator>
        <Tab.Screen name="Home" component={Screen} />
        {/* Tapping this tab crashes the app on iOS (Fabric): */}
        <Tab.Screen name="메시지" component={Screen} />
      </Tab.Navigator>
    </NavigationContainer>
  );
}

Proposed fix

Use -UTF8String, which returns a proper UTF-8 C string for any NSString contents (with a ?: "" guard for the nil-receiver edge case), at both call sites:

--- a/packages/react-native-bottom-tabs/ios/RCTTabViewComponentView.mm
+++ b/packages/react-native-bottom-tabs/ios/RCTTabViewComponentView.mm
@@ -238,7 +238,7 @@ - (void)onPageSelectedWithKey:(NSString *)key reactTag:(NSNumber *)reactTag {
   auto eventEmitter = std::static_pointer_cast<const RNCTabViewEventEmitter>(_eventEmitter);
   if (eventEmitter) {
     eventEmitter->onPageSelected(RNCTabViewEventEmitter::OnPageSelected{
-      .key = [key cStringUsingEncoding:kCFStringEncodingUTF8]
+      .key = std::string([key UTF8String] ?: "")
     });
   }
 }
@@ -247,7 +247,7 @@ - (void)onLongPressWithKey:(NSString *)key reactTag:(NSNumber *)reactTag {
   auto eventEmitter = std::static_pointer_cast<const RNCTabViewEventEmitter>(_eventEmitter);
   if (eventEmitter) {
     eventEmitter->onTabLongPress(RNCTabViewEventEmitter::OnTabLongPress {
-      .key = [key cStringUsingEncoding:kCFStringEncodingUTF8]
+      .key = std::string([key UTF8String] ?: "")
     });
   }
 }

We are running exactly this as a patch-package patch in production and it fully resolves the crash. Happy to open a PR if you'd like.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions