game-activity: tolerate the NULL pre-IME GameTextInput buffer - #252
game-activity: tolerate the NULL pre-IME GameTextInput buffer#252mudbungie wants to merge 1 commit into
Conversation
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.
|
Hit this independently this week... Bevy 0.19, android-activity 0.6.1 (game-activity backend), Android 15, debug build. Different shape from the report above: I only poll text_input_state() while the name-entry dialog is open, so it didn't die on the first frame. The first poll happened when the dialog Unrelated, but a trap that made this one a pain to find: my panic hook calls internal_data_path(), which re-takes the app mutex the callback is already holding, so instead of the abort we got a frozen app and nothing in logcat. Took a native stack to figure out what was going on. Nothing to do with this PR. If anyone hits this before the PR lands: push an empty TextInputState once at startup. After setStateInner runs the pointer is never null again, so one early push closes the race. +1, the guard looks right to me. |
The defect
GameTextInputdelivers its initial state — before the IME has attached —with a NULL
text_UTF8pointer andtext_length == 0.map_input_state_to_text_event_callbackfeeds that pointer straight tostd::slice::from_raw_parts, whose contract requires a non-null pointereven for a zero-length slice. That is undefined behavior in release builds,
and under
debug_assertionsthe standard library's precondition checkfires: a non-unwinding panic inside an
extern "C"callback, i.e. animmediate abort.
Observed
Every debug build of a
game-activity-backend app closes on its firstframe (observed with android-activity 0.6.1 + androidx games-activity
4.4.0, egui/winit app, current-generation Pixel, SDK 35). The tombstone
points at the stdlib's
from_raw_partsprecondition inside the callback.Release builds compile the check out and happen to survive the len-0 read,
which makes the failure look like a debug-only mystery rather than what it
is — UB reached on every launch.
The fix
Treat the NULL buffer as the empty text it represents before constructing
the slice. One guard, no behavior change for any non-null buffer.