]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: qpack: support bigger prefix-integer encoding
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 30 May 2022 12:24:40 +0000 (14:24 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 30 May 2022 12:30:05 +0000 (14:30 +0200)
Prefix-integer encoding function was incomplete. It was not able to deal
correctly with value encoded on more than 2 bytes. This maximum value depends
on the size of the prefix, but value greater than 254 were all impacted.

Most notably, this change is required to support header name/value with
sizeable length. Previously, length was incorrectly encoded. The client thus
closed the connection with QPACK_DECOMPRESSION_ERROR.

src/qpack-enc.c

index 5c4b99f4109a07356c9857d4252fda7ecd064c3e..59bb97fb663f5315ba4fd12ffde8b3df812b051a 100644 (file)
@@ -28,22 +28,37 @@ static size_t qpack_get_prefix_int_size(int i, int prefix_size)
  *
  * Returns 0 if success else non-zero.
  */
-static int qpack_encode_prefix_integer(struct buffer *out, int i, int prefix_size, unsigned char before_prefix)
+static int qpack_encode_prefix_integer(struct buffer *out, int i,
+                                       int prefix_size,
+                                       unsigned char before_prefix)
 {
-       BUG_ON(!prefix_size);
+       const int mod = (1 << prefix_size) - 1;
+       BUG_ON_HOT(!prefix_size);
 
-       if (i < (1 << prefix_size) - 1) {
+       if (i < mod) {
                if (b_room(out) < 1)
                        return 1;
 
                b_putchr(out, before_prefix | i);
        }
        else {
-               if (b_room(out) < 2)
+               int to_encode = i - mod;
+               const size_t sz = to_encode / mod;
+
+               if (b_room(out) < sz)
                        return 1;
 
-               b_putchr(out, before_prefix | ((1 << prefix_size) - 1));
-               b_putchr(out, i - ((1 << prefix_size) - 1));
+               b_putchr(out, before_prefix | mod);
+               while (1) {
+                       if (to_encode > 0x7f) {
+                               b_putchr(out, 0x80 | (to_encode & 0x7f));
+                               to_encode >>= 7;
+                       }
+                       else {
+                               b_putchr(out, to_encode & 0x7f);
+                               break;
+                       }
+               }
        }
 
        return 0;