quiche accepts QUIC transport parameters with zero-length values for integer fields (e.g. max_idle_timeout, max_ack_delay). The empty value buffer gets interpreted as varint 0 via the FFI bridge.
RFC 9000 §18.2 requires integer transport parameters to carry a varint value. A zero-byte encoding is not a valid varint.
Example: 0100 (max_idle_timeout with length 0) — quiche treats this as max_idle_timeout=0.
ngtcp2 and lsquic both reject with TRANSPORT_PARAMETER_ERROR.
Comparison:
| Seed |
ngtcp2 |
lsquic |
quiche |
max_idle_timeout empty 0100 |
REJECT |
REJECT |
ACCEPT |
max_ack_delay empty 0b00 |
REJECT |
REJECT |
ACCEPT |
Legal zero 010100 |
ACCEPT |
ACCEPT |
ACCEPT |
Root cause is in quiche/src/transport_params.rs — val.get_varint() on an empty value buffer is treated as 0 instead of an error.
Fix: Reject integer TPs when decoded value length is 0 before calling varint parse.
Found through differential fuzzing (PathDiff v23), also filed with picoquic.
quiche accepts QUIC transport parameters with zero-length values for integer fields (e.g.
max_idle_timeout,max_ack_delay). The empty value buffer gets interpreted as varint 0 via the FFI bridge.RFC 9000 §18.2 requires integer transport parameters to carry a varint value. A zero-byte encoding is not a valid varint.
Example:
0100(max_idle_timeout with length 0) — quiche treats this as max_idle_timeout=0.ngtcp2 and lsquic both reject with TRANSPORT_PARAMETER_ERROR.
Comparison:
01000b00010100Root cause is in
quiche/src/transport_params.rs—val.get_varint()on an empty value buffer is treated as 0 instead of an error.Fix: Reject integer TPs when decoded value length is 0 before calling varint parse.
Found through differential fuzzing (PathDiff v23), also filed with picoquic.