]> git.kaiwu.me - haproxy.git/commitdiff
BUG/MEDIUM: mux-h1: don't swap buffers when transferring data with a reserved offset
authorChristopher Faulet <cfaulet@haproxy.com>
Wed, 7 Oct 2026 09:37:59 +0000 (11:37 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Fri, 16 Oct 2026 17:10:27 +0000 (19:10 +0200)
In h1_nego_ff(), when the output is chunked, some room may be reserved to emit
the chunk size later, in h1_done_ff(). However, when the producer's buffer is
not empty, a first copy may be performed via the b_xfer() function. At this
stage the buffers may be swapped while it is not expected. The reserved space
may be moved and the head position lost.

In practice, it is pretty hard to hit the bug.

Now the data are always copied when room is reserved, using b_force_xfer().
b_xfer() is still used when no room is reserved.

This was introduced by commit e8cc8a60b in 3.1 (backported to 3.0). It
must be backported as far as 3.0.

src/mux_h1.c

index dc50929e78bfb793b144cc8afbe755208d18efb5..12eb43d89858d5add8e3e9fc9e6ef26914954ab0 100644 (file)
@@ -5211,9 +5211,14 @@ static size_t h1_nego_ff(struct stconn *sc, struct buffer *input, size_t count,
 
                if (xfer > b_data(input))
                        xfer = b_data(input);
-               h1c->obuf.head += offset;
-               h1s->sd->iobuf.data = b_xfer(&h1c->obuf, input, xfer);
-               h1c->obuf.head -= offset;
+               if (offset) {
+                       /* Room is reserved the chunk size, force the xfer to avoid any buffer swap */
+                       h1c->obuf.head += offset;
+                       h1s->sd->iobuf.data = b_force_xfer(&h1c->obuf, input, xfer);
+                       h1c->obuf.head -= offset;
+               }
+               else
+                       h1s->sd->iobuf.data = b_xfer(&h1c->obuf, input, xfer);
 
                /* Cannot forward more data, wait for room */
                if (b_data(input))