]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: mux-h1: Force close mode for bodyless message announcing a C-L master
authorChristopher Faulet <cfaulet@haproxy.com>
Wed, 22 Apr 2026 14:55:00 +0000 (16:55 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Thu, 23 Apr 2026 15:06:11 +0000 (17:06 +0200)
When dealing with EOH block, we must be sure to force the close mode for
message with no payload but annoncing a non-null content-length.

It is mainly an issue on the server side but it could be encountered on
client side too. Without this fix, a request can be switched to the DONE
state while the server is still expecting the payload. In an ideal world,
this case should not happen. But in conjunction with other bugs, it may lead
to a desynchro between haproxy and the server.

Now, when a non-null content-length is announced but we know we reached the
end of the message, we force the close mode. The only exception is for
bodyless responses (204s, 304s and responses to head requests).

Thanks to Martino Spagnuolo (r3verii) for his detailed report on this issue.

This patch must be backported to all stable version.

src/mux_h1.c

index 527d3495f0cf5bad8123acd6bf128242fa9ec6ae..ae7d8fc72822faa3defb226acf284153d0000f03 100644 (file)
@@ -2864,6 +2864,13 @@ static size_t h1_make_eoh(struct h1s *h1s, struct h1m *h1m, struct htx *htx, siz
                        h1s->flags = (h1s->flags & ~H1S_F_WANT_MSK) | H1S_F_WANT_CLO;
                        TRACE_STATE("force close mode (T-E + HTTP/1.0)", H1_EV_TX_DATA|H1_EV_TX_HDRS, h1s->h1c->conn, h1s);
                }
+               else if ((h1m->flags & H1_MF_CLEN) && h1m->body_len != 0 &&
+                        htx_is_unique_blk(htx, blk) && (htx->flags & HTX_FL_EOM) &&
+                        (!(h1m->flags & H1_MF_RESP) || !(h1s->flags & H1S_F_BODYLESS_RESP))) {
+                       /* C-L but no data for non-bodyless response or for a request: force close */
+                       h1s->flags = (h1s->flags & ~H1S_F_WANT_MSK) | H1S_F_WANT_CLO;
+                       TRACE_STATE("force close mode (C-L without data)", H1_EV_TX_DATA|H1_EV_TX_HDRS, h1s->h1c->conn, h1s);
+               }
 
                /* the conn_mode must be processed. So do it */
                n = ist("connection");