From 8c7278b53ae71a9cbd2acfc9e98d573c61a00620 Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 23 Feb 2026 08:50:00 +0000 Subject: [PATCH 1/5] Memory leaks in cmd_display_menu, from Huihui Huang. --- cmd-display-menu.c | 34 ++++++++++++++++++---------------- menu.c | 3 +++ 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/cmd-display-menu.c b/cmd-display-menu.c index fc9a99b6..9d02dca3 100644 --- a/cmd-display-menu.c +++ b/cmd-display-menu.c @@ -295,7 +295,7 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item) const char *border_style = args_get(args, 'S'); const char *selected_style = args_get(args, 'H'); enum box_lines lines = BOX_LINES_DEFAULT; - char *title, *cause; + char *title, *cause = NULL; int flags = 0, starting_choice = 0; u_int px, py, i, count = args_count(args); struct options *o = target->s->curw->window->options; @@ -313,8 +313,7 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item) &cause); if (cause != NULL) { cmdq_error(item, "starting choice %s", cause); - free(cause); - return (CMD_RETURN_ERROR); + goto fail; } } } @@ -335,8 +334,7 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item) if (count - i < 2) { cmdq_error(item, "not enough arguments"); - menu_free(menu); - return (CMD_RETURN_ERROR); + goto fail; } key = args_string(args, i++); @@ -348,17 +346,13 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item) } if (menu == NULL) { cmdq_error(item, "invalid menu arguments"); - return (CMD_RETURN_ERROR); - } - if (menu->count == 0) { - menu_free(menu); - return (CMD_RETURN_NORMAL); + goto fail; } + if (menu->count == 0) + goto out; if (!cmd_display_menu_get_pos(tc, item, args, &px, &py, menu->width + 4, - menu->count + 2)) { - menu_free(menu); - return (CMD_RETURN_NORMAL); - } + menu->count + 2)) + goto out; value = args_get(args, 'b'); if (value != NULL) { @@ -367,8 +361,7 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item) &cause); if (lines == -1) { cmdq_error(item, "menu-border-lines %s", cause); - free(cause); - return (CMD_RETURN_ERROR); + goto fail; } } @@ -380,6 +373,15 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item) style, selected_style, border_style, target, NULL, NULL) != 0) return (CMD_RETURN_NORMAL); return (CMD_RETURN_WAIT); + +out: + menu_free(menu); + return (CMD_RETURN_NORMAL); + +fail: + free(cause); + menu_free(menu); + return (CMD_RETURN_ERROR); } static enum cmd_retval diff --git a/menu.c b/menu.c index c458e68b..e4f79dec 100644 --- a/menu.c +++ b/menu.c @@ -161,6 +161,9 @@ menu_free(struct menu *menu) { u_int i; + if (menu == NULL) + return; + for (i = 0; i < menu->count; i++) { free((void *)menu->items[i].name); free((void *)menu->items[i].command); From a76e6eca6bc03858dd51f24cbfe6f672d3a980ef Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 23 Feb 2026 08:54:56 +0000 Subject: [PATCH 2/5] Another memory leak from Huihui Huang. --- cmd-server-access.c | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd-server-access.c b/cmd-server-access.c index b2b718b8..43cf4d5f 100644 --- a/cmd-server-access.c +++ b/cmd-server-access.c @@ -90,6 +90,7 @@ cmd_server_access_exec(struct cmd *self, struct cmdq_item *item) pw = getpwnam(name); if (pw == NULL) { cmdq_error(item, "unknown user: %s", name); + free(name); return (CMD_RETURN_ERROR); } free(name); From 0dc1b5adfbf60025e940ced3983d097150ce0d83 Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 23 Feb 2026 08:58:40 +0000 Subject: [PATCH 3/5] Do not leak list on failure, reported by Huihui Huang. --- status.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/status.c b/status.c index edbb04ad..87d5e017 100644 --- a/status.c +++ b/status.c @@ -1890,7 +1890,7 @@ status_prompt_complete_window_menu(struct client *c, struct session *s, struct winlink *wl; char **list = NULL, *tmp; u_int lines = status_line_size(c), height; - u_int py, size = 0; + u_int py, size = 0, i; if (c->tty.sy - lines < 3) return (NULL); @@ -1969,6 +1969,9 @@ status_prompt_complete_window_menu(struct client *c, struct session *s, BOX_LINES_DEFAULT, NULL, NULL, NULL, NULL, status_prompt_menu_callback, spm) != 0) { menu_free(menu); + for (i = 0; i < size; i++) + free(list[i]); + free(list); free(spm); return (NULL); } From 0cc4f0fd76183324ba33d2bff1405210c1b92ac3 Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 23 Feb 2026 09:08:07 +0000 Subject: [PATCH 4/5] Use buffer size for b64_pton, from someone in GitHub issue 4882. --- tty-keys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tty-keys.c b/tty-keys.c index 7f9e8352..8fc51174 100644 --- a/tty-keys.c +++ b/tty-keys.c @@ -1389,7 +1389,7 @@ tty_keys_clipboard(struct tty *tty, const char *buf, size_t len, size_t *size) return (0); } out = xmalloc(needed); - if ((outlen = b64_pton(copy, out, len)) == -1) { + if ((outlen = b64_pton(copy, out, needed)) == -1) { free(out); free(copy); return (0); From f1f9c63cdb4d675d752e2eb3cb520a8fe43f3632 Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 23 Feb 2026 09:12:57 +0000 Subject: [PATCH 5/5] Free history entries properly, from Huihui Huang in GitHub issue 4870. --- cmd-show-prompt-history.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cmd-show-prompt-history.c b/cmd-show-prompt-history.c index 1b95bcaf..5b88499c 100644 --- a/cmd-show-prompt-history.c +++ b/cmd-show-prompt-history.c @@ -60,6 +60,9 @@ cmd_show_prompt_history_exec(struct cmd *self, struct cmdq_item *item) if (cmd_get_entry(self) == &cmd_clear_prompt_history_entry) { if (typestr == NULL) { for (tidx = 0; tidx < PROMPT_NTYPES; tidx++) { + for (hidx = 0; hidx < status_prompt_hsize[tidx]; + hidx++) + free(status_prompt_hlist[tidx][hidx]); free(status_prompt_hlist[tidx]); status_prompt_hlist[tidx] = NULL; status_prompt_hsize[tidx] = 0; @@ -70,6 +73,8 @@ cmd_show_prompt_history_exec(struct cmd *self, struct cmdq_item *item) cmdq_error(item, "invalid type: %s", typestr); return (CMD_RETURN_ERROR); } + for (hidx = 0; hidx < status_prompt_hsize[type]; hidx++) + free(status_prompt_hlist[type][hidx]); free(status_prompt_hlist[type]); status_prompt_hlist[type] = NULL; status_prompt_hsize[type] = 0;