From: Amaury Denoyelle Date: Thu, 18 Jun 2026 08:52:49 +0000 (+0200) Subject: BUG/MINOR: hq-interop: reject too big content X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0a98fdb038d84b9626c6dfe4355874a52d1b7a8c;p=thirdparty%2Fhaproxy.git BUG/MINOR: hq-interop: reject too big content hq-interop request parser is minimal. It simply extracts a method and a path until the whitespace delimiter. Parsing is interrupted if the delimiter cannot be found, and MUX is responsible to reinvoke it later with new content added. This patch adjusts hq-interop parsing in case of a missing delimiter. Now it also checks if there is space remaining in the buffer. If this is not the case, it returns a fatal error as parsing cannot be completed at all. This change has the side effect of preventing a BUG_ON() crash in MUX : in case of a truncated parsing, qcs_transfer_rx_data() may be used to realign content from the next buffer. However this function explicitely forbids to be called with a full buffer as it could do nothing in this case, hence this BUG_ON() to ensure parsing is never fully blocked. The impact of this bug remains low despite the potential BUG_ON() crash. This is because hq-interop is only used for QUIC debugging purpose and should not be activated in production. HTTP/3 layer is immune as it already ensures that frame length is never bigger than a buffer size (except for DATA frames which can be parsed in a streaming mode). Thanks to BeaCox for having reported us this issue. This should be backported up to 2.6. From 3.3, qcm_stream_rx_bufsz() is using the older "qmux" prefix and must be renamed. Also, this function does not exists in 3.0 and older so the test must be adjusted there as well. --- diff --git a/src/hq_interop.c b/src/hq_interop.c index c1fc5c23d..d17dd7977 100644 --- a/src/hq_interop.c +++ b/src/hq_interop.c @@ -39,12 +39,22 @@ static ssize_t hq_interop_rcv_buf_req(struct qcs *qcs, struct buffer *b, int fin } if (!data || !HTTP_IS_SPHT(*ptr)) { + if (b_size(b) - b_room(b) >= qcm_stream_rx_bufsz()) { + fprintf(stderr, "content too big\n"); + return -1; + } + fprintf(stderr, "truncated stream\n"); return 0; } ptr++; if (!--data) { + if (b_size(b) - b_room(b) >= qcm_stream_rx_bufsz()) { + fprintf(stderr, "content too big\n"); + return -1; + } + fprintf(stderr, "truncated stream\n"); return 0; } @@ -62,6 +72,11 @@ static ssize_t hq_interop_rcv_buf_req(struct qcs *qcs, struct buffer *b, int fin } if (!data) { + if (b_size(b) - b_room(b) >= qcm_stream_rx_bufsz()) { + fprintf(stderr, "content too big\n"); + return -1; + } + fprintf(stderr, "truncated stream\n"); return 0; }