PQ Crypta Logo

Encoder stream setting a dynamic table capacity above the client's limit

Close the connection with QPACK_ENCODER_STREAM_ERROR (0x201). §4.3.1 says the new capacity "MUST be lower than or equal to the limit" the decoder advertised, and that a decoder "MUST treat a new dynamic table capacity value that exceeds this limit as a connection error of type QPACK_ENCODER_STREAM_ERROR". Unlike the other two dynamic-table tests, this one runs against every client, because the capacity asked for is computed from the one that client advertised: one byte more, whatever it said. It was a fixed 4096 until 2026-09-20, which exceeded the zero every client then advertised and would have exceeded nothing at all for a client that granted a 4096-byte table.

PQ CRYPTA PLATFORM

🏠 Main

📰 News

👤 Account

⟨ QUANTUM ERROR PORTAL ⟩

Navigate the Error Dimensions

Jump to an anomaly59

Every one of these is a page: what the server emits, the clause it is judged against, and how each client answered. The full list carries the verdict tallies too.

h-qpack-encoder-overflow · RFC 9204 §4.3.1, §6 · correctness · layer http3 · udp/4502 · MUST

Passing this means: Rejected something invalid, with the code the RFC names.

Anomaly type: other_uni_stream

How each client answered

ClientVersionVerdictWhat happened
curl libcurl/8.23.0 ngtcp2/1.25.0 Fail Objected at the QUIC layer (rejected at the QUIC layer with INTERNAL_ERROR) instead of signalling the HTTP/3 error. The violation was detected and rejected, which is the right instinct; §8.1 requires an HTTP/3 connection error to be carried in an application close, and this test names 0x201. A transport close carries no HTTP/3 code at all, so a peer has no way to learn what was wrong.
quinn noq fork (189b0ed) Pass Rejected with the required error code 0x201.
aioquic 1.3.0 (PyPI wheel) Pass Rejected with the required error code 0x201.
chromium build 1248 Pass Rejected with the required error code 0x201.
quic-go quic-go v0.61.0 (h1:9So2anK4Tp22) Unsupported does not read the QPACK encoder stream, so the invalid instruction on it never reached its decoder. This endpoint filled the flow-control window the client granted on that stream and no credit came back while the client stayed connected -- a client that had consumed the stream would have had to grant more.
quiche 0.30.0 (1c8e976) Fail Accepted a protocol violation and carried on. The anomaly was on the QPACK encoder stream, and this client extended flow-control credit on it -- a receiver extends credit on a stream only once its application has consumed what was already there, so the bytes were read rather than merely delivered. This should have been rejected.
neqo 0.31.1 (cac2b74) Pass Rejected with the required error code 0x201.
picoquic 8162550 Fail Accepted a protocol violation and carried on. The anomaly was on the QPACK encoder stream, and this client extended flow-control credit on it -- a receiver extends credit on a stream only once its application has consumed what was already there, so the bytes were read rather than merely delivered. This should have been rejected.
ngtcp2 3c23148 Pass Rejected with the required error code 0x201.
lsquic 4.9.4 (2b30189) Pass Rejected with the required error code 0x201.
xquic 2060a44 Fail Rejected, but with error 0x106 where the specification requires 0x201. The violation was detected; the code reported is wrong.
msquic 2.7.0 (7e6525d) Fail Accepted a protocol violation and carried on. The anomaly was on the QPACK encoder stream, and this client extended flow-control credit on it -- a receiver extends credit on a stream only once its application has consumed what was already there, so the bytes were read rather than merely delivered. This should have been rejected.
quico 0.7.0 (npm) Pass Rejected with the required error code 0x201.

What the clause requires

Close the connection with QPACK_ENCODER_STREAM_ERROR (0x201). §4.3.1 says the new capacity "MUST be lower than or equal to the limit" the decoder advertised, and that a decoder "MUST treat a new dynamic table capacity value that exceeds this limit as a connection error of type QPACK_ENCODER_STREAM_ERROR". Unlike the other two dynamic-table tests, this one runs against every client, because the capacity asked for is computed from the one that client advertised: one byte more, whatever it said. It was a fixed 4096 until 2026-09-20, which exceeded the zero every client then advertised and would have exceeded nothing at all for a client that granted a 4096-byte table.

Judged against RFC 9204.

Run this one yourself

Every test is reachable from your own client. Nothing here needs an account.

curl -s https://conformance.pqcrypta.com/catalog.json \
  | jq '.tests[] | select(.id == "h-qpack-encoder-overflow")'