]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: h3: fix access to QCS <sd> definitely quic-interop
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 10 Dec 2025 10:57:34 +0000 (11:57 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 10 Dec 2025 11:04:37 +0000 (12:04 +0100)
The previous patch tried to fix access to QCS <sd> member, as the latter
is not always allocated anymore on the frontend side.

  a15f0461a016a664427f5aaad2227adcc622c882
  BUG/MEDIUM: h3: do not access QCS <sd> if not allocated

In particular, access was prevented after HEADERS parsing in case
h3_req_headers_to_htx() returned an error, which indicates that the
stream-endpoint allocation was not performed. However, this still is not
enough when QCS instance is already closed at this step. Indeed, in this
case, h3_req_headers_to_htx() returns OK but stream-endpoint allocation
is skipped as an optimization as no data exchange will be performed.

To definitely fix this kind of problems, add checks on qcs <sd> member
before accessing it in H3 layer. This method is the safest one to ensure
there is no NULL dereferencement.

This should fix github issue #3211.

This must be backported along the above mentionned patch.

src/h3.c

index c0a51d365c344bd9ce06468ee5c5a5affb2e33a2..79266457d6756453194f197fdb2617f0f185a060 100644 (file)
--- a/src/h3.c
+++ b/src/h3.c
@@ -1784,11 +1784,8 @@ static ssize_t h3_rcv_buf(struct qcs *qcs, struct buffer *b, int fin)
                                        if (h3_check_body_size(qcs, (fin && flen == b_data(b))))
                                                break;
                                }
-                               else {
-                                       /* content-length not present, update estimated payload length.
-                                        * <qcs.sd> is valid here as HEADERS frame were already parsed,
-                                        * guaranteed by h3_check_frame_valid().
-                                        */
+                               else if (qcs->sd) {
+                                       /* content-length not present, update estimated payload length. */
                                        qcs->sd->kip = h3s->data_len;
                                }
                        }
@@ -1853,9 +1850,10 @@ static ssize_t h3_rcv_buf(struct qcs *qcs, struct buffer *b, int fin)
                                }
 
                                /* Update estimated payload with content-length value if present.
-                                * <sd> must be allocated on h3_req_headers_to_htx() success.
+                                * On FE side, <sd> may be NULL on h3_req_headers_to_htx()
+                                * error or if stream is already closed.
                                 */
-                               if (ret >= 0 && h3s->flags & H3_SF_HAVE_CLEN)
+                               if (qcs->sd && h3s->flags & H3_SF_HAVE_CLEN)
                                        qcs->sd->kip = h3s->body_len;
                        }
                        else {