Implements the Go RTMP stack unit-test plan (internal/rtmp), cross-referenced
to the C++ srs_utest_manual_protocol/protocol2/rtmp suites, and fixes the one
panic class the fuzz targets exposed.
Tests added (rtmp_test.go):
- TestReadMessageInterleavedMultiStream interleaved multi-cid reassembly
- TestReadMessageLargeChunkStreamID 2-/3-byte cid full-message read
- TestProtocolWritePacketReadMessageRoundTrip encoder<->decoder, 14 pkts x 4 sizes
- TestReadMessageTimestampDiscontinuity backward/forward jump, 31-bit wrap
- TestReadWriteLargePayloadChunkBoundaries chunk-boundary stress
- TestGoldenWireBytes golden bytes for headers + controls
- FuzzReadMessage / FuzzDecodeMessage / FuzzPacketUnmarshal untrusted-input fuzz
- TestPacketUnmarshalAdversarialInputs resource-safety / truncation
- TestProtocolTransactionMapConcurrency -race on the transaction map
Hardening (rtmp.go): the fuzz targets found that the variantCallPacket family
counted a stale optional-field default (CommandObject/Args pre-set to Null by a
New*Packet constructor) when the wire data was exhausted, so Size() overran the
caller's p = p[Size():] advance and panicked on truncated, untrusted input.
Reset those fields to nil before the presence check, and route the embedded
advances in CallPacket/CreateStreamResPacket/PublishPacket/PlayPacket through a
bounds-checked advanceBytes helper so any future Size()/consumed mismatch becomes
a clean error instead of a slice-out-of-range panic.
Verified: full proxy unit suite passes; TestProtocolTransactionMapConcurrency
clean under go test -race -count=3; all proxy E2E scripts pass.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>