]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: h3: Be sure to handle fin bit on the last DATA frame
authorChristopher Faulet <cfaulet@haproxy.com>
Fri, 28 Jul 2023 07:33:29 +0000 (09:33 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Fri, 28 Jul 2023 07:33:32 +0000 (09:33 +0200)
When DATA frames are decoded for a QUIC stream, we take care to not exceed
the announced content-length, if any. To do so, we check we don't received
more data than excepted but also no less than announced. For the last check,
we rely on the fin bit.

However, it is possible to have several DATA frames to decode at a time
while the end of the stream was received. In this case, we must take care to
handle the fin bit only on the last frame. But because of a bug, the fin bit
was handled to early, erroneously triggering an internal error.

This patch must be backported as far as 2.6.

src/h3.c

index 42289c0a5ec71373ba9d171c14a5abefa0179fad..94b50ba90472ee4d92f96efdd169424511855573 100644 (file)
--- a/src/h3.c
+++ b/src/h3.c
@@ -1095,7 +1095,7 @@ static ssize_t h3_decode_qcs(struct qcs *qcs, struct buffer *b, int fin)
                        /* Check that content-length is not exceeded on a new DATA frame. */
                        if (ftype == H3_FT_DATA) {
                                h3s->data_len += flen;
-                               if (h3s->flags & H3_SF_HAVE_CLEN && h3_check_body_size(qcs, fin))
+                               if (h3s->flags & H3_SF_HAVE_CLEN && h3_check_body_size(qcs, (fin && flen == b_data(b))))
                                        break;
                        }
 
@@ -1130,12 +1130,12 @@ static ssize_t h3_decode_qcs(struct qcs *qcs, struct buffer *b, int fin)
                        break;
                }
 
+               last_stream_frame = (fin && flen == b_data(b));
+
                /* Check content-length equality with DATA frames length on the last frame. */
-               if (fin && h3s->flags & H3_SF_HAVE_CLEN && h3_check_body_size(qcs, fin))
+               if (last_stream_frame && h3s->flags & H3_SF_HAVE_CLEN && h3_check_body_size(qcs, last_stream_frame))
                        break;
 
-               last_stream_frame = (fin && flen == b_data(b));
-
                h3_inc_frame_type_cnt(h3c->prx_counters, ftype);
                switch (ftype) {
                case H3_FT_DATA: