From: Christopher Faulet Date: Mon, 29 Jun 2026 16:33:02 +0000 (+0200) Subject: MEDIUM: htx: Be sure size of headers never exceed regular buffer on update X-Git-Tag: v3.5-dev2~20 X-Git-Url: http://git.kaiwu.me/postgresql/log/contrib/postgres_fdw/static/$%7BGITURL%7D$%7Bcid%7D?a=commitdiff_plain;h=e9a4746f58367813412d5af0cf7ee438208de0e3;p=haproxy.git MEDIUM: htx: Be sure size of headers never exceed regular buffer on update When an HTX header or an HTX start-line is added or updated, a test is now performed to be sure the whole headers size, including the start-line never exceeds the regular buffer size. It is mandatory because it is now possible to use larger buffers. However, it remains impossible to send HEADERS frame in H2 and QUIC larger than a regular buffer. So we must be sure the HTTP analysis will never produce too big headers because they will be rejected later, at the forwarding stage. The purpose of large buffers is to be able to store large payload, larger than regular buffers. Headers must remain quite small. This commit depends on the following one: MINOR: htx: Add a field to save the headers data size Both should be backported to 3.4 to avoid any trouble with large buffers. It is not strictly speaking a bug, but it will avoid hazardous behavior depending on the payload size. --- diff --git a/src/htx.c b/src/htx.c index 132c2c121..7143e3961 100644 --- a/src/htx.c +++ b/src/htx.c @@ -29,6 +29,14 @@ static inline __attribute__((always_inline)) void htx_memcpy(void *dst, void *sr memcpy(dst, src, len); } +/* Retruns 1 if the headers size with addition of exceeds the maximum size + * allowed for headers. + */ +static inline __attribute__((always_inline)) int htx_hdrs_too_big(const struct htx *htx, int32_t len) +{ + return (sizeof(struct htx) + htx->hdrs_data + len > global.tune.bufsize); +} + /* Defragments an HTX message. It removes unused blocks and unwraps the payloads * part. A temporary buffer is used to do so. This function never fails. Most of * time, we need keep a ref on a specific HTX block. Thus is is set, the @@ -341,6 +349,8 @@ struct htx_blk *htx_add_blk(struct htx *htx, enum htx_blk_type type, uint32_t bl struct htx_blk *blk; BUG_ON(blksz >= 256 << 20); + if (unlikely(type < HTX_BLK_EOH && htx_hdrs_too_big(htx, blksz))) + return NULL; blk = htx_reserve_nxblk(htx, blksz); if (!blk) return NULL; @@ -638,6 +648,10 @@ struct htx_blk *htx_replace_blk_value(struct htx *htx, struct htx_blk *blk, n = htx_get_blk_name(htx, blk); v = htx_get_blk_value(htx, blk); delta = new.len - old.len; + + if (unlikely(htx_get_blk_type(blk) < HTX_BLK_EOH && htx_hdrs_too_big(htx, delta))) + return NULL; + ret = htx_prepare_blk_expansion(htx, blk, delta); if (!ret) return NULL; /* not enough space */ @@ -1020,6 +1034,9 @@ struct htx_blk *htx_replace_header(struct htx *htx, struct htx_blk *blk, return NULL; delta = name.len + value.len - htx_get_blksz(blk); + if (unlikely(htx_hdrs_too_big(htx, delta))) + return NULL; + ret = htx_prepare_blk_expansion(htx, blk, delta); if (!ret) return NULL; /* not enough space */ @@ -1072,6 +1089,10 @@ struct htx_sl *htx_replace_stline(struct htx *htx, struct htx_blk *blk, const st sz = htx_get_blksz(blk); delta = sizeof(*sl) + p1.len + p2.len + p3.len - sz; + + if (unlikely(htx_hdrs_too_big(htx, delta))) + return NULL; + ret = htx_prepare_blk_expansion(htx, blk, delta); if (!ret) return NULL; /* not enough space */