From 0dc862ce1315445bae0890aa1607b5b7570e749d Mon Sep 17 00:00:00 2001 From: Jo Turk Date: Wed, 21 Oct 2026 05:19:53 +0300 Subject: [PATCH] Ignore unused TWCC status vector entries Limit parsed symbols to PacketStatusCount so unused vector entries do not create extra deltas or reject otherwise valid feedback. Found while reviewing Anthropic's OSS Scanner report ANT-2026-WZBN6GIK. Refs: https://github.com/pion/webrtc/issues/3641 --- transport_layer_cc.go | 7 ++++--- transport_layer_cc_test.go | 30 ++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/transport_layer_cc.go b/transport_layer_cc.go index 3c0e220..5df05ea 100644 --- a/transport_layer_cc.go +++ b/transport_layer_cc.go @@ -533,22 +533,23 @@ func (t *TransportLayerCC) Unmarshal(rawPacket []byte) error { if err != nil { return err } + packetNumberToProcess := min(int(t.PacketStatusCount-processedPacketNum), len(packetStatus.SymbolList)) if packetStatus.SymbolSize == TypeTCCSymbolSizeOneBit { - for j := 0; j < len(packetStatus.SymbolList); j++ { + for j := range packetNumberToProcess { if packetStatus.SymbolList[j] == TypeTCCPacketReceivedSmallDelta { t.RecvDeltas = append(t.RecvDeltas, &RecvDelta{Type: TypeTCCPacketReceivedSmallDelta}) } } } if packetStatus.SymbolSize == TypeTCCSymbolSizeTwoBit { - for j := 0; j < len(packetStatus.SymbolList); j++ { + for j := range packetNumberToProcess { if packetStatus.SymbolList[j] == TypeTCCPacketReceivedSmallDelta || packetStatus.SymbolList[j] == TypeTCCPacketReceivedLargeDelta { t.RecvDeltas = append(t.RecvDeltas, &RecvDelta{Type: packetStatus.SymbolList[j]}) } } } - processedPacketNum += uint16(len(packetStatus.SymbolList)) //nolint:gosec // G115 + processedPacketNum += uint16(packetNumberToProcess) //nolint:gosec // bounded by remaining packet count } packetStatusPos += packetStatusChunkLength t.PacketChunks = append(t.PacketChunks, iPacketStatus) diff --git a/transport_layer_cc_test.go b/transport_layer_cc_test.go index e7897db..b5954ea 100644 --- a/transport_layer_cc_test.go +++ b/transport_layer_cc_test.go @@ -4,6 +4,8 @@ package rtcp import ( + "encoding/binary" + "fmt" "testing" "github.com/stretchr/testify/assert" @@ -1213,3 +1215,31 @@ func TestTransportLayerCC_LengthOverflow(t *testing.T) { assert.ErrorIs(t, err, errBadLength) assert.Nil(t, data) } + +func TestTransportLayerCC_UnmarshalUnusedVector(t *testing.T) { + for _, symbol := range []uint16{0xbfff, 0xeaaa} { + for _, missing := range []uint16{0, 65530} { + t.Run(fmt.Sprintf("%x/%d", symbol, missing), func(t *testing.T) { + header := [20]byte{0x8f, 205, 0, 5} + data := header[:] + binary.BigEndian.PutUint16(data[14:16], missing+1) + for remaining := missing; remaining > 0; { + count := min(remaining, 8191) + data = binary.BigEndian.AppendUint16(data, count) + remaining -= count + } + data = binary.BigEndian.AppendUint16(data, symbol) + data = append(data, 0, 0) + if missing > 0 { + data = append(data, 0, 0) + data[3] = 10 + } + + var packet TransportLayerCC + assert.NoError(t, packet.Unmarshal(data)) + assert.Len(t, packet.RecvDeltas, 1) + assert.Equal(t, missing+1, packet.PacketStatusCount) + }) + } + } +}