Parsing QPACK varints with excessive continuation bytes increases shift
by 7 on each iteration. When shift reaches 63 or higher, evaluating:
(v & 127) > (limit - ret) >> shift
executes a bitwise shift on a 64-bit integer with an out-of-range count,
which is Undefined Behavior in C.
Fix this by jumping to too_large label if shift >= 63 before the shift runs.
Thank you to @OneZ3r0 for having reported this issue.
Should be backported to all versions.
if (!len)
goto too_short;
+ /* A valid QPACK varint is at most 62 bits. Zero-payload
+ * continuations must not drive shift past 63, otherwise the
+ * "(limit - ret) >> shift" check below runs with an out-of-range
+ * shift count (C undefined behavior).
+ */
+ if (shift >= 63)
+ goto too_large;
v = *raw++;
len--;
- /* This check is sufficient to prevent any overflow
- * and implicitly limits shift to 63.
- */
+ /* This check is sufficient to prevent any overflow. */
if ((v & 127) > (limit - ret) >> shift)
goto too_large;