From 975ee89cea97b12fbc9ecede116580e4a76141d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= Date: Fri, 16 Feb 2024 15:47:56 +0100 Subject: [PATCH] QHttp2Connection: confirm successive remote stream IDs are higher MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit And it should also apply to the promised streams, not separate ID tracking. https://datatracker.ietf.org/doc/html/rfc9113#section-5.1.1 Change-Id: I6826a39c98f9b6a585200e628533843db731a85b Reviewed-by: Timur Pocheptsov Reviewed-by: Øystein Heskestad (cherry picked from commit e247a6ce9ff83ef62424eef01d26cb752a4d2abc) Reviewed-by: Volker Hilsheimer --- src/network/access/qhttp2connection.cpp | 12 ++++++++---- src/network/access/qhttp2connection_p.h | 1 - 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/network/access/qhttp2connection.cpp b/src/network/access/qhttp2connection.cpp index 349968d8d1d..a8b763a5f4a 100644 --- a/src/network/access/qhttp2connection.cpp +++ b/src/network/access/qhttp2connection.cpp @@ -892,12 +892,16 @@ void QHttp2Connection::handleHEADERS() if (streamID == connectionStreamID) return connectionError(PROTOCOL_ERROR, "HEADERS on 0x0 stream"); - if (QPointer stream = m_streams.value(streamID); !stream) { + if (streamID > m_lastIncomingStreamID) { QHttp2Stream *newStream = createStreamInternal_impl(streamID); m_lastIncomingStreamID = streamID; qCDebug(qHttp2ConnectionLog, "[%p] Created new incoming stream %d", this, streamID); emit newIncomingStream(newStream); - } else if (streamWasReset(streamID)) { + } else if (auto it = m_streams.constFind(streamID); it == m_streams.cend()) { + qCDebug(qHttp2ConnectionLog, "[%p] Received HEADERS on non-existent stream %d", this, + streamID); + return connectionError(PROTOCOL_ERROR, "HEADERS on invalid stream"); + } else if (!*it || (*it)->wasReset()) { qCDebug(qHttp2ConnectionLog, "[%p] Received HEADERS on reset stream %d", this, streamID); return connectionError(ENHANCE_YOUR_CALM, "HEADERS on invalid stream"); } @@ -1048,13 +1052,13 @@ void QHttp2Connection::handlePUSH_PROMISE() return connectionError(ENHANCE_YOUR_CALM, "PUSH_PROMISE with invalid associated stream"); const auto reservedID = qFromBigEndian(inboundFrame.dataBegin()); - if ((reservedID & 1) || reservedID <= lastPromisedID || reservedID > lastValidStreamID) + if ((reservedID & 1) || reservedID <= m_lastIncomingStreamID || reservedID > lastValidStreamID) return connectionError(PROTOCOL_ERROR, "PUSH_PROMISE with invalid promised stream ID"); auto *stream = createStreamInternal_impl(reservedID); if (!stream) return connectionError(PROTOCOL_ERROR, "PUSH_PROMISE with already active stream ID"); - lastPromisedID = reservedID; + m_lastIncomingStreamID = reservedID; stream->setState(QHttp2Stream::State::ReservedRemote); if (!pushPromiseEnabled) { diff --git a/src/network/access/qhttp2connection_p.h b/src/network/access/qhttp2connection_p.h index 7ca303f0a8c..6733468bfae 100644 --- a/src/network/access/qhttp2connection_p.h +++ b/src/network/access/qhttp2connection_p.h @@ -346,7 +346,6 @@ private: bool m_upgradedConnection = false; bool m_goingAway = false; bool pushPromiseEnabled = false; - quint32 lastPromisedID = Http2::connectionStreamID; quint32 m_lastIncomingStreamID = Http2::connectionStreamID; // Server-side only: