Skip to content

Commit cca590c

Browse files
committed
Fix a use-after-free introduced in the recent key handling refactor
1 parent 863fff8 commit cca590c

File tree

1 file changed

+20
-2
lines changed

1 file changed

+20
-2
lines changed

kitty/keys.c

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,16 @@ update_ime_position(OSWindow *os_window, Window* w, Screen *screen) {
8888
glfwUpdateIMEState(global_state.callback_os_window->handle, 2, left, top, cell_width, cell_height);
8989
}
9090

91+
static inline Window*
92+
window_for_id(id_type window_id) {
93+
Tab *t = global_state.callback_os_window->tabs + global_state.callback_os_window->active_tab;
94+
for (unsigned int i = 0; i < t->num_windows; i++) {
95+
Window *w = t->windows + i;
96+
if (w->id == window_id) return w;
97+
}
98+
return NULL;
99+
}
100+
91101
void
92102
on_key_input(GLFWkeyevent *ev) {
93103
Window *w = active_window();
@@ -102,6 +112,8 @@ on_key_input(GLFWkeyevent *ev) {
102112
if (!w) { debug("no active window, ignoring\n"); return; }
103113
if (OPT(mouse_hide_wait) < 0 && !is_modifier_key(key)) hide_mouse(global_state.callback_os_window);
104114
Screen *screen = w->render_data.screen;
115+
id_type active_window_id = w->id;
116+
105117
switch(ev->ime_state) {
106118
case 1: // update pre-edit text
107119
update_ime_position(global_state.callback_os_window, w, screen);
@@ -133,28 +145,34 @@ on_key_input(GLFWkeyevent *ev) {
133145
if (
134146
action != GLFW_RELEASE && !is_modifier_key(key)
135147
) {
148+
w->last_special_key_pressed = key;
136149
create_key_event();
137150
call_boss(process_sequence, "O", ke);
138151
Py_CLEAR(ke);
139152
}
140153
return;
141154
}
155+
142156
if (action == GLFW_PRESS || action == GLFW_REPEAT) {
143157
create_key_event();
144158
PyObject *ret = PyObject_CallMethod(global_state.boss, "dispatch_possible_special_key", "O", ke);
145159
Py_CLEAR(ke);
146160
bool consumed = false;
147-
w->last_special_key_pressed = 0;
161+
// the shortcut could have created a new window or closed the window, rendering the pointer
162+
// no longer valid
163+
w = window_for_id(active_window_id);
164+
if (w) w->last_special_key_pressed = 0;
148165
if (ret == NULL) { PyErr_Print(); }
149166
else {
150167
consumed = ret == Py_True;
151168
Py_DECREF(ret);
152169
if (consumed) {
153170
debug("handled as shortcut\n");
154-
w->last_special_key_pressed = key;
171+
if (w) w->last_special_key_pressed = key;
155172
return;
156173
}
157174
}
175+
if (!w) return;
158176
} else if (w->last_special_key_pressed == key) {
159177
w->last_special_key_pressed = 0;
160178
debug("ignoring release event for previous press that was handled as shortcut");

0 commit comments

Comments
 (0)