From 7c6159a28de1e3913deb601ad1ba5017adf9c027 Mon Sep 17 00:00:00 2001 From: Amaury Denoyelle Date: Fri, 13 Nov 2026 16:55:32 +0100 Subject: [PATCH] BUG/MEDIUM: mux_quic: fix Rx flow control increment on RESET_STREAM Since the following patch, on RESET_STREAM frame reception, its final size field is used to account for non-received data in the connection flow control. 1b2bd2aeef08209664585e4b3f230744835257d9 BUG/MINOR: mux_quic: report conn error on RESET_STREAM fctl violation This addition is not correct as it uses the read offset of the QCS instance instead of the maximum offset already checked in flow control. Over time, there is a risk to report a flow control violation despite legitimate client usage. Fix this by using the proper QCS field in the flow control calculation check. Note that accounted data for MAX_DATA emission is still based on the QCS read offset though. This must be backported up to 2.8, after the above-mentioned patch. --- src/mux_quic.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/mux_quic.c b/src/mux_quic.c index 9a72d7ca5..89770d37f 100644 --- a/src/mux_quic.c +++ b/src/mux_quic.c @@ -2377,7 +2377,7 @@ int qcc_recv_reset_stream(struct qcc *qcc, uint64_t id, uint64_t err, uint64_t f struct qcs *qcs; struct qc_stream_rxbuf *b; int prev_glitches = qcc->glitches; - uint64_t to_consume; + uint64_t extra_data; TRACE_ENTER(QMUX_EV_QCC_RECV, qcc->conn); @@ -2426,12 +2426,12 @@ int qcc_recv_reset_stream(struct qcc *qcc, uint64_t id, uint64_t err, uint64_t f goto err; } - /* Discarded data to account for in connection flow control. */ - to_consume = final_size - qcs->rx.offset; + /* Discarded data to check against the connection flow control. */ + extra_data = final_size - qcs->rx.offset_max; /* Ensure final size respects the current stream and connection flow control limits. */ if (final_size > qcs->rx.msd || - qcc->lfctl.offsets_recv + to_consume > qcc->lfctl.md) { + qcc->lfctl.offsets_recv + extra_data > qcc->lfctl.md) { TRACE_ERROR("flow control violation on RESET_STREAM final size", QMUX_EV_QCC_RECV|QMUX_EV_QCS_RECV|QMUX_EV_PROTO_ERR, qcc->conn, qcs); qcc_set_error(qcc, QC_ERR_FLOW_CONTROL_ERROR, 0, @@ -2439,7 +2439,7 @@ int qcc_recv_reset_stream(struct qcc *qcc, uint64_t id, uint64_t err, uint64_t f goto err; } - qcc->lfctl.offsets_recv += to_consume; + qcc->lfctl.offsets_recv += extra_data; qcs->flags |= QC_SF_SIZE_KNOWN|QC_SF_RECV_RESET; qcs_close_remote(qcs); @@ -2460,7 +2460,8 @@ int qcc_recv_reset_stream(struct qcc *qcc, uint64_t id, uint64_t err, uint64_t f qcs_free_rxbuf(qcs, b); } - qcc_account_for_conn_fctl(qcc, to_consume); + /* Account into conn fctl not-yet-read and extra bytes from final size */ + qcc_account_for_conn_fctl(qcc, final_size - qcs->rx.offset); /* Ensure final size checks coherence for future STREAM frames. */ qcs->rx.offset_max = final_size; -- 2.47.3