From cae229cadc28d578e20942c7e964741ad71aba15 Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 5 May 2026 12:02:12 +0000 Subject: [PATCH 1/3] Discard queued data and clear offsets when turning pane off to prevent later read of data that has been removed. From Aaron Campbell in GitHub issue 5054. --- control.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/control.c b/control.c index f7fb761c..4a7201ef 100644 --- a/control.c +++ b/control.c @@ -356,6 +356,9 @@ control_set_pane_off(struct client *c, struct window_pane *wp) struct control_pane *cp; cp = control_add_pane(c, wp); + control_discard_pane(c, cp); + memcpy(&cp->offset, &wp->offset, sizeof cp->offset); + memcpy(&cp->queued, &wp->offset, sizeof cp->queued); cp->flags |= CONTROL_PANE_OFF; } From 1fbd00e1e8fbbedf0e1adb72bc8503ed8a7d1901 Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 5 May 2026 12:06:52 +0000 Subject: [PATCH 2/3] Add missing flags to screen_mode_to_string and do not write before before if any are missed, second bit from qingliu at alauda dot io. --- screen.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/screen.c b/screen.c index 18f4d519..b257f695 100644 --- a/screen.c +++ b/screen.c @@ -751,6 +751,8 @@ screen_mode_to_string(int mode) strlcat(tmp, "CURSOR_BLINKING,", sizeof tmp); if (mode & MODE_CURSOR_VERY_VISIBLE) strlcat(tmp, "CURSOR_VERY_VISIBLE,", sizeof tmp); + if (mode & MODE_CURSOR_BLINKING_SET) + strlcat(tmp, "CURSOR_BLINKING_SET,", sizeof tmp); if (mode & MODE_MOUSE_UTF8) strlcat(tmp, "MOUSE_UTF8,", sizeof tmp); if (mode & MODE_MOUSE_SGR) @@ -771,7 +773,10 @@ screen_mode_to_string(int mode) strlcat(tmp, "KEYS_EXTENDED_2,", sizeof tmp); if (mode & MODE_THEME_UPDATES) strlcat(tmp, "THEME_UPDATES,", sizeof tmp); - tmp[strlen(tmp) - 1] = '\0'; + if (mode & MODE_SYNC) + strlcat(tmp, "SYNC,", sizeof tmp); + if (*tmp != '\0') + tmp[strlen(tmp) - 1] = '\0'; return (tmp); } From 518fcf7e0371d07d83e0a79df6db9780855eb6b3 Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 5 May 2026 13:18:46 +0000 Subject: [PATCH 3/3] Do not sanitize title when popping it from stack, also add a limit to number of pushed titles. --- screen.c | 18 +++++++++++++++--- tmux.h | 1 + 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/screen.c b/screen.c index b257f695..3d9ead65 100644 --- a/screen.c +++ b/screen.c @@ -264,6 +264,16 @@ screen_push_title(struct screen *s) { struct screen_title_entry *title_entry; + log_debug("%s: %u", __func__, s->ntitles); + + while (s->ntitles >= 10) { + title_entry = TAILQ_LAST(s->titles, screen_titles); + free(title_entry->text); + TAILQ_REMOVE(s->titles, title_entry, entry); + free(title_entry); + s->ntitles--; + } + if (s->titles == NULL) { s->titles = xmalloc(sizeof *s->titles); TAILQ_INIT(s->titles); @@ -271,6 +281,7 @@ screen_push_title(struct screen *s) title_entry = xmalloc(sizeof *title_entry); title_entry->text = xstrdup(s->title); TAILQ_INSERT_HEAD(s->titles, title_entry, entry); + s->ntitles++; } /* @@ -284,14 +295,15 @@ screen_pop_title(struct screen *s) if (s->titles == NULL) return; + log_debug("%s: %u", __func__, s->ntitles); title_entry = TAILQ_FIRST(s->titles); if (title_entry != NULL) { - screen_set_title(s, title_entry->text); - + free(s->title); + s->title = title_entry->text; TAILQ_REMOVE(s->titles, title_entry, entry); - free(title_entry->text); free(title_entry); + s->ntitles--; } } diff --git a/tmux.h b/tmux.h index 93596a08..6fd51150 100644 --- a/tmux.h +++ b/tmux.h @@ -979,6 +979,7 @@ struct screen { char *title; char *path; struct screen_titles *titles; + u_int ntitles; struct grid *grid; /* grid data */