xcb: ignore bigger size window icon when size exceeds limit

In the absence of the BIG-REQUESTS extension, the maximum
request length is only 65535, with DPR=2, a 128*128 icon size
will be (128*2)^2 = 65536, which exceeds the maximum
request length.

See also the official doc for xcb_get_maximum_request_length.

https://xcb.freedesktop.org/manual/group__XCB__Core__API.html

uint32_t xcb_get_maximum_request_length(xcb_connection_t *c)

In the absence of the BIG-REQUESTS extension, returns the maximum
request length field from the connection setup data, which may be
as much as 65535. If the server supports BIG-REQUESTS, then the
maximum request length field from the reply to the BigRequestsEnable
request will be returned instead.

Note that this length is measured in four-byte units, making the
theoretical maximum lengths roughly 256kB without BIG-REQUESTS and
16GB with.

Fixes: QTBUG-127392
Pick-to: 6.7 6.5 6.2 5.15
Change-Id: Iee53f579802e8bc54ed1519bc5b5591b5e5700e1
Reviewed-by: Jøger Hansegård <joger.hansegard@qt.io>
Reviewed-by: Liang Qi <liang.qi@qt.io>
(cherry picked from commit 0ed5d4d674c241f7affa3b87feb948c26e11d5cc)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Liang Qi 2024-07-22 19:25:24 +02:00 committed by Qt Cherry-pick Bot
parent c237b57983
commit 9f0c48c6b1

View File

@ -1348,6 +1348,7 @@ void QXcbWindow::setWindowIconText(const QString &title)
void QXcbWindow::setWindowIcon(const QIcon &icon) void QXcbWindow::setWindowIcon(const QIcon &icon)
{ {
QList<quint32> icon_data; QList<quint32> icon_data;
const uint32_t sizeLimit = xcb_get_maximum_request_length(xcb_connection());
if (!icon.isNull()) { if (!icon.isNull()) {
QList<QSize> availableSizes = icon.availableSizes(); QList<QSize> availableSizes = icon.availableSizes();
if (availableSizes.isEmpty()) { if (availableSizes.isEmpty()) {
@ -1363,7 +1364,12 @@ void QXcbWindow::setWindowIcon(const QIcon &icon)
if (!pixmap.isNull()) { if (!pixmap.isNull()) {
QImage image = pixmap.toImage().convertToFormat(QImage::Format_ARGB32); QImage image = pixmap.toImage().convertToFormat(QImage::Format_ARGB32);
int pos = icon_data.size(); int pos = icon_data.size();
icon_data.resize(pos + 2 + image.width()*image.height()); int newSize = pos + 2 + image.width()*image.height();
// In the absence of the BIG-REQUESTS extension, or with too big DPR,
// the size of icon data is too big for the xcb request very easily.
if (quint64(newSize) > quint64(sizeLimit))
break;
icon_data.resize(newSize);
icon_data[pos++] = image.width(); icon_data[pos++] = image.width();
icon_data[pos++] = image.height(); icon_data[pos++] = image.height();
memcpy(icon_data.data() + pos, image.bits(), image.width()*image.height()*4); memcpy(icon_data.data() + pos, image.bits(), image.width()*image.height()*4);
@ -1373,10 +1379,10 @@ void QXcbWindow::setWindowIcon(const QIcon &icon)
if (!icon_data.isEmpty()) { if (!icon_data.isEmpty()) {
// Ignore icon exceeding maximum xcb request length // Ignore icon exceeding maximum xcb request length
if (quint64(icon_data.size()) > quint64(xcb_get_maximum_request_length(xcb_connection()))) { if (quint64(icon_data.size()) > quint64(sizeLimit)) {
qWarning() << "Ignoring window icon" << icon_data.size() qWarning() << "Ignoring window icon" << icon_data.size()
<< "exceeds maximum xcb request length" << "exceeds maximum xcb request length"
<< xcb_get_maximum_request_length(xcb_connection()); << sizeLimit;
return; return;
} }
xcb_change_property(xcb_connection(), xcb_change_property(xcb_connection(),