Skip to content

Commit 1661ef1

Browse files
committed
wm: recompute WindowsetProjection.screens on each usage
Fixes potential UAF from destroyed screens not yet removed by a wayland commit.
1 parent 68c2c85 commit 1661ef1

3 files changed

Lines changed: 17 additions & 14 deletions

File tree

changelog/next.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@
66
- Fixed missing/wrong change signals on various properties.
77
- Fixed session lock crashes on sleep, wake, DPMS, and unlocking.
88
- QsWindow.updatesEnabled makes sure windows are redrawn when set to true.
9+
- Fixed potential crashes from usage of `WindowsetProjection.screens` during monitor unplug.

src/windowmanager/windowset.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,22 @@ WindowsetProjection::WindowsetProjection(QObject* parent): QObject(parent) {
3030
}
3131
return result;
3232
});
33+
}
3334

34-
this->bScreens.setBinding([this] {
35-
QList<QuickshellScreenInfo*> screens;
35+
QList<QuickshellScreenInfo*> WindowsetProjection::screens() {
36+
QList<QuickshellScreenInfo*> screens;
3637

37-
for (auto* screen: this->bQScreens.value()) {
38-
screens.append(QuickshellTracked::instance()->screenInfo(screen));
38+
for (auto* screen: this->bQScreens.value()) {
39+
if (auto* qsScreen = QuickshellTracked::instance()->screenInfo(screen)) {
40+
screens.append(qsScreen);
41+
} else {
42+
qCDebug(logWorkspace) << this << "screens list contains invalid screen"
43+
<< static_cast<void*>(screen)
44+
<< "which was probably removed before workspace state has settled.";
3945
}
46+
}
4047

41-
return screens;
42-
});
48+
return screens;
4349
}
4450

4551
} // namespace qs::wm

src/windowmanager/windowset.hpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -132,17 +132,15 @@ class WindowsetProjection: public QObject {
132132
QML_UNCREATABLE("");
133133
// clang-format off
134134
/// Screens the windowset projection spans, often a single screen or all screens.
135-
Q_PROPERTY(QList<QuickshellScreenInfo*> screens READ default NOTIFY screensChanged BINDABLE bindableScreens);
135+
Q_PROPERTY(QList<QuickshellScreenInfo*> screens READ screens NOTIFY screensChanged);
136136
/// Windowsets that are currently present on the projection.
137137
Q_PROPERTY(QList<Windowset*> windowsets READ default NOTIFY windowsetsChanged BINDABLE bindableWindowsets);
138138
// clang-format on
139139

140140
public:
141141
explicit WindowsetProjection(QObject* parent);
142142

143-
[[nodiscard]] QBindable<QList<QuickshellScreenInfo*>> bindableScreens() const {
144-
return &this->bScreens;
145-
}
143+
[[nodiscard]] QList<QuickshellScreenInfo*> screens();
146144

147145
[[nodiscard]] QBindable<QList<QScreen*>> bindableQScreens() const { return &this->bQScreens; }
148146

@@ -155,12 +153,10 @@ class WindowsetProjection: public QObject {
155153
void windowsetsChanged();
156154

157155
protected:
158-
Q_OBJECT_BINDABLE_PROPERTY(WindowsetProjection, QList<QScreen*>, bQScreens);
159-
160156
Q_OBJECT_BINDABLE_PROPERTY(
161157
WindowsetProjection,
162-
QList<QuickshellScreenInfo*>,
163-
bScreens,
158+
QList<QScreen*>,
159+
bQScreens,
164160
&WindowsetProjection::screensChanged
165161
);
166162

0 commit comments

Comments
 (0)