1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
From 5363a5475a1dd4158c1ddb23de2da34e88738673 Mon Sep 17 00:00:00 2001
From: Romain Francoise <romain@rfr.io>
Date: Sun, 25 Feb 2024 15:53:25 +0100
Subject: [PATCH] Don't notify when unzooming windows from window_destroy()
Since commit 36e1ac65560, window_destroy() calls window_unzoom()
but the latter emits a 'window-layout-changed' notification with
the window which is about to be freed. This results in the
callback later dereferencing a freed window, or a double-free.
Closes: #3857.
---
cmd-display-panes.c | 2 +-
cmd-resize-pane.c | 2 +-
popup.c | 2 +-
resize.c | 2 +-
server-fn.c | 2 +-
tmux.h | 2 +-
window.c | 10 ++++++----
7 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/cmd-display-panes.c b/cmd-display-panes.c
index 06f6dc277a..25556f3d58 100644
--- a/cmd-display-panes.c
+++ b/cmd-display-panes.c
@@ -246,7 +246,7 @@ cmd_display_panes_key(struct client *c, void *data, struct key_event *event)
wp = window_pane_at_index(w, index);
if (wp == NULL)
return (1);
- window_unzoom(w);
+ window_unzoom(w, 1);
xasprintf(&expanded, "%%%u", wp->id);
diff --git a/cmd-resize-pane.c b/cmd-resize-pane.c
index c9439441f6..b2c167f59f 100644
--- a/cmd-resize-pane.c
+++ b/cmd-resize-pane.c
@@ -87,7 +87,7 @@ cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
if (args_has(args, 'Z')) {
if (w->flags & WINDOW_ZOOMED)
- window_unzoom(w);
+ window_unzoom(w, 1);
else
window_zoom(wp);
server_redraw_window(w);
diff --git a/popup.c b/popup.c
index 4742733932..01b95e27b8 100644
--- a/popup.c
+++ b/popup.c
@@ -345,7 +345,7 @@ popup_make_pane(struct popup_data *pd, enum layout_type type)
u_int hlimit;
const char *shell;
- window_unzoom(w);
+ window_unzoom(w, 1);
lc = layout_split_pane(wp, type, -1, 0);
hlimit = options_get_number(s->options, "history-limit");
diff --git a/resize.c b/resize.c
index 457fee0a7b..dff9571270 100644
--- a/resize.c
+++ b/resize.c
@@ -40,7 +40,7 @@ resize_window(struct window *w, u_int sx, u_int sy, int xpixel, int ypixel)
/* If the window is zoomed, unzoom. */
zoomed = w->flags & WINDOW_ZOOMED;
if (zoomed)
- window_unzoom(w);
+ window_unzoom(w, 1);
/* Resize the layout first. */
layout_resize(w, sx, sy);
diff --git a/server-fn.c b/server-fn.c
index 2f649329cb..00d0e37843 100644
--- a/server-fn.c
+++ b/server-fn.c
@@ -488,6 +488,6 @@ server_check_unattached(void)
void
server_unzoom_window(struct window *w)
{
- if (window_unzoom(w) == 0)
+ if (window_unzoom(w, 1) == 0)
server_redraw_window(w);
}
diff --git a/tmux.h b/tmux.h
index a50adbfae0..7671cca097 100644
--- a/tmux.h
+++ b/tmux.h
@@ -3070,7 +3070,7 @@ struct window_pane *window_add_pane(struct window *, struct window_pane *,
void window_resize(struct window *, u_int, u_int, int, int);
void window_pane_send_resize(struct window_pane *, u_int, u_int);
int window_zoom(struct window_pane *);
-int window_unzoom(struct window *);
+int window_unzoom(struct window *, int);
int window_push_zoom(struct window *, int, int);
int window_pop_zoom(struct window *);
void window_lost_pane(struct window *, struct window_pane *);
diff --git a/window.c b/window.c
index 77ce41d8f7..69a42ab7e6 100644
--- a/window.c
+++ b/window.c
@@ -338,7 +338,7 @@ window_destroy(struct window *w)
{
log_debug("window @%u destroyed (%d references)", w->id, w->references);
- window_unzoom(w);
+ window_unzoom(w, 0);
RB_REMOVE(windows, &windows, w);
if (w->layout_root != NULL)
@@ -673,7 +673,7 @@ window_zoom(struct window_pane *wp)
}
int
-window_unzoom(struct window *w)
+window_unzoom(struct window *w, int notify)
{
struct window_pane *wp;
@@ -690,7 +690,9 @@ window_unzoom(struct window *w)
wp->saved_layout_cell = NULL;
}
layout_fix_panes(w, NULL);
- notify_window("window-layout-changed", w);
+
+ if (notify)
+ notify_window("window-layout-changed", w);
return (0);
}
@@ -704,7 +706,7 @@ window_push_zoom(struct window *w, int always, int flag)
w->flags |= WINDOW_WASZOOMED;
else
w->flags &= ~WINDOW_WASZOOMED;
- return (window_unzoom(w) == 0);
+ return (window_unzoom(w, 1) == 0);
}
int
|