qtbase patch: add defensive validation in oldestEnteredScreen

This commit is contained in:
Damocles 2026-04-20 11:33:31 +02:00
parent 8ad32c631a
commit d247f64cac

View file

@ -1,5 +1,5 @@
diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.cpp b/src/plugins/platforms/wayland/qwaylanddisplay.cpp diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.cpp b/src/plugins/platforms/wayland/qwaylanddisplay.cpp
index 02169e77..a1f3befe 100644 index 02169e77..43ab00fa 100644
--- a/src/plugins/platforms/wayland/qwaylanddisplay.cpp --- a/src/plugins/platforms/wayland/qwaylanddisplay.cpp
+++ b/src/plugins/platforms/wayland/qwaylanddisplay.cpp +++ b/src/plugins/platforms/wayland/qwaylanddisplay.cpp
@@ -423,8 +423,10 @@ void QWaylandDisplay::reconnect() @@ -423,8 +423,10 @@ void QWaylandDisplay::reconnect()
@ -15,7 +15,7 @@ index 02169e77..a1f3befe 100644
while (!mScreens.isEmpty()) { while (!mScreens.isEmpty()) {
auto screen = mScreens.takeLast(); auto screen = mScreens.takeLast();
@@ -603,6 +605,22 @@ QWaylandScreen *QWaylandDisplay::screenForOutput(struct wl_output *output) const @@ -603,6 +605,27 @@ QWaylandScreen *QWaylandDisplay::screenForOutput(struct wl_output *output) const
return nullptr; return nullptr;
} }
@ -29,6 +29,11 @@ index 02169e77..a1f3befe 100644
+ mSurfaces.removeOne(surface); + mSurfaces.removeOne(surface);
+} +}
+ +
+bool QWaylandDisplay::isScreenAlive(QWaylandScreen *screen) const
+{
+ return mScreens.contains(screen) || mWaitingScreens.contains(screen);
+}
+
+void QWaylandDisplay::forgetScreenForSurfaces(QWaylandScreen *screen) +void QWaylandDisplay::forgetScreenForSurfaces(QWaylandScreen *screen)
+{ +{
+ for (auto *surface : std::as_const(mSurfaces)) + for (auto *surface : std::as_const(mSurfaces))
@ -38,7 +43,7 @@ index 02169e77..a1f3befe 100644
void QWaylandDisplay::handleScreenInitialized(QWaylandScreen *screen) void QWaylandDisplay::handleScreenInitialized(QWaylandScreen *screen)
{ {
if (!mWaitingScreens.removeOne(screen)) if (!mWaitingScreens.removeOne(screen))
@@ -823,6 +841,7 @@ void QWaylandDisplay::registry_global_remove(uint32_t id) @@ -823,6 +846,7 @@ void QWaylandDisplay::registry_global_remove(uint32_t id)
for (auto *screen : mWaitingScreens) { for (auto *screen : mWaitingScreens) {
if (screen->outputId() == id) { if (screen->outputId() == id) {
mWaitingScreens.removeOne(screen); mWaitingScreens.removeOne(screen);
@ -46,7 +51,7 @@ index 02169e77..a1f3befe 100644
delete screen; delete screen;
break; break;
} }
@@ -831,6 +850,7 @@ void QWaylandDisplay::registry_global_remove(uint32_t id) @@ -831,6 +855,7 @@ void QWaylandDisplay::registry_global_remove(uint32_t id)
for (QWaylandScreen *screen : std::as_const(mScreens)) { for (QWaylandScreen *screen : std::as_const(mScreens)) {
if (screen->outputId() == id) { if (screen->outputId() == id) {
mScreens.removeOne(screen); mScreens.removeOne(screen);
@ -55,20 +60,21 @@ index 02169e77..a1f3befe 100644
ensureScreen(); ensureScreen();
QWindowSystemInterface::handleScreenRemoved(screen); QWindowSystemInterface::handleScreenRemoved(screen);
diff --git a/src/plugins/platforms/wayland/qwaylanddisplay_p.h b/src/plugins/platforms/wayland/qwaylanddisplay_p.h diff --git a/src/plugins/platforms/wayland/qwaylanddisplay_p.h b/src/plugins/platforms/wayland/qwaylanddisplay_p.h
index 29952886..0baa378f 100644 index 29952886..88b57945 100644
--- a/src/plugins/platforms/wayland/qwaylanddisplay_p.h --- a/src/plugins/platforms/wayland/qwaylanddisplay_p.h
+++ b/src/plugins/platforms/wayland/qwaylanddisplay_p.h +++ b/src/plugins/platforms/wayland/qwaylanddisplay_p.h
@@ -116,6 +116,9 @@ public: @@ -116,6 +116,10 @@ public:
QPlatformPlaceholderScreen *placeholderScreen() const { return mPlaceholderScreen; } QPlatformPlaceholderScreen *placeholderScreen() const { return mPlaceholderScreen; }
void ensureScreen(); void ensureScreen();
+ void registerSurface(QWaylandSurface *surface); + void registerSurface(QWaylandSurface *surface);
+ void unregisterSurface(QWaylandSurface *surface); + void unregisterSurface(QWaylandSurface *surface);
+ bool isScreenAlive(QWaylandScreen *screen) const;
+ +
QWaylandScreen *screenForOutput(struct wl_output *output) const; QWaylandScreen *screenForOutput(struct wl_output *output) const;
void handleScreenInitialized(QWaylandScreen *screen); void handleScreenInitialized(QWaylandScreen *screen);
@@ -289,6 +292,7 @@ private: @@ -289,6 +293,7 @@ private:
void checkWaylandError(); void checkWaylandError();
void reconnect(); void reconnect();
void setupConnection(); void setupConnection();
@ -76,7 +82,7 @@ index 29952886..0baa378f 100644
void handleWaylandSync(); void handleWaylandSync();
void requestWaylandSync(); void requestWaylandSync();
@@ -311,6 +315,7 @@ private: @@ -311,6 +316,7 @@ private:
QList<QWaylandScreen *> mScreens; QList<QWaylandScreen *> mScreens;
QPlatformPlaceholderScreen *mPlaceholderScreen = nullptr; QPlatformPlaceholderScreen *mPlaceholderScreen = nullptr;
QList<QWaylandInputDevice *> mInputDevices; QList<QWaylandInputDevice *> mInputDevices;
@ -85,10 +91,10 @@ index 29952886..0baa378f 100644
QWaylandIntegration *mWaylandIntegration = nullptr; QWaylandIntegration *mWaylandIntegration = nullptr;
#if QT_CONFIG(cursor) #if QT_CONFIG(cursor)
diff --git a/src/plugins/platforms/wayland/qwaylandsurface.cpp b/src/plugins/platforms/wayland/qwaylandsurface.cpp diff --git a/src/plugins/platforms/wayland/qwaylandsurface.cpp b/src/plugins/platforms/wayland/qwaylandsurface.cpp
index 274fdda8..b37e9265 100644 index 274fdda8..fd098066 100644
--- a/src/plugins/platforms/wayland/qwaylandsurface.cpp --- a/src/plugins/platforms/wayland/qwaylandsurface.cpp
+++ b/src/plugins/platforms/wayland/qwaylandsurface.cpp +++ b/src/plugins/platforms/wayland/qwaylandsurface.cpp
@@ -13,13 +13,16 @@ namespace QtWaylandClient { @@ -13,18 +13,31 @@ namespace QtWaylandClient {
QWaylandSurface::QWaylandSurface(QWaylandDisplay *display) QWaylandSurface::QWaylandSurface(QWaylandDisplay *display)
: wl_surface(display->createSurface(this)) : wl_surface(display->createSurface(this))
@ -105,6 +111,21 @@ index 274fdda8..b37e9265 100644
destroy(); destroy();
} }
QWaylandScreen *QWaylandSurface::oldestEnteredScreen()
{
+ // Prune any screen pointers that the display no longer knows about.
+ // This guards against every possible stale-pointer path: waiting-screen
+ // deletion, signal-ordering gaps during ensureScreen(), and any future
+ // code that removes a screen without notifying surfaces.
+ if (m_display) {
+ m_screens.removeIf([this](QWaylandScreen *s) {
+ return !m_display->isScreenAlive(s);
+ });
+ }
+
for (auto *screen : std::as_const(m_screens)) {
// only report valid screens
// we can have some ouptuts waiting for xdg output information
diff --git a/src/plugins/platforms/wayland/qwaylandsurface_p.h b/src/plugins/platforms/wayland/qwaylandsurface_p.h diff --git a/src/plugins/platforms/wayland/qwaylandsurface_p.h b/src/plugins/platforms/wayland/qwaylandsurface_p.h
index 41860297..ddb63b04 100644 index 41860297..ddb63b04 100644
--- a/src/plugins/platforms/wayland/qwaylandsurface_p.h --- a/src/plugins/platforms/wayland/qwaylandsurface_p.h