diff options
author | 2016-10-02 22:03:52 -0500 | |
---|---|---|
committer | 2016-10-02 22:03:52 -0500 | |
commit | 4c0e809028de5efbbfbbbc9685c47b2c0015d56e (patch) | |
tree | af83f1eb07a19bc1edf0f21a9e5cfc38d059a44a /sway | |
parent | Merge pull request #921 from zandrmartin/patch-3 (diff) | |
download | sway-4c0e809028de5efbbfbbbc9685c47b2c0015d56e.tar.gz sway-4c0e809028de5efbbfbbbc9685c47b2c0015d56e.tar.zst sway-4c0e809028de5efbbfbbbc9685c47b2c0015d56e.zip |
prevent dereference of freed workspace
Diffstat (limited to 'sway')
-rw-r--r-- | sway/focus.c | 47 |
1 files changed, 31 insertions, 16 deletions
diff --git a/sway/focus.c b/sway/focus.c index 35dff1e4..e9b032f8 100644 --- a/sway/focus.c +++ b/sway/focus.c | |||
@@ -1,3 +1,4 @@ | |||
1 | #include "stdbool.h" | ||
1 | #include <wlc/wlc.h> | 2 | #include <wlc/wlc.h> |
2 | #include "sway/focus.h" | 3 | #include "sway/focus.h" |
3 | #include "sway/workspace.h" | 4 | #include "sway/workspace.h" |
@@ -99,14 +100,24 @@ bool set_focused_container(swayc_t *c) { | |||
99 | if (locked_container_focus || !c || !c->parent) { | 100 | if (locked_container_focus || !c || !c->parent) { |
100 | return false; | 101 | return false; |
101 | } | 102 | } |
102 | swayc_t *active_ws = swayc_active_workspace(); | 103 | |
103 | int active_ws_child_count = 0; | 104 | // current ("old") workspace for sending workspace change event later |
104 | if (active_ws) { | 105 | swayc_t *old_ws = swayc_active_workspace(); |
105 | active_ws_child_count = active_ws->children->length + active_ws->floating->length; | 106 | // keep track of child count so we can determine if it gets destroyed |
107 | int old_ws_child_count = 0; | ||
108 | if (old_ws) { | ||
109 | old_ws_child_count = old_ws->children->length + old_ws->floating->length; | ||
106 | } | 110 | } |
107 | 111 | ||
112 | // current ("old") focused container | ||
113 | swayc_t *old_focus = get_focused_container(&root_container); | ||
114 | // if old_focus is a workspace, then it's the same workspace as | ||
115 | // old_ws, and we'll need to null its pointer too, since it will | ||
116 | // be destroyed in the update_focus() call | ||
117 | bool old_focus_was_ws = (old_focus->type == C_WORKSPACE); | ||
118 | |||
119 | // workspace of new focused container | ||
108 | swayc_t *workspace = swayc_active_workspace_for(c); | 120 | swayc_t *workspace = swayc_active_workspace_for(c); |
109 | swayc_t *focused = get_focused_container(&root_container); | ||
110 | 121 | ||
111 | if (swayc_is_fullscreen(get_focused_container(workspace))) { | 122 | if (swayc_is_fullscreen(get_focused_container(workspace))) { |
112 | // if switching to a workspace with a fullscreen view, | 123 | // if switching to a workspace with a fullscreen view, |
@@ -136,11 +147,19 @@ bool set_focused_container(swayc_t *c) { | |||
136 | p->is_focused = false; | 147 | p->is_focused = false; |
137 | } | 148 | } |
138 | 149 | ||
150 | if (old_focus_was_ws && old_ws_child_count == 0) { | ||
151 | // this workspace was destroyed in update_focus(), so null the pointers | ||
152 | old_focus = NULL; | ||
153 | old_ws = NULL; | ||
154 | } | ||
155 | |||
139 | if (!(wlc_view_get_type(p->handle) & WLC_BIT_POPUP)) { | 156 | if (!(wlc_view_get_type(p->handle) & WLC_BIT_POPUP)) { |
140 | if (focused->type == C_VIEW) { | 157 | if (old_focus) { |
141 | wlc_view_set_state(focused->handle, WLC_BIT_ACTIVATED, false); | 158 | if (old_focus->type == C_VIEW) { |
159 | wlc_view_set_state(old_focus->handle, WLC_BIT_ACTIVATED, false); | ||
160 | } | ||
161 | update_container_border(old_focus); | ||
142 | } | 162 | } |
143 | update_container_border(focused); | ||
144 | if (c->type == C_VIEW) { | 163 | if (c->type == C_VIEW) { |
145 | wlc_view_set_state(c->handle, WLC_BIT_ACTIVATED, true); | 164 | wlc_view_set_state(c->handle, WLC_BIT_ACTIVATED, true); |
146 | } | 165 | } |
@@ -161,15 +180,11 @@ bool set_focused_container(swayc_t *c) { | |||
161 | } | 180 | } |
162 | } | 181 | } |
163 | 182 | ||
164 | if (active_ws != workspace) { | 183 | if (old_ws != workspace) { |
165 | // active_ws might have been destroyed by now | 184 | // old_ws might be NULL here but that's ok |
166 | // (focus swap away from empty ws = destroy ws) | 185 | ipc_event_workspace(old_ws, workspace, "focus"); |
167 | if (active_ws_child_count == 0) { | ||
168 | active_ws = NULL; | ||
169 | } | ||
170 | |||
171 | ipc_event_workspace(active_ws, workspace, "focus"); | ||
172 | } | 186 | } |
187 | |||
173 | return true; | 188 | return true; |
174 | } | 189 | } |
175 | 190 | ||