]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: qpack: correctly deal with too large decoded numbers
authorFrederic Lecaille <flecaille@haproxy.com>
Thu, 5 Mar 2026 13:46:51 +0000 (14:46 +0100)
committerFrederic Lecaille <flecaille@haproxy.com>
Thu, 5 Mar 2026 14:02:02 +0000 (15:02 +0100)
Same fix as this one for hpack:

7315428615 ("BUG/MEDIUM: hpack: correctly deal with too large decoded numbers")

Indeed, the encoding of integers for QPACK is the same as for HPACK but for 64 bits
integers.

Must be backported as far as 2.6.

src/qpack-dec.c

index d1afcd6b1a6cfc26f66a6393bd31a0278073e9fb..04f949029d5706a1f77c8f0b6519295a263c26c9 100644 (file)
@@ -63,6 +63,7 @@ static uint64_t qpack_get_varint(const unsigned char **buf, uint64_t *len_in, in
        uint64_t ret = 0;
        int len = *len_in;
        const uint8_t *raw = *buf;
+       uint64_t v, max = ~0;
        uint8_t shift = 0;
 
        if (len == 0)
@@ -73,24 +74,26 @@ static uint64_t qpack_get_varint(const unsigned char **buf, uint64_t *len_in, in
        if (ret != (uint64_t)((1ULL << b) - 1))
                goto end;
 
-       while (len && (*raw & 128)) {
-               ret += ((uint64_t)*raw++ & 127) << shift;
-               shift += 7;
+       do {
+               if (!len)
+                       goto too_short;
+               v = *raw++;
                len--;
-       }
-
-       /* last 7 bits */
-       if (!len)
-               goto too_short;
-
-       len--;
-       ret += ((uint64_t)*raw++ & 127) << shift;
+               if (v & 127) { // make UBSan happy
+                       if ((v & 127) > max)
+                               goto too_large;
+                       ret += (v & 127) << shift;
+               }
+               max >>= 7;
+               shift += 7;
+       } while (v & 128);
 
  end:
        *buf = raw;
        *len_in = len;
        return ret;
 
+ too_large:
  too_short:
        *len_in = (uint64_t)-1;
        return 0;