]> git.kaiwu.me - haproxy.git/commitdiff
BUG/MINOR: h3: handle unknown frame type on request stream as specified
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 4 Sep 2026 07:55:36 +0000 (09:55 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Tue, 8 Sep 2026 13:02:29 +0000 (15:02 +0200)
HTTP/3 specification allows the ability to define extra frame types. An
implementation must silently ignored unknown frame types.

Prior to this patch, haproxy stack completely discards an unknown frame.
However, on a request stream, if this acts as the last stream frame, it
would lead to a missing HTX EOM before the stream is closed on timeout.

Now, an HTX EOM is properly reported to the upper layer, which ensures
the request can successfully be achieved. A reset is emitted though if
no headers were previously received as in this case the HTTP request is
incomplete.

This must be backported up to 2.6.

src/h3.c

index 306a3302badbbb5ee1d5b99c78be083cacaa40a3..01f723bda50ec203b0fb57251cfc04202530b608 100644 (file)
--- a/src/h3.c
+++ b/src/h3.c
@@ -2215,12 +2215,26 @@ static ssize_t h3_rcv_buf(struct qcs *qcs, struct buffer *b, int fin)
                        ret = flen;
                        break;
                default:
-                       /* RFC 9114 Section 9. Extensions to HTTP/3
-                        *
-                        * Implementations MUST discard frames [...] that have unknown
-                        * or unsupported types.
-                        */
-                       ret = flen;
+                       if (quic_stream_is_bidi(qcs->id) && last_stream_frame) {
+                               /* No header seen, HTTP message is malformed. */
+                               if (h3s->st_req == H3S_ST_REQ_BEFORE) {
+                                       TRACE_ERROR("malformed request closed by unknown frame without any header", H3_EV_RX_FRAME, qcs->qcc->conn, qcs);
+                                       h3s->err = H3_ERR_MESSAGE_ERROR;
+                                       qcc_report_glitch(qcs->qcc, 1);
+                                       ret = -1;
+                               }
+
+                               /* Reuse wrapper function to easily set EOM on HTX message. */
+                               if (qcs_http_handle_standalone_fin(qcs)) {
+                                       TRACE_ERROR("cannot set EOM", H3_EV_RX_FRAME, qcs->qcc->conn, qcs);
+                                       qcc_set_error(qcs->qcc, H3_ERR_INTERNAL_ERROR, 1,
+                                                     muxc_tevt_type_internal_err);
+                                       goto err;
+                               }
+                       }
+
+                       if (ret >= 0)
+                               ret = flen;
                        break;
                }