From 04eee2410df4a85005c9562db13a1fec93d7c2e4 Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 13 Jan 2020 07:51:54 +0000 Subject: [PATCH] Treat plausible but invalid keys (like C-BSpace) as literal like any other unrecognised string passed to send-keys. Reported by Anthony Sottile in GitHub issue 2049. --- cmd-send-keys.c | 14 +++++++++++--- input-keys.c | 17 +++++++++-------- tmux.h | 4 ++-- window.c | 14 ++++++++------ 4 files changed, 30 insertions(+), 19 deletions(-) diff --git a/cmd-send-keys.c b/cmd-send-keys.c index ddbab6f7..cc04a73f 100644 --- a/cmd-send-keys.c +++ b/cmd-send-keys.c @@ -60,6 +60,9 @@ static struct cmdq_item * cmd_send_keys_inject_key(struct client *c, struct cmd_find_state *fs, struct cmdq_item *item, key_code key) { + struct session *s = fs->s; + struct winlink *wl = fs->wl; + struct window_pane *wp = fs->wp; struct window_mode_entry *wme; struct key_table *table; struct key_binding *bd; @@ -68,7 +71,8 @@ cmd_send_keys_inject_key(struct client *c, struct cmd_find_state *fs, if (wme == NULL || wme->mode->key_table == NULL) { if (options_get_number(fs->wp->window->options, "xterm-keys")) key |= KEYC_XTERM; - window_pane_key(fs->wp, item->client, fs->s, fs->wl, key, NULL); + if (window_pane_key(wp, item->client, s, wl, key, NULL) != 0) + return (NULL); return (item); } table = key_bindings_get_table(wme->mode->key_table(wme), 1); @@ -87,6 +91,7 @@ cmd_send_keys_inject_string(struct client *c, struct cmd_find_state *fs, struct cmdq_item *item, struct args *args, int i) { const char *s = args->argv[i]; + struct cmdq_item *new_item; struct utf8_data *ud, *uc; wchar_t wc; key_code key; @@ -104,8 +109,11 @@ cmd_send_keys_inject_string(struct client *c, struct cmd_find_state *fs, literal = args_has(args, 'l'); if (!literal) { key = key_string_lookup_string(s); - if (key != KEYC_NONE && key != KEYC_UNKNOWN) - return (cmd_send_keys_inject_key(c, fs, item, key)); + if (key != KEYC_NONE && key != KEYC_UNKNOWN) { + new_item = cmd_send_keys_inject_key(c, fs, item, key); + if (new_item != NULL) + return (new_item); + } literal = 1; } if (literal) { diff --git a/input-keys.c b/input-keys.c index 01f9ad9d..5c7e8b1f 100644 --- a/input-keys.c +++ b/input-keys.c @@ -150,7 +150,7 @@ input_split2(u_int c, u_char *dst) } /* Translate a key code into an output key sequence. */ -void +int input_key(struct window_pane *wp, key_code key, struct mouse_event *m) { const struct input_key_ent *ike; @@ -167,14 +167,14 @@ input_key(struct window_pane *wp, key_code key, struct mouse_event *m) if (KEYC_IS_MOUSE(key)) { if (m != NULL && m->wp != -1 && (u_int)m->wp == wp->id) input_key_mouse(wp, m); - return; + return (0); } /* Literal keys go as themselves (can't be more than eight bits). */ if (key & KEYC_LITERAL) { ud.data[0] = (u_char)key; bufferevent_write(wp->event, &ud.data[0], 1); - return; + return (0); } /* Is this backspace? */ @@ -195,15 +195,15 @@ input_key(struct window_pane *wp, key_code key, struct mouse_event *m) bufferevent_write(wp->event, "\033", 1); ud.data[0] = justkey; bufferevent_write(wp->event, &ud.data[0], 1); - return; + return (0); } if (justkey > 0x7f && justkey < KEYC_BASE) { if (utf8_split(justkey, &ud) != UTF8_DONE) - return; + return (-1); if (key & KEYC_ESCAPE) bufferevent_write(wp->event, "\033", 1); bufferevent_write(wp->event, ud.data, ud.size); - return; + return (0); } /* @@ -214,7 +214,7 @@ input_key(struct window_pane *wp, key_code key, struct mouse_event *m) if ((out = xterm_keys_lookup(key)) != NULL) { bufferevent_write(wp->event, out, strlen(out)); free(out); - return; + return (0); } } key &= ~KEYC_XTERM; @@ -237,7 +237,7 @@ input_key(struct window_pane *wp, key_code key, struct mouse_event *m) } if (i == nitems(input_keys)) { log_debug("key 0x%llx missing", key); - return; + return (-1); } dlen = strlen(ike->data); log_debug("found key 0x%llx: \"%s\"", key, ike->data); @@ -246,6 +246,7 @@ input_key(struct window_pane *wp, key_code key, struct mouse_event *m) if (key & KEYC_ESCAPE) bufferevent_write(wp->event, "\033", 1); bufferevent_write(wp->event, ike->data, dlen); + return (0); } /* Translate mouse and output. */ diff --git a/tmux.h b/tmux.h index 7c7dcc99..75e483c5 100644 --- a/tmux.h +++ b/tmux.h @@ -2275,7 +2275,7 @@ void input_parse(struct window_pane *); void input_parse_buffer(struct window_pane *, u_char *, size_t); /* input-key.c */ -void input_key(struct window_pane *, key_code, struct mouse_event *); +int input_key(struct window_pane *, key_code, struct mouse_event *); /* xterm-keys.c */ char *xterm_keys_lookup(key_code); @@ -2498,7 +2498,7 @@ int window_pane_set_mode(struct window_pane *, struct args *); void window_pane_reset_mode(struct window_pane *); void window_pane_reset_mode_all(struct window_pane *); -void window_pane_key(struct window_pane *, struct client *, +int window_pane_key(struct window_pane *, struct client *, struct session *, struct winlink *, key_code, struct mouse_event *); int window_pane_visible(struct window_pane *); diff --git a/window.c b/window.c index 64c95855..bd25b5d1 100644 --- a/window.c +++ b/window.c @@ -1229,7 +1229,7 @@ window_pane_reset_mode_all(struct window_pane *wp) window_pane_reset_mode(wp); } -void +int window_pane_key(struct window_pane *wp, struct client *c, struct session *s, struct winlink *wl, key_code key, struct mouse_event *m) { @@ -1237,23 +1237,24 @@ window_pane_key(struct window_pane *wp, struct client *c, struct session *s, struct window_pane *wp2; if (KEYC_IS_MOUSE(key) && m == NULL) - return; + return (-1); wme = TAILQ_FIRST(&wp->modes); if (wme != NULL) { wp->modelast = time(NULL); if (wme->mode->key != NULL) wme->mode->key(wme, c, s, wl, (key & ~KEYC_XTERM), m); - return; + return (0); } if (wp->fd == -1 || wp->flags & PANE_INPUTOFF) - return; + return (0); - input_key(wp, key, m); + if (input_key(wp, key, m) != 0) + return (-1); if (KEYC_IS_MOUSE(key)) - return; + return (0); if (options_get_number(wp->window->options, "synchronize-panes")) { TAILQ_FOREACH(wp2, &wp->window->panes, entry) { if (wp2 != wp && @@ -1264,6 +1265,7 @@ window_pane_key(struct window_pane *wp, struct client *c, struct session *s, input_key(wp2, key, NULL); } } + return (0); } int