]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
OPTIM: h3: skip buf realign if no trailer to encode
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 26 Jan 2023 16:49:21 +0000 (17:49 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 30 Jan 2023 14:39:41 +0000 (15:39 +0100)
h3_resp_trailers_send() may be called due to an HTX EOT block present
without preceeding HTX TRAILER block. In this case, no HEADERS frame
will be generated by H3 layer and MUX will emit an empty STREAM frame
with FIN set.

However, before skipping these, some operations are conducted on qcs
buffer to realign it and try to encode the QPACK field section line in a
buffer copy. These operation are thus unneeded if no trailer is
generated. Even worse, the function will fail if there is not enough
space in the buffer for the superfluous QPACK section line.

To improve this situation, this patch adds an early goto statement to
skip most operations in h3_resp_trailers_send() if no HTX trailer block
is found.

This patch is related to github issue #2006.

This should be backported up to 2.7.

src/h3.c

index cbb7540036e3dc377c5793eba015eec295ac29a1..14637e5bea5b2c9a560a3c89db57c8e4cf22d89a 100644 (file)
--- a/src/h3.c
+++ b/src/h3.c
@@ -1377,6 +1377,13 @@ static int h3_resp_trailers_send(struct qcs *qcs, struct htx *htx)
                }
        }
 
+       if (!hdr) {
+               /* No headers encoded here so no need to generate a H3 HEADERS
+                * frame. Mux will send an empty QUIC STREAM frame with FIN.
+                */
+               TRACE_DATA("skipping trailer", H3_EV_TX_HDR, qcs->qcc->conn, qcs);
+               goto end;
+       }
        list[hdr].n = ist("");
 
        res = mux_get_buf(qcs);
@@ -1420,24 +1427,24 @@ static int h3_resp_trailers_send(struct qcs *qcs, struct htx *htx)
                }
        }
 
-       /* Now that all headers are encoded, we are certain that res buffer is
-        * big enough.
-        */
-
        /* Check that at least one header was encoded in buffer. */
-       if (b_tail(&headers_buf) != tail) {
-               b_putchr(res, 0x01); /* h3 HEADERS frame type */
-               if (!b_quic_enc_int(res, b_data(&headers_buf), 8))
-                       ABORT_NOW();
-               b_add(res, b_data(&headers_buf));
-       }
-       else  {
+       if (b_tail(&headers_buf) == tail) {
                /* No headers encoded here so no need to generate a H3 HEADERS
                 * frame. Mux will send an empty QUIC STREAM frame with FIN.
                 */
                TRACE_DATA("skipping trailer", H3_EV_TX_HDR, qcs->qcc->conn, qcs);
+               goto end;
        }
 
+       /* Now that all headers are encoded, we are certain that res buffer is
+        * big enough.
+        */
+       b_putchr(res, 0x01); /* h3 HEADERS frame type */
+       if (!b_quic_enc_int(res, b_data(&headers_buf), 8))
+               ABORT_NOW();
+       b_add(res, b_data(&headers_buf));
+
+ end:
        ret = 0;
        blk = htx_get_head_blk(htx);
        while (blk) {