From 529a8dbfbac8efbda5b0bdbe1abcf81f6b749d02 Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Mon, 5 Jan 2026 19:28:39 +0100 Subject: [PATCH] BUG/MEDIUM: mux-h1: Take care to update value during zero-copy forwarding Since the extra field was removed from the HTX structure, a regression was introduced when forwarding of chunked messages. The value was not decreased as it should be when data were sent via the zero-copy forwarding. Because of this bug, it was possible to announce a chunk size larger than the chunk data sent. To fix the bug, an helper function was added to properly update the value when a chunk size is emitted. This function is now called when new chunk is announced, including during zero-copy forwarding. As a workaround, "tune.disable-zero-copy-forwarding" or just "tune.h1.zero-copy-fwd-send off" can be set in the global section. This patch should fix the issue #3230. It must be backported to 3.3. --- src/mux_h1.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/mux_h1.c b/src/mux_h1.c index 8e80af974..3d88ad8b1 100644 --- a/src/mux_h1.c +++ b/src/mux_h1.c @@ -871,6 +871,14 @@ static inline size_t h1s_data_pending(const struct h1s *h1s) return ((h1m->state == H1_MSG_DONE) ? 0 : b_data(&h1s->h1c->ibuf)); } +static inline void h1s_consume_kop(struct h1s *h1s, size_t count) +{ + if (h1s->sd->kop > count) + h1s->sd->kop -= count; + else + h1s->sd->kop = 0; +} + /* Creates a new stream connector and the associate stream. is used as input * buffer for the stream. On success, it is transferred to the stream and the * mux is no longer responsible of it. On error, is unchanged, thus the @@ -3093,7 +3101,7 @@ static size_t h1_make_data(struct h1s *h1s, struct h1m *h1m, struct buffer *buf, goto error; } h1m->curr_len = (h1s->sd->kop ? h1s->sd->kop : count); - h1s->sd->kop = 0; + h1s_consume_kop(h1s, h1m->curr_len); /* Because chunk meta-data are prepended, the chunk size of the current chunk * must be handled before the end of the previous chunk. @@ -3185,7 +3193,7 @@ static size_t h1_make_data(struct h1s *h1s, struct h1m *h1m, struct buffer *buf, h1m->curr_len = 0; goto full; } - h1s->sd->kop = 0; + h1s_consume_kop(h1s, h1m->curr_len); h1m->state = H1_MSG_DATA; } @@ -4959,6 +4967,7 @@ static size_t h1_nego_ff(struct stconn *sc, struct buffer *input, size_t count, goto out; } h1m->curr_len = count; + h1s_consume_kop(h1s, h1m->curr_len); } else { /* The producer does not know the chunk size, thus this will be emitted at the @@ -5094,11 +5103,13 @@ static size_t h1_done_ff(struct stconn *sc) struct buffer buf = b_make(b_orig(&h1c->obuf), b_size(&h1c->obuf), b_peek_ofs(&h1c->obuf, b_data(&h1c->obuf) - sd->iobuf.data + sd->iobuf.offset), sd->iobuf.data); + h1_prepend_chunk_size(&buf, sd->iobuf.data, sd->iobuf.offset - ((h1m->state == H1_MSG_CHUNK_CRLF) ? 2 : 0)); if (h1m->state == H1_MSG_CHUNK_CRLF) h1_prepend_chunk_crlf(&buf); b_add(&h1c->obuf, sd->iobuf.offset); h1m->state = H1_MSG_CHUNK_CRLF; + h1s_consume_kop(h1s, sd->iobuf.data); } total = sd->iobuf.data; -- 2.47.3