From d077f7ccf48424fa40eea29c69283ec23732c96d Mon Sep 17 00:00:00 2001 From: Amaury Denoyelle Date: Thu, 21 Dec 2023 17:42:43 +0100 Subject: [PATCH] BUG/MINOR: h3: close connection on header list too big 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 | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/h3.c b/src/h3.c index 60b8673c1..9c6b17ea1 100644 --- 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; } }