From: Willy Tarreau Date: Mon, 27 Jul 2026 09:42:31 +0000 (+0200) Subject: BUG/MINOR: http-act: restore the response buffer state in the early-hint action X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=0b329bbe6a0310773a7a8d262c9902fee4705fd1;p=thirdparty%2Fhaproxy.git BUG/MINOR: http-act: restore the response buffer state in the early-hint action http_action_early_hint() starts with: struct htx *htx = htx_from_buf(&res->buf); htx_from_buf() marks the underlying buffer as full (b_data = b_size) and, as documented, it is the caller's responsibility to call htx_to_buf() to update it back. The function never does it. On the success path this is harmless because the HTX message is not empty, which is exactly what a full buffer represents, and on the error path channel_htx_truncate() takes care of it. But the very first test of the function is: if (!(s->txn.http->req.flags & HTTP_MSGF_VER_11)) goto leave; so for an HTTP/1.0 client, where no 103 response may be emitted, the response buffer is left flagged as containing b_size bytes of data while the HTX message is empty, until some other code path happens to call htx_to_buf() on it. Any code looking at b_data(&res->buf) in between sees a full response buffer. No misbehaviour could be observed (the HTX-aware helpers all work on the HTX message, not on b_data), but leaving the buffer in a state that contradicts its contents is an accident waiting to happen. Let's simply call htx_to_buf() on the leave path. It is a no-op for the other two paths since the message is either non-empty or was already truncated. This should be backported to all supported versions. --- diff --git a/src/http_act.c b/src/http_act.c index d4c68e223..0bb7b05f7 100644 --- a/src/http_act.c +++ b/src/http_act.c @@ -1389,6 +1389,11 @@ static enum act_return http_action_early_hint(struct act_rule *rule, struct prox } leave: + /* the buffer was marked as full by htx_from_buf() above, it must be + * updated back, especially on the HTTP/1.0 path where the HTX message + * was left untouched and empty. + */ + htx_to_buf(htx, &res->buf); free_trash_chunk(value); return ret;