]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: h3: reject too big frames
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Tue, 24 May 2022 09:13:46 +0000 (11:13 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 25 May 2022 13:41:25 +0000 (15:41 +0200)
The whole frame payload must have been received to demux a H3 frames,
except for H3 DATA which can be fragmented into multiple HTX blocks.

If the frame is bigger than the buffer and is not a DATA frame, a
connection error is reported with error H3_EXCESSIVE_LOAD.

This should be completed in the future with the H3 settings to limit the
size of uncompressed header section.

This code is more generic : it can handle every H3 frames. This is done
in order to be able to use h3_decode_qcs() to demux both uni and bidir
streams.

src/h3.c

index 8d2732e44ee193a702600c5b53368afd7f2da1ce..c2dfd00026891b72c49962d527173dda55ba4b56 100644 (file)
--- a/src/h3.c
+++ b/src/h3.c
@@ -296,11 +296,24 @@ static int h3_decode_qcs(struct qcs *qcs, int fin, void *ctx)
 
                flen = h3s->demux_frame_len;
                ftype = h3s->demux_frame_type;
-               /* Do not demux HEADERS if frame incomplete. */
-               if (ftype == H3_FT_HEADERS && flen > b_data(&b)) {
-                       BUG_ON(ncb_is_full(rxbuf)); /* TODO should define SETTINGS for max header size */
+
+               /* Do not demux incomplete frames except H3 DATA which can be
+                * fragmented in multiple HTX blocks.
+                */
+               if (flen > b_data(&b) && ftype != H3_FT_DATA) {
+                       /* Reject frames bigger than bufsize.
+                        *
+                        * TODO HEADERS should in complement be limited with H3
+                        * SETTINGS_MAX_FIELD_SECTION_SIZE parameter to prevent
+                        * excessive decompressed size.
+                        */
+                       if (flen > ncb_size(rxbuf)) {
+                               qcc_emit_cc_app(qcs->qcc, H3_EXCESSIVE_LOAD);
+                               return 1;
+                       }
                        break;
                }
+
                last_stream_frame = (fin && flen == ncb_total_data(rxbuf));
 
                switch (ftype) {
@@ -316,14 +329,15 @@ static int h3_decode_qcs(struct qcs *qcs, int fin, void *ctx)
                        break;
                case H3_FT_PUSH_PROMISE:
                        /* Not supported */
-                       ret = MIN(ncb_data(rxbuf, 0), flen);
+                       ret = flen;
                        break;
                default:
                        /* draft-ietf-quic-http34 9. Extensions to HTTP/3
                         * unknown frame types MUST be ignored
                         */
                        h3_debug_printf(stderr, "ignore unknown frame type 0x%lx\n", ftype);
-                       ret = MIN(ncb_data(rxbuf, 0), flen);
+                       ret = flen;
+                       break;
                }
 
                if (ret) {