Skip to content

Commit 123746a

Browse files
committed
guard seat_get_focus() NULL dereferences
seat_get_focus() can return NULL when the focus stack is empty. a few call sites don't check for this and just dereference the result, which crashes sway. this happens when a client disconnects abruptly, leaving the seat with a stale has_focus flag or empty focus stack. whatever touches focus next dereferences NULL. the two confirmed crash sites were seat_set_workspace_focus and seat_set_focus_surface (coredumps below). seat_unfocus_unless_client has the same pattern so a check was added there too for safety. coredumps: #0 seat_send_unfocus () #1 seat_set_workspace_focus () #2 seat_set_focus () #3 wl_signal_emit_mutable () #4 container_begin_destroy () #5 view_unmap () #6 handle_unmap () #0 seat_send_unfocus () #1 seat_set_workspace_focus () #2 seat_set_focus () #3 handle_button () #0 seat_send_unfocus () #1 seat_set_workspace_focus () #2 seat_set_focus () #3 workspace_switch () #4 cmd_workspace () #5 execute_command () #6 ipc_client_handle_command () #0 seat_send_unfocus () #1 seat_set_focus_surface () #2 seat_set_focus_layer () #3 handle_node_destroy ()
1 parent c57daaf commit 123746a

1 file changed

Lines changed: 9 additions & 5 deletions

File tree

sway/input/seat.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1136,10 +1136,12 @@ static void seat_set_workspace_focus(struct sway_seat *seat, struct sway_node *n
11361136

11371137
if (node == NULL) {
11381138
// Close any popups on the old focus
1139-
if (node_is_view(last_focus)) {
1140-
view_close_popups(last_focus->sway_container->view);
1139+
if (last_focus) {
1140+
if (node_is_view(last_focus)) {
1141+
view_close_popups(last_focus->sway_container->view);
1142+
}
1143+
seat_send_unfocus(last_focus, seat);
11411144
}
1142-
seat_send_unfocus(last_focus, seat);
11431145
sway_input_method_relay_set_focus(&seat->im_relay, NULL);
11441146
seat->has_focus = false;
11451147
return;
@@ -1291,7 +1293,9 @@ void seat_set_focus_surface(struct sway_seat *seat,
12911293
struct wlr_surface *surface, bool unfocus) {
12921294
if (seat->has_focus && unfocus) {
12931295
struct sway_node *focus = seat_get_focus(seat);
1294-
seat_send_unfocus(focus, seat);
1296+
if (focus) {
1297+
seat_send_unfocus(focus, seat);
1298+
}
12951299
seat->has_focus = false;
12961300
}
12971301

@@ -1340,7 +1344,7 @@ void seat_unfocus_unless_client(struct sway_seat *seat, struct wl_client *client
13401344
}
13411345
if (seat->has_focus) {
13421346
struct sway_node *focus = seat_get_focus(seat);
1343-
if (node_is_view(focus) && wl_resource_get_client(
1347+
if (focus && node_is_view(focus) && wl_resource_get_client(
13441348
focus->sway_container->view->surface->resource) != client) {
13451349
seat_set_focus(seat, NULL);
13461350
}

0 commit comments

Comments
 (0)