Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package qt6-httpserver for openSUSE:Factory
checked in at 2026-11-05 18:28:31
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/qt6-httpserver (Old)
and /work/SRC/openSUSE:Factory/.qt6-httpserver.new.3759290 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "qt6-httpserver"
Thu Nov 5 18:28:31 2026 rev:31 rq:1394836 version:6.12.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/qt6-httpserver/qt6-httpserver.changes
2026-10-18 19:21:27.852133524 +0200
+++
/work/SRC/openSUSE:Factory/.qt6-httpserver.new.3759290/qt6-httpserver.changes
2026-11-05 18:28:34.387351472 +0100
@@ -1,0 +2,6 @@
+Wed Nov 4 07:47:28 UTC 2026 - Christophe Marin <[email protected]>
+
+- Add upstream change (CVE-2026-110944)
+ * CVE-2026-110944-qthttpserver-6.12-0001.diff
+
+-------------------------------------------------------------------
New:
----
CVE-2026-110944-qthttpserver-6.12-0001.diff
----------(New B)----------
New:- Add upstream change (CVE-2026-110944)
* CVE-2026-110944-qthttpserver-6.12-0001.diff
----------(New E)----------
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ qt6-httpserver.spec ++++++
--- /var/tmp/diff_new_pack.4rc4NP/_old 2026-11-05 18:28:35.421394470 +0100
+++ /var/tmp/diff_new_pack.4rc4NP/_new 2026-11-05 18:28:35.424394594 +0100
@@ -33,6 +33,8 @@
License: GPL-3.0-only
URL: https://www.qt.io
Source0:
https://download.qt.io/official_releases/qt/%{short_version}/%{real_version}%{tar_suffix}/submodules/%{tar_name}-%{real_version}%{tar_suffix}.tar.xz
+# PATCH-FIX-UPSTREAM
+Patch0: CVE-2026-110944-qthttpserver-6.12-0001.diff
BuildRequires: pkgconfig
BuildRequires: cmake(Qt6Concurrent) = %{real_version}
BuildRequires: cmake(Qt6Core) = %{real_version}
++++++ CVE-2026-110944-qthttpserver-6.12-0001.diff ++++++
>From d0b683915dd1d29a161366e074aae50ba932c24f Mon Sep 17 00:00:00 2001
From: Mate Barany <[email protected]>
Date: Tue, 08 Sep 2026 17:15:25 +0200
Subject: [PATCH] Cap chunk-size line length to prevent memory exhaustion
getChunkSize() appended the chunk-size line into the shared fragment
buffer byte by byte with no ceiling, and the body-size limit never
applies (it gates decoded body bytes only). A chunked request with an
endless hex string or unterminated chunk-extension thus grew fragment
until OOM.
Bound it per byte via isHeaderFieldSizeAllowed() (48 KiB),
sending 400 and returning -1.
Fixes: QTBUG-150270
Pick-to: 6.12.0 6.11
Change-Id: I104d2adca36710ca812e58024dfc5544dcba52af
Reviewed-by: MÃ¥rten Nordheim <[email protected]>
Reviewed-by: Thiago Macieira <[email protected]>
(cherry picked from commit 988f1d72679f4fe55442af4f431d1c5b11171656)
Reviewed-by: Qt Cherry-pick Bot <[email protected]>
---
diff --git a/src/httpserver/qhttpserverparser.cpp
b/src/httpserver/qhttpserverparser.cpp
index 4fbec04..dd5b563 100644
--- a/src/httpserver/qhttpserverparser.cpp
+++ b/src/httpserver/qhttpserverparser.cpp
@@ -563,7 +563,10 @@
}
// Note that chunk size gets stored in currentChunkSize, what is
returned is the bytes
// read
- bytes += getChunkSize(socket, ¤tChunkSize);
+ const qsizetype chunkSizeBytes = getChunkSize(socket,
¤tChunkSize);
+ if (chunkSizeBytes < 0)
+ return -1;
+ bytes += chunkSizeBytes;
if (currentChunkSize == -1)
break;
if (!filter->isBodySizeAllowed(bodyBuffer.byteAmount() +
currentChunkSize)) {
@@ -643,6 +646,14 @@
bytes += haveRead;
fragment.append(c);
+ if (!filter->isHeaderFieldSizeAllowed(fragment.size())) {
+ sendError(socket,
QHttpServerResponder::StatusCode::BadRequest);
+ socket->skip(socket->bytesAvailable());
+ qCDebug(lcHttpServerParser) << "Chunk size line too long at"
<< fragment.size()
+ << "bytes from client" <<
getClientIpAddressAndPort();
+ fragment.clear();
+ return -1;
+ }
}
}
diff --git a/tests/auto/qabstracthttpserver/tst_qabstracthttpserver.cpp
b/tests/auto/qabstracthttpserver/tst_qabstracthttpserver.cpp
index 1ef3fc2..39ac8dc 100644
--- a/tests/auto/qabstracthttpserver/tst_qabstracthttpserver.cpp
+++ b/tests/auto/qabstracthttpserver/tst_qabstracthttpserver.cpp
@@ -154,6 +154,8 @@
void http2request();
void socketDisconnected();
void keepAliveTimeout();
+ void chunkedRequest();
+ void chunkedSizeLineTooLong();
private:
#if QT_CONFIG(ssl)
@@ -990,6 +992,90 @@
#endif // QT_CONFIG(ssl)
}
+void tst_QAbstractHttpServer::chunkedRequest()
+{
+ struct HttpServer : QAbstractHttpServer
+ {
+ QByteArray body;
+ bool handleRequest(const QHttpServerRequest &request,
+ QHttpServerResponder &responder) override
+ {
+ body = request.body();
+ auto _responder = std::move(responder);
+ return true;
+ }
+
+ void missingHandler(const QHttpServerRequest &, QHttpServerResponder
&) override { }
+ } server;
+
+ QTcpServer tcpServer;
+ QVERIFY(tcpServer.listen());
+ server.bind(&tcpServer);
+
+ QTcpSocket client;
+ client.connectToHost(QHostAddress::LocalHost, tcpServer.serverPort());
+ QVERIFY(client.waitForConnected());
+
+ // A well-formed chunked request body must be decoded and delivered.
+ client.write("POST / HTTP/1.1\r\n"
+ "Host: localhost\r\n"
+ "Transfer-Encoding: chunked\r\n"
+ "\r\n"
+ "5\r\nHello\r\n"
+ "6\r\n World\r\n"
+ "0\r\n\r\n");
+ QVERIFY(client.waitForBytesWritten());
+
+ QTRY_COMPARE(server.body, QByteArray("Hello World"));
+}
+
+void tst_QAbstractHttpServer::chunkedSizeLineTooLong()
+{
+ struct HttpServer : QAbstractHttpServer
+ {
+ bool handleRequestCalled = false;
+ bool handleRequest(const QHttpServerRequest &, QHttpServerResponder
&responder) override
+ {
+ handleRequestCalled = true;
+ auto _responder = std::move(responder);
+ return true;
+ }
+
+ void missingHandler(const QHttpServerRequest &, QHttpServerResponder
&) override { }
+ } server;
+
+ QTcpServer tcpServer;
+ QVERIFY(tcpServer.listen());
+ server.bind(&tcpServer);
+
+ // Lower the per-field limit (default 48 KiB) so a few hundred bytes trip
the
+ // size-line cap
+ QHttpServerConfiguration config;
+ config.setMaximumHeaderFieldSize(256);
+ server.setConfiguration(config);
+
+ QTcpSocket client;
+ client.connectToHost(QHostAddress::LocalHost, tcpServer.serverPort());
+ QVERIFY(client.waitForConnected());
+
+ // Send a chunk-size line that never terminates: a run of digits with no
CRLF.
+ // This is not a valid chunk. The parser must bound the size-line buffer,
+ // reply 400, and close.
+ QByteArray request = "POST / HTTP/1.1\r\n"
+ "Host: localhost\r\n"
+ "Transfer-Encoding: chunked\r\n"
+ "\r\n";
+ request += QByteArray(512, '0'); // exceeds the 256-byte size-line cap, no
CRLF
+ client.write(request);
+ QVERIFY(client.waitForBytesWritten());
+
+ // waitForDisconnected() would only wait on the client socket and time out
+ QTRY_COMPARE(client.state(), QAbstractSocket::UnconnectedState);
+ const QByteArray response = client.readAll();
+ QVERIFY2(response.startsWith("HTTP/1.1 400"), response.constData());
+ QVERIFY(!server.handleRequestCalled);
+}
+
QT_END_NAMESPACE
QTEST_MAIN(tst_QAbstractHttpServer)