5c534b1774
Round 2 of the audit follow-ups. Each item caps a peer-controlled allocation that pre-fix could be inflated to hold gigabytes of heap or pin a CPU core indefinitely. * Http3FrameReader: cap pending unparsed buffer (1 MiB) and per-frame body length (16 MiB). A peer streaming a partial-frame prefix without ever delivering the body now raises QuicCodecException instead of growing buf indefinitely. * CapsuleReader: cap pending buffer (1 MiB) and per-capsule body (64 KiB). Symmetric encoder-side check on WT_CLOSE_SESSION reason size, matching the existing decoder cap. * WtPeerStreamDemux: replace Channel.UNLIMITED with bounded channels + suspending sends. readyStreams now caps queued peer-initiated streams at 1024; per-stream chunkChannel caps at 64 chunks. The collector's suspending send naturally back-pressures via QUIC flow control when the application is slow, rather than pinning heap. * WtDatagram.decode: validate quarter-id is in [0, (2^62-1)/4] so `r.value * 4` cannot overflow Long and wrap into a small signed value matching our session id (cross-session datagram injection). * QuicReader.readBytes / skip: translate negative-count into typed QuicCodecException instead of letting IllegalArgumentException escape from copyOfRange. * AckTracker: cap stored disjoint ranges at 64. A peer that sends alternating-bit-pattern PNs can no longer grow our ACK frame past what fits in a packet; oldest range evicts on overflow. * JcaAesGcmAead: track recent encrypt nonces (8) instead of just the most-recent, so a single intermediate seal between two rebuilds can't mask a duplicate against the second-most-recent. Drop the remembered nonce on doFinal failure so a retry takes the safe fresh-Cipher path. Add synchronized() defence-in-depth. Each cap has a generous default (above any legitimate use) but finite. Tests use no-arg construction; existing call sites unaffected. All 269 :quic:jvmTest tests pass. https://claude.ai/code/session_01AhGvbMV8uPRse3TmAGaddM