]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: h3: handle errors on HEADERS parsing/QPACK decoding
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 30 Jun 2022 08:04:42 +0000 (10:04 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 30 Jun 2022 09:51:06 +0000 (11:51 +0200)
Emit a CONNECTION_CLOSE if HEADERS parsing function returns an error.
This is useful to remove previous ABORT_NOW guards.

For the moment, the whole connection is closed. In the future, it may be
justified to only reset the faulting stream in some cases. This requires
the implementation of RESET_STREAM emission.

src/h3.c

index c15adf02973345b140934036e6e4d22529843846..60c003bfe829ef01a7734b4958335819445bdae8 100644 (file)
--- a/src/h3.c
+++ b/src/h3.c
@@ -326,6 +326,8 @@ static int h3_is_frame_valid(struct h3c *h3c, struct qcs *qcs, uint64_t ftype)
 static ssize_t h3_headers_to_htx(struct qcs *qcs, const struct buffer *buf,
                                  uint64_t len, char fin)
 {
+       struct h3s *h3s = qcs->ctx;
+       struct h3c *h3c = h3s->h3c;
        struct buffer htx_buf = BUF_NULL;
        struct buffer *tmp = get_trash_chunk();
        struct htx *htx = NULL;
@@ -335,14 +337,17 @@ static ssize_t h3_headers_to_htx(struct qcs *qcs, const struct buffer *buf,
        struct ist meth = IST_NULL, path = IST_NULL;
        //struct ist scheme = IST_NULL, authority = IST_NULL;
        struct ist authority = IST_NULL;
-       int hdr_idx;
+       int hdr_idx, ret;
 
        TRACE_ENTER(H3_EV_RX_FRAME|H3_EV_RX_HDR, qcs->qcc->conn, qcs);
 
        /* TODO support buffer wrapping */
        BUG_ON(b_head(buf) + len >= b_wrap(buf));
-       if (qpack_decode_fs((const unsigned char *)b_head(buf), len, tmp,
-                           list, sizeof(list) / sizeof(list[0])) < 0) {
+       ret = qpack_decode_fs((const unsigned char *)b_head(buf), len, tmp,
+                           list, sizeof(list) / sizeof(list[0]));
+       if (ret < 0) {
+               TRACE_ERROR("QPACK decoding error", H3_EV_RX_FRAME|H3_EV_RX_HDR, qcs->qcc->conn, qcs);
+               h3c->err = -ret;
                return -1;
        }
 
@@ -375,8 +380,10 @@ static ssize_t h3_headers_to_htx(struct qcs *qcs, const struct buffer *buf,
        flags |= HTX_SL_F_XFER_LEN;
 
        sl = htx_add_stline(htx, HTX_BLK_REQ_SL, flags, meth, path, ist("HTTP/3.0"));
-       if (!sl)
+       if (!sl) {
+               h3c->err = H3_INTERNAL_ERROR;
                return -1;
+       }
 
        if (fin)
                sl->flags |= HTX_SL_F_BODYLESS;
@@ -404,8 +411,10 @@ static ssize_t h3_headers_to_htx(struct qcs *qcs, const struct buffer *buf,
        if (fin)
                htx->flags |= HTX_FL_EOM;
 
-       if (!qc_attach_sc(qcs, &htx_buf))
+       if (!qc_attach_sc(qcs, &htx_buf)) {
+               h3c->err = H3_INTERNAL_ERROR;
                return -1;
+       }
 
        /* buffer is transferred to the stream connector and set to NULL
         * except on stream creation error.
@@ -651,8 +660,14 @@ static ssize_t h3_decode_qcs(struct qcs *qcs, struct buffer *b, int fin)
                        break;
                case H3_FT_HEADERS:
                        ret = h3_headers_to_htx(qcs, b, flen, last_stream_frame);
-                       /* TODO handle error reporting. Stream closure required. */
-                       if (ret < 0) { ABORT_NOW(); }
+                       if (ret < 0) {
+                               /* TODO for some error, it may be preferable to
+                                * only close the stream once RESET_STREAM is
+                                * supported.
+                                */
+                               qcc_emit_cc_app(qcs->qcc, h3c->err);
+                               return -1;
+                       }
                        break;
                case H3_FT_CANCEL_PUSH:
                case H3_FT_PUSH_PROMISE: