diff --git a/srcpkgs/qt6-base/patches/CVE-2024-39936-qtbase-6.7.patch b/srcpkgs/qt6-base/patches/CVE-2024-39936-qtbase-6.7.patch new file mode 100644 index 00000000000..bef53fb76a3 --- /dev/null +++ b/srcpkgs/qt6-base/patches/CVE-2024-39936-qtbase-6.7.patch @@ -0,0 +1,138 @@ +diff --git a/src/network/access/qhttp2protocolhandler.cpp b/src/network/access/qhttp2protocolhandler.cpp +index 0abd99b9bc2..3631b13dc85 100644 +--- a/src/network/access/qhttp2protocolhandler.cpp ++++ b/src/network/access/qhttp2protocolhandler.cpp +@@ -303,12 +303,12 @@ bool QHttp2ProtocolHandler::sendRequest() + } + } + +- if (!prefaceSent && !sendClientPreface()) +- return false; +- + if (!requests.size()) + return true; + ++ if (!prefaceSent && !sendClientPreface()) ++ return false; ++ + m_channel->state = QHttpNetworkConnectionChannel::WritingState; + // Check what was promised/pushed, maybe we do not have to send a request + // and have a response already? +diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp +index 6766989690c..1e4161d1fdf 100644 +--- a/src/network/access/qhttpnetworkconnectionchannel.cpp ++++ b/src/network/access/qhttpnetworkconnectionchannel.cpp +@@ -209,6 +209,10 @@ void QHttpNetworkConnectionChannel::abort() + bool QHttpNetworkConnectionChannel::sendRequest() + { + Q_ASSERT(protocolHandler); ++ if (waitingForPotentialAbort) { ++ needInvokeSendRequest = true; ++ return false; // this return value is unused ++ } + return protocolHandler->sendRequest(); + } + +@@ -221,21 +225,28 @@ bool QHttpNetworkConnectionChannel::sendRequest() + void QHttpNetworkConnectionChannel::sendRequestDelayed() + { + QMetaObject::invokeMethod(this, [this] { +- Q_ASSERT(protocolHandler); + if (reply) +- protocolHandler->sendRequest(); ++ sendRequest(); + }, Qt::ConnectionType::QueuedConnection); + } + + void QHttpNetworkConnectionChannel::_q_receiveReply() + { + Q_ASSERT(protocolHandler); ++ if (waitingForPotentialAbort) { ++ needInvokeReceiveReply = true; ++ return; ++ } + protocolHandler->_q_receiveReply(); + } + + void QHttpNetworkConnectionChannel::_q_readyRead() + { + Q_ASSERT(protocolHandler); ++ if (waitingForPotentialAbort) { ++ needInvokeReadyRead = true; ++ return; ++ } + protocolHandler->_q_readyRead(); + } + +@@ -1239,7 +1250,18 @@ void QHttpNetworkConnectionChannel::_q_encrypted() + if (!h2RequestsToSend.isEmpty()) { + // Similar to HTTP/1.1 counterpart below: + const auto &pair = std::as_const(h2RequestsToSend).first(); ++ waitingForPotentialAbort = true; + emit pair.second->encrypted(); ++ ++ // We don't send or handle any received data until any effects from ++ // emitting encrypted() have been processed. This is necessary ++ // because the user may have called abort(). We may also abort the ++ // whole connection if the request has been aborted and there is ++ // no more requests to send. ++ QMetaObject::invokeMethod(this, ++ &QHttpNetworkConnectionChannel::checkAndResumeCommunication, ++ Qt::QueuedConnection); ++ + // In case our peer has sent us its settings (window size, max concurrent streams etc.) + // let's give _q_receiveReply a chance to read them first ('invokeMethod', QueuedConnection). + } +@@ -1257,6 +1279,28 @@ void QHttpNetworkConnectionChannel::_q_encrypted() + QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); + } + ++ ++void QHttpNetworkConnectionChannel::checkAndResumeCommunication() ++{ ++ Q_ASSERT(connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2 ++ || connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2Direct); ++ ++ // Because HTTP/2 requires that we send a SETTINGS frame as the first thing we do, and respond ++ // to a SETTINGS frame with an ACK, we need to delay any handling until we can ensure that any ++ // effects from emitting encrypted() have been processed. ++ // This function is called after encrypted() was emitted, so check for changes. ++ ++ if (!reply && h2RequestsToSend.isEmpty()) ++ abort(); ++ waitingForPotentialAbort = false; ++ if (needInvokeReadyRead) ++ _q_readyRead(); ++ if (needInvokeReceiveReply) ++ _q_receiveReply(); ++ if (needInvokeSendRequest) ++ sendRequest(); ++} ++ + void QHttpNetworkConnectionChannel::requeueHttp2Requests() + { + const auto h2RequestsToSendCopy = std::exchange(h2RequestsToSend, {}); +diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h +index c42290feca4..061f20fd426 100644 +--- a/src/network/access/qhttpnetworkconnectionchannel_p.h ++++ b/src/network/access/qhttpnetworkconnectionchannel_p.h +@@ -74,6 +74,10 @@ public: + QAbstractSocket *socket; + bool ssl; + bool isInitialized; ++ bool waitingForPotentialAbort = false; ++ bool needInvokeReceiveReply = false; ++ bool needInvokeReadyRead = false; ++ bool needInvokeSendRequest = false; + ChannelState state; + QHttpNetworkRequest request; // current request, only used for HTTP + QHttpNetworkReply *reply; // current reply for this request, only used for HTTP +@@ -146,6 +150,8 @@ public: + void closeAndResendCurrentRequest(); + void resendCurrentRequest(); + ++ void checkAndResumeCommunication(); ++ + bool isSocketBusy() const; + bool isSocketWriting() const; + bool isSocketWaiting() const; diff --git a/srcpkgs/qt6-base/template b/srcpkgs/qt6-base/template index 4b63dc5d840..4ac4eb88add 100644 --- a/srcpkgs/qt6-base/template +++ b/srcpkgs/qt6-base/template @@ -3,7 +3,7 @@ # On update rebuild all pkg with qt6-base-private-devel pkgname=qt6-base version=6.7.2 -revision=1 +revision=2 build_style=cmake configure_args="-DINSTALL_DATADIR=share/qt6 -DINSTALL_ARCHDATADIR=lib${XBPS_TARGET_WORDSIZE}/qt6