]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: h3: close connection on header list too big
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 21 Dec 2023 16:42:43 +0000 (17:42 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 22 Dec 2023 14:43:39 +0000 (15:43 +0100)
When parsing a HTX response, if too many headers are present, stop
sending and close the connection with error code H3_INTERNAL_ERROR.

Previously, no error was reported despite the interruption of header
parsing. This cause an infinite loop. However, this is considered as
minor as it happens on the response path from backend side.

This should be backported up to 2.6.
It relies on previous commit
  "MINOR: h3: check connection error during sending".

src/h3.c

index 60b8673c1180f92451e1b01dc0d3dfca3f3397ff..9c6b17ea1c63ff87446aa0b9f30952ac8ec1687a 100644 (file)
--- a/src/h3.c
+++ b/src/h3.c
@@ -1488,6 +1488,8 @@ static int h3_control_send(struct qcs *qcs, void *ctx)
 
 static int h3_resp_headers_send(struct qcs *qcs, struct htx *htx)
 {
+       struct h3s *h3s = qcs->ctx;
+       struct h3c *h3c = h3s->h3c;
        struct buffer outbuf;
        struct buffer headers_buf = BUF_NULL;
        struct buffer *res;
@@ -1521,8 +1523,11 @@ static int h3_resp_headers_send(struct qcs *qcs, struct htx *htx)
                        status = sl->info.res.status;
                }
                else if (type == HTX_BLK_HDR) {
-                       if (unlikely(hdr >= sizeof(list) / sizeof(list[0]) - 1))
+                       if (unlikely(hdr >= sizeof(list) / sizeof(list[0]) - 1)) {
+                               TRACE_ERROR("too many headers", H3_EV_TX_FRAME|H3_EV_TX_HDR, qcs->qcc->conn, qcs);
+                               h3c->err = H3_INTERNAL_ERROR;
                                goto err;
+                       }
                        list[hdr].n = htx_get_blk_name(htx, blk);
                        list[hdr].v = htx_get_blk_value(htx, blk);
                        hdr++;
@@ -1627,6 +1632,8 @@ static int h3_resp_headers_send(struct qcs *qcs, struct htx *htx)
  */
 static int h3_resp_trailers_send(struct qcs *qcs, struct htx *htx)
 {
+       struct h3s *h3s = qcs->ctx;
+       struct h3c *h3c = h3s->h3c;
        struct buffer headers_buf = BUF_NULL;
        struct buffer *res;
        struct http_hdr list[global.tune.max_http_hdr];
@@ -1649,14 +1656,18 @@ static int h3_resp_trailers_send(struct qcs *qcs, struct htx *htx)
                        break;
 
                if (type == HTX_BLK_TLR) {
-                       if (unlikely(hdr >= sizeof(list) / sizeof(list[0]) - 1))
+                       if (unlikely(hdr >= sizeof(list) / sizeof(list[0]) - 1)) {
+                               TRACE_ERROR("too many headers", H3_EV_TX_FRAME|H3_EV_TX_HDR, qcs->qcc->conn, qcs);
+                               h3c->err = H3_INTERNAL_ERROR;
                                goto err;
+                       }
                        list[hdr].n = htx_get_blk_name(htx, blk);
                        list[hdr].v = htx_get_blk_value(htx, blk);
                        hdr++;
                }
                else {
                        TRACE_ERROR("unexpected HTX block", H3_EV_TX_FRAME|H3_EV_TX_HDR, qcs->qcc->conn, qcs);
+                       h3c->err = H3_INTERNAL_ERROR;
                        goto err;
                }
        }