From f88ff99d82f3e2f9811d174838d28fc4339e2284 Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Tue, 14 Mar 2023 16:59:39 +0000 Subject: [PATCH] wayland: Truncate strings sent via plasmawindowmanager interface Wayland has a limited size for strings in arguments. We should truncate any strings that come from user-defined data before sending. We keep the full title around within kwin as it keeps logic simpler. Size length logic is lifted from QWaylandWindow's setTitle BUG: 465775 --- .../client/test_wayland_windowmanagement.cpp | 13 ++++++++++++ .../plasmawindowmanagement_interface.cpp | 21 +++++++++++++++---- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/wayland/autotests/client/test_wayland_windowmanagement.cpp b/src/wayland/autotests/client/test_wayland_windowmanagement.cpp index 7755fad265..e6dc059a28 100644 --- a/src/wayland/autotests/client/test_wayland_windowmanagement.cpp +++ b/src/wayland/autotests/client/test_wayland_windowmanagement.cpp @@ -36,6 +36,7 @@ private Q_SLOTS: void init(); void testWindowTitle(); + void testReallyLongTitle(); void testMinimizedGeometry(); void testUseAfterUnmap(); void testServerDelete(); @@ -166,6 +167,18 @@ void TestWindowManagement::testWindowTitle() QCOMPARE(m_window->title(), QString::fromUtf8("Test Title")); } +void TestWindowManagement::testReallyLongTitle() +{ + QString title; + title.fill(QLatin1Char('t'), 500000); + m_windowInterface->setTitle(title); + + QSignalSpy titleSpy(m_window, &KWayland::Client::PlasmaWindow::titleChanged); + + QVERIFY(titleSpy.wait()); + QVERIFY(m_window->title().startsWith("t")); +} + void TestWindowManagement::testMinimizedGeometry() { m_window->setMinimizedGeometry(m_surface, QRect(5, 10, 100, 200)); diff --git a/src/wayland/plasmawindowmanagement_interface.cpp b/src/wayland/plasmawindowmanagement_interface.cpp index ebde1c2a41..e9370347d2 100644 --- a/src/wayland/plasmawindowmanagement_interface.cpp +++ b/src/wayland/plasmawindowmanagement_interface.cpp @@ -25,6 +25,19 @@ namespace KWaylandServer static const quint32 s_version = 16; static const quint32 s_activationVersion = 1; +// any strings that come from user-defined sources +// that could exceed the maximum wayland length (i.e xwayland clients) +// need to be truncated to the maximumWaylandBufferSize +static QString truncate(const QString &stringIn) +{ + const int libwaylandMaxBufferSize = 4096; + // Some parts of the buffer is used for metadata, so subtract 100 to be on the safe side. + // Also, QString is in utf-16, which means that in the worst case each character will be + // three bytes when converted to utf-8 (which is what libwayland uses), so divide by three. + const int maxLength = libwaylandMaxBufferSize / 3 - 100; + return stringIn.left(maxLength); +} + class PlasmaWindowManagementInterfacePrivate : public QtWaylandServer::org_kde_plasma_window_management { public: @@ -347,13 +360,13 @@ void PlasmaWindowInterfacePrivate::org_kde_plasma_window_bind_resource(Resource } } if (!m_appId.isEmpty()) { - send_app_id_changed(resource->handle, m_appId); + send_app_id_changed(resource->handle, truncate(m_appId)); } if (m_pid != 0) { send_pid_changed(resource->handle, m_pid); } if (!m_title.isEmpty()) { - send_title_changed(resource->handle, m_title); + send_title_changed(resource->handle, truncate(m_title)); } if (!m_appObjectPath.isEmpty() || !m_appServiceName.isEmpty()) { send_application_menu(resource->handle, m_appServiceName, m_appObjectPath); @@ -393,7 +406,7 @@ void PlasmaWindowInterfacePrivate::setAppId(const QString &appId) const auto clientResources = resourceMap(); for (auto resource : clientResources) { - send_app_id_changed(resource->handle, m_appId); + send_app_id_changed(resource->handle, truncate(m_appId)); } } @@ -503,7 +516,7 @@ void PlasmaWindowInterfacePrivate::setTitle(const QString &title) const auto clientResources = resourceMap(); for (auto resource : clientResources) { - send_title_changed(resource->handle, m_title); + send_title_changed(resource->handle, truncate(m_title)); } }