BUG/MEDIUM: h3: trim whitespaces in header value prior to QPACK encoding
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 16 Apr 2025 15:29:41 +0000 (17:29 +0200)
committerAurelien DARRAGON <adarragon@haproxy.com>
Thu, 17 Apr 2025 12:57:03 +0000 (14:57 +0200)
This commit does a similar job than the previous one, but it acts now on
the response path. Any leading or trailing whitespaces characters from a
HTX block header value are removed, prior to the header encoding via
QPACK.

This must be backported up to 2.6.

(cherry picked from commit bd3587574dae43cc019d8e9998e0996c75550de4)
Signed-off-by: Aurelien DARRAGON <adarragon@haproxy.com>
(cherry picked from commit a4f7bfa029ada954c8fae75c1426555a3a4012d4)
[ada: ctx adjt]
Signed-off-by: Aurelien DARRAGON <adarragon@haproxy.com>

src/h3.c

index bfa1ea2..9745611 100644 (file)
--- a/src/h3.c
+++ b/src/h3.c
@@ -1583,6 +1583,29 @@ static int h3_control_send(struct qcs *qcs, void *ctx)
        return -1;
 }
 
+/* Encode header field name <n> value <v> into <buf> buffer using QPACK. Strip
+ * any leading/trailing WS in value prior to encoding.
+ *
+ * Returns 0 on success else non zero.
+ */
+static int h3_encode_header(struct buffer *buf,
+                            const struct ist n, const struct ist v)
+{
+       struct ist v_strip;
+       char *ptr;
+
+       /* trim leading/trailing LWS */
+       for (v_strip = v; istlen(v_strip); --v_strip.len) {
+               ptr = istptr(v_strip);
+               if (unlikely(HTTP_IS_LWS(*ptr)))
+                       ++v_strip.ptr;
+               else if (!unlikely(HTTP_IS_LWS(ptr[istlen(v_strip) - 1])))
+                       break;
+       }
+
+       return qpack_encode_header(buf, n, v_strip);
+}
+
 static int h3_resp_headers_send(struct qcs *qcs, struct htx *htx)
 {
        int err;
@@ -1693,7 +1716,7 @@ static int h3_resp_headers_send(struct qcs *qcs, struct htx *htx)
                        list[hdr].v = ist("trailers");
                }
 
-               if (qpack_encode_header(&headers_buf, list[hdr].n, list[hdr].v))
+               if (h3_encode_header(&headers_buf, list[hdr].n, list[hdr].v))
                        goto err;
        }
 
@@ -1847,7 +1870,7 @@ static int h3_resp_trailers_send(struct qcs *qcs, struct htx *htx)
                        continue;
                }
 
-               if (qpack_encode_header(&headers_buf, list[hdr].n, list[hdr].v)) {
+               if (h3_encode_header(&headers_buf, list[hdr].n, list[hdr].v)) {
                        TRACE_STATE("not enough room for all trailers", H3_EV_TX_FRAME|H3_EV_TX_HDR, qcs->qcc->conn, qcs);
                        if (qcc_release_stream_txbuf(qcs))
                                goto end;