]> git.kaiwu.me - haproxy.git/commitdiff
BUG/MEDIUM: mux_quic: ensure FIN is reported after Rx data transfer
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Tue, 20 Oct 2026 13:48:15 +0000 (15:48 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 21 Oct 2026 12:09:41 +0000 (14:09 +0200)
Multiple Rx buffers may be allocated per QCS instance. Each buffer is
parsed separately. If necessary, data may be transferred from the next
buffer when the parser is blocked in the middle of a frame.

This operation causes an issue if only two buffers remains and all data
with FIN are already received. In this case, QCS is not yet remotely
closed during qcc_recv(). If all content from the next buffer is
transferred, close is still not set. This prevents HTX EOM from being
set, which result in a stream closed after timeout.

Fix this by calling qcs_close_remote() in qcs_transfer_rx_data() if the
above scenario described is encountered. This is sufficient to produce
HTX EOM signal as parsing will be restarted via a new call to app_ops
rcv_buf with <fin> parameter now set.

If the next buffer has been emptied but is not truncated, it is still
reinserted in the rxbuf tree. This could result in a second
qcs_close_remote() call for the same QCS which is forbidden. Thus, this
patch depends on the below fix to prevent this situation.

  1dcaae1caf62b97789e77acb18c7b22753391d45
  BUG/MEDIUM: mux_quic: fix crash on QCS double remote close

This should be backported up to 3.2 after a period of observation, as
multiple Rx buffers were implemented there.

src/mux_quic.c

index 82fe6c393fee3cc66794368344d558ebaecc01fe..7c31594b2b09b18c95346113af9ce7f2f3011fc1 100644 (file)
@@ -1312,6 +1312,13 @@ static int qcs_transfer_rx_data(struct qcs *qcs, struct qc_stream_rxbuf *rxbuf)
                        bdata_ctr_bdec(&qcs->rx.data);
                }
 
+               /* Close QCS remotely if all data with FIN already stored in
+                * current buf. Similar to what qcc_decode_qcs() already does
+                * after consume.
+                */
+               if ((qcs->flags & QC_SF_SIZE_KNOWN) && qcs->rx.offset_max == rxbuf->off_end)
+                       qcs_close_remote(qcs);
+
                ret = 0;
        }