From 8d77a37fa26b1570b807c91e257fd11e80473ba5 Mon Sep 17 00:00:00 2001 From: mudbungie Date: Sun, 23 Aug 2026 19:44:01 -0700 Subject: [PATCH] game-activity: tolerate the NULL pre-IME GameTextInput buffer GameTextInput's initial state, delivered before the IME has attached, carries a NULL text pointer with length 0. The conversion callback fed it straight to slice::from_raw_parts, which requires a non-null pointer even for an empty slice: undefined behavior in release builds, and under debug_assertions the standard library's precondition check aborts the process (a non-unwinding panic inside an extern "C" callback) on the first frame of every debug build using the game-activity backend. Treat the NULL buffer as the empty text it represents. --- android-activity/src/game_activity/mod.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/android-activity/src/game_activity/mod.rs b/android-activity/src/game_activity/mod.rs index 6233335..ba08c50 100644 --- a/android-activity/src/game_activity/mod.rs +++ b/android-activity/src/game_activity/mod.rs @@ -713,8 +713,18 @@ impl AndroidAppInner { // Java uses a modified UTF-8 format, which is a modified cesu8 format let out_ptr: *mut TextInputState = context.cast(); let text_modified_utf8: *const u8 = (*state).text_UTF8.cast(); - let text_modified_utf8 = - std::slice::from_raw_parts(text_modified_utf8, (*state).text_length as usize); + // Before the IME has attached, GameTextInput hands us its initial + // state with a NULL text buffer (and length 0). `from_raw_parts` + // requires a non-null pointer even for empty slices, so feeding it + // NULL is UB — and under `debug_assertions` the standard library's + // precondition check turns it into an immediate abort (a + // non-unwinding panic inside an `extern "C"` callback) on the first + // frame of every debug build. + let text_modified_utf8 = if text_modified_utf8.is_null() { + &[] + } else { + std::slice::from_raw_parts(text_modified_utf8, (*state).text_length as usize) + }; match simd_cesu8::mutf8::decode(text_modified_utf8) { Ok(str) => { let len = str.len();