]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: hq-interop: reject too big content flx04/quic-interop
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 18 Jun 2026 08:52:49 +0000 (10:52 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 18 Jun 2026 12:33:30 +0000 (14:33 +0200)
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 <root@beacox.space> 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.

src/hq_interop.c

index c1fc5c23d58fc4fddfe727bb663b681380819b7b..d17dd7977c8af5fbd608651840be9775da6932f0 100644 (file)
@@ -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;
        }