From 0f81598e9f5336a7169f8a6c0c6ce075c7c1c168 Mon Sep 17 00:00:00 2001 From: Chris Collins Date: Thu, 8 Feb 2024 16:06:12 +1100 Subject: [PATCH] Wayland: Avoid SEGV if a modifier notification comes before the keymap --- src/video/wayland/SDL_waylandevents.c | 28 +++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c index e0b44084d..b85c35919 100644 --- a/src/video/wayland/SDL_waylandevents.c +++ b/src/video/wayland/SDL_waylandevents.c @@ -1146,6 +1146,13 @@ static void keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard, return; } + if (input->xkb.keymap != NULL) { + /* if there's already a keymap loaded, throw it away rather than leaking it before + * parsing the new one + */ + WAYLAND_xkb_keymap_unref(input->xkb.keymap); + input->xkb.keymap = NULL; + } input->xkb.keymap = WAYLAND_xkb_keymap_new_from_string(input->display->xkb_context, map_str, XKB_KEYMAP_FORMAT_TEXT_V1, @@ -1169,6 +1176,13 @@ static void keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard, input->xkb.idx_caps = 1 << GET_MOD_INDEX(CAPS); #undef GET_MOD_INDEX + if (input->xkb.state != NULL) { + /* if there's already a state, throw it away rather than leaking it before + * trying to create a new one with the new keymap. + */ + WAYLAND_xkb_state_unref(input->xkb.state); + input->xkb.state = NULL; + } input->xkb.state = WAYLAND_xkb_state_new(input->xkb.keymap); if (!input->xkb.state) { SDL_SetError("failed to create XKB state\n"); @@ -1214,10 +1228,18 @@ static void keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard, } /* Set up XKB compose table */ + if (input->xkb.compose_table != NULL) { + WAYLAND_xkb_compose_table_unref(input->xkb.compose_table); + input->xkb.compose_table = NULL; + } input->xkb.compose_table = WAYLAND_xkb_compose_table_new_from_locale(input->display->xkb_context, locale, XKB_COMPOSE_COMPILE_NO_FLAGS); if (input->xkb.compose_table) { /* Set up XKB compose state */ + if (input->xkb.compose_state != NULL) { + WAYLAND_xkb_compose_state_unref(input->xkb.compose_state); + input->xkb.compose_state = NULL; + } input->xkb.compose_state = WAYLAND_xkb_compose_state_new(input->xkb.compose_table, XKB_COMPOSE_STATE_NO_FLAGS); if (!input->xkb.compose_state) { @@ -1607,6 +1629,12 @@ static void keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard, struct SDL_WaylandInput *input = data; Wayland_Keymap keymap; + if (input->xkb.state == NULL) { + /* if we get a modifier notification before the keymap, there's nothing we can do with the information + */ + return; + } + WAYLAND_xkb_state_update_mask(input->xkb.state, mods_depressed, mods_latched, mods_locked, 0, 0, group);