]> git.kaiwu.me - haproxy.git/commitdiff
BUG/MEDIUM: h3: fix end-of-input report on DATA wrapping
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 7 Oct 2026 13:31:40 +0000 (15:31 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 8 Oct 2026 12:10:03 +0000 (14:10 +0200)
A received H3 DATA frame may wrap in the buffer. Function
h3_data_to_htx() will parse it in two pass in this case, calling
htx_add_data() twice.

A double bug was present in case of such parsing as second call of
htx_add_data() return value was immediately added in <htx_sent>. This
could cause first check to activate QC_SF_DEM_FULL to be ignored. This
is a minor issue, as MUX would immediately reinvoke h3_rcv_buf(), with
the flag set this time.

The second bug is more important : comparison for HTX EOM reporting was
invalid in case of a two pass parsing. Most of the time, this result in
EOM not reported, causing the stream layer to report a stream
interruption with state CL--.

Fix this by using an intermediary return value for the second
htx_add_data() invokation. This value is only added to <htx_sent> once
necessary checks are performed. It is important to keep h3_data_to_htx()
to still return the total value of HTX added data to avoid parser desync
issue.

This must be backported up to 2.6, after a period of observation.

src/h3.c

index fb6d9556b8171afcfb6a9b5b24a0b99bd96cea29..a52538cf82b97a27d9cf0a2f18b592dd4e3a6f5f 100644 (file)
--- a/src/h3.c
+++ b/src/h3.c
@@ -1669,7 +1669,7 @@ static ssize_t h3_data_to_htx(struct qcs *qcs, const struct buffer *buf,
 {
        struct buffer *appbuf = NULL;
        struct htx *htx = NULL;
-       size_t htx_sent = 0;
+       size_t htx_sent = 0, ret;
        int htx_space;
        char *head;
 
@@ -1734,14 +1734,15 @@ static ssize_t h3_data_to_htx(struct qcs *qcs, const struct buffer *buf,
                goto retry;
        }
 
-       htx_sent += htx_add_data(htx, ist2(head, len));
-       if (htx_sent < len) {
+       ret = htx_add_data(htx, ist2(head, len));
+       if (ret < len) {
                qcs->flags |= QC_SF_DEM_FULL;
                goto out;
        }
 
-       if (fin && len == htx_sent)
+       if (fin && len == ret)
                htx_set_eom(htx);
+       htx_sent += ret;
 
  out:
        if (appbuf)