bd192fc649
Closes the remaining items from the round-2 audit.
Driver send-loop PTO timer:
Loop suspends on `withTimeoutOrNull(ptoMillis) { sendWakeup.receive() }`
instead of unconditional receive. PTO doubles on each consecutive timeout
up to 60s; resets to 1s on any wakeup.
Without this, a single lost ClientHello with no inbound traffic to drive
wakeups left the connection wedged forever. The PTO wake now gives the
writer a chance to re-emit on retransmission.
JdkCertificateValidator hostname matching:
- IDN.toASCII normalization on both the cert SAN and the input host so
a SAN of `xn--bcher-kva.de` matches an input of `bücher.de`.
- IPv6 literals compared via InetAddress.getByName().hostAddress so
`::1` and `0:0:0:0:0:0:0:1` compare equal.
- Wildcard public-suffix-label rejection: requires the suffix to contain
at least 2 dots, so `*.com` is rejected even if a misbehaving CA
issued such a cert.
QpackHuffman.decode O(N×256) → O(N×L) where L is the number of distinct
code lengths (≤ 26):
Previously the inner loop scanned all 256 symbols per output byte. Now
it walks length buckets in ascending order and does a HashMap lookup at
each. For ASCII text the hot path matches at length 5-8.
Http3FrameReader.push + CapsuleReader.push amortized compaction:
Was O(N) memcpy on every push → O(N²) over the lifetime of a long-lived
stream. Now compacts only when consumed prefix is at least half the
buffer, giving amortized O(1) per byte.
All :quic:jvmTest + :nestsClient:jvmTest pass.
End of round-2 audit fixes. The branch now passes:
- Every RFC 9001 Appendix A test vector bit-for-bit
- The full in-memory client+server pipe handshake
- Hostile-input fuzzing of decodeFrames
- Coalesced-packets ACK regression
- Multi-cipher-suite (AES-GCM + ChaCha20-Poly1305) handshake
- Negative-path TLS rejection (session_id_echo, version, group, missing
extensions)
https://claude.ai/code/session_01EC1tfXfap8k8GyKvrxkxZx