From: Christopher Faulet Date: Mon, 27 Nov 2023 07:23:45 +0000 (+0100) Subject: BUG/MEDIUM: mux-h1: Properly ignore trailers when a content-length is announced X-Git-Tag: v2.9-dev12~84 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b4eaadae84462d42f0b748b882d00c0c4f8d57e8;p=thirdparty%2Fhaproxy.git BUG/MEDIUM: mux-h1: Properly ignore trailers when a content-length is announced It is not possible in H1, but in H2 (and probably H3) it is possible to have trailers at the end of a message while a Content-Length was announced. However, depending if the trailers are received with the last HTX DATA block or the zero-copy forwarding is used or not, an processing error may be triggered, leading to a 500-internal-error. To fix the issue, when a content-length is announced and all the payload was processed, we switch the message to H1_MSG_DONE state only if the end-of-message was also reported (HTX_FL_EOM flag set). Otherwise, it is switched to H1_MSG_TRAILERS state to be able to properly ignored the trailers, if so. The patch must be backported as far as 2.4. Be careful, this part was highly refactored. The patch will have to be adapted to be backported. --- diff --git a/src/mux_h1.c b/src/mux_h1.c index 63eb78e1c3..73338774cb 100644 --- a/src/mux_h1.c +++ b/src/mux_h1.c @@ -2485,7 +2485,7 @@ static size_t h1_make_eoh(struct h1s *h1s, struct h1m *h1m, struct htx *htx, siz } else if (!chunk_memcat(&outbuf, "\r\n", 2)) goto full; - h1m->state = H1_MSG_DONE; + h1m->state = ((htx->flags & HTX_FL_EOM) ? H1_MSG_DONE : H1_MSG_TRAILERS); } else { if (!chunk_memcat(&outbuf, "\r\n", 2)) @@ -2577,7 +2577,7 @@ static size_t h1_make_data(struct h1s *h1s, struct h1m *h1m, struct buffer *buf, } h1m->curr_len -= count; if (!h1m->curr_len) - h1m->state = H1_MSG_DONE; + h1m->state = (eom ? H1_MSG_DONE : H1_MSG_TRAILERS); } else if (h1m->flags & H1_MF_CHNK) { /* The message is chunked. We need to check if we must @@ -4530,7 +4530,7 @@ static size_t h1_done_ff(struct stconn *sc) h1m->curr_len -= total; if (!h1m->curr_len && (h1m->flags & H1_MF_CLEN)) - h1m->state = H1_MSG_DONE; + h1m->state = ((sd->iobuf.flags & IOBUF_FL_EOI) ? H1_MSG_DONE : H1_MSG_TRAILERS); else if (!h1m->curr_len && (h1m->flags & H1_MF_CHNK)) { if (h1m->state == H1_MSG_DATA) h1m->state = H1_MSG_CHUNK_CRLF;