]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: h3: adjust error on PUSH_PROMISE frame reception
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Tue, 26 May 2026 08:53:48 +0000 (10:53 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Tue, 26 May 2026 11:52:03 +0000 (13:52 +0200)
HTTP/3 PUSH_PROMISE frames are systematically rejected with H3 error
FRAME_UNEXPECTED. This is adapted on the server side as a client can
never emit them.

This patch adapts error reporting when haproxy runs as a client. In this
case, server is still forbidden to emit any PUSH_PROMISE as MAX_PUSH_ID
frames are never emitted. In this case, ID_ERROR must be used as an
error code.

This must be backported up to 3.3.

src/h3.c

index 3e28c2e41f8feec3d2a745669c6d50bc3779d7f2..62b69588d327a6a09f29b16c403cbc5e68f0927f 100644 (file)
--- a/src/h3.c
+++ b/src/h3.c
@@ -437,14 +437,16 @@ static int h3_check_frame_valid(struct h3c *h3c, struct qcs *qcs, uint64_t ftype
 
        case H3_FT_PUSH_PROMISE:
                /* RFC 9114 7.2.5. PUSH_PROMISE
+                *
+                * If a PUSH_PROMISE frame is received on the control stream, the client
+                * MUST respond with a connection error of type H3_FRAME_UNEXPECTED.
                 *
                 * A client MUST NOT send a PUSH_PROMISE frame. A server MUST treat the
                 * receipt of a PUSH_PROMISE frame as a connection error of type
                 * H3_FRAME_UNEXPECTED.
                 */
-
-               /* TODO server-side only. */
-               ret = H3_ERR_FRAME_UNEXPECTED;
+               if (h3s->type == H3S_T_CTRL || !conn_is_back(qcs->qcc->conn))
+                       ret = H3_ERR_FRAME_UNEXPECTED;
                break;
 
        default:
@@ -1982,7 +1984,6 @@ static ssize_t h3_rcv_buf(struct qcs *qcs, struct buffer *b, int fin)
                                goto err;
                        }
                        break;
-               case H3_FT_PUSH_PROMISE:
                case H3_FT_MAX_PUSH_ID:
                        /* Not supported */
                        ret = flen;
@@ -1996,6 +1997,18 @@ static ssize_t h3_rcv_buf(struct qcs *qcs, struct buffer *b, int fin)
                        }
                        h3c->flags |= H3_CF_SETTINGS_RECV;
                        break;
+               case H3_FT_PUSH_PROMISE:
+                       /* h3_check_frame_valid() must reject on server side. */
+                       BUG_ON(!conn_is_back(qcs->qcc->conn));
+
+                       /* RFC 9114 7.2.5. PUSH_PROMISE
+                        *
+                        * A client MUST treat
+                        * receipt of a PUSH_PROMISE frame that contains a larger push ID than
+                        * the client has advertised as a connection error of H3_ID_ERROR.
+                        */
+                       ret = H3_ERR_ID_ERROR;
+                       break;
                default:
                        /* RFC 9114 Section 9. Extensions to HTTP/3
                         *