Repository navigation
Description
Marshal computes the packet size in a uint16, which wraps for large packets. The buffer is then allocated too small and Marshal panics instead of returning an error.
TransportLayerCC: packetLen() wraps above 65535 bytes.
Lines 365 to 377 in 2599616
| func (t *TransportLayerCC) packetLen() uint16 { | |
| //nolint:gocognit,cyclop | |
| n := uint16(headerLength + packetChunkOffset + len(t.PacketChunks)*2) //nolint:gosec // G115 | |
| for _, d := range t.RecvDeltas { | |
| if d.Type == TypeTCCPacketReceivedSmallDelta { | |
| n++ | |
| } else { | |
| n += 2 | |
| } | |
| } | |
| return n | |
| } |
CCFeedbackReport: Header().Length wraps above 262144 bytes, and Marshal sizes its buffer from it.
Lines 137 to 149 in 2599616
| Length: uint16(b.MarshalSize()/4 - 1), //nolint:gosec // G115 | |
| } | |
| } | |
| // Marshal encodes the Congestion Control Feedback Report in binary. | |
| func (b CCFeedbackReport) Marshal() ([]byte, error) { | |
| header := b.Header() | |
| headerBuf, err := header.Marshal() | |
| if err != nil { | |
| return nil, err | |
| } | |
| length := 4 * (int(header.Length) + 1) | |
| buf := make([]byte, length) |
Reproducer
package main
import (
"fmt"
"github.com/pion/rtcp"
)
func try(name string, p rtcp.Packet) {
defer func() { fmt.Println(name, "->", recover()) }()
p.Marshal()
}
func main() {
// 32768 large deltas: 2 bytes each, so the packet is over 65535 bytes.
deltas := make([]*rtcp.RecvDelta, 32768)
for i := range deltas {
deltas[i] = &rtcp.RecvDelta{Type: rtcp.TypeTCCPacketReceivedLargeDelta}
}
try("TransportLayerCC", &rtcp.TransportLayerCC{RecvDeltas: deltas})
// 8 blocks of 16384 metric blocks each: over 262144 bytes.
ccfb := &rtcp.CCFeedbackReport{}
for range 8 {
ccfb.ReportBlocks = append(ccfb.ReportBlocks, rtcp.CCFeedbackReportBlock{
MetricBlocks: make([]rtcp.CCFeedbackMetricBlock, 16384),
})
}
try("CCFeedbackReport", ccfb)
}TransportLayerCC -> runtime error: slice bounds out of range [18:16]
CCFeedbackReport -> runtime error: slice bounds out of range [32784:76]
The panics are at transport_layer_cc.go:446 and rfc8888.go:158.
Expected: Marshal returns an error when the packet does not fit the length field (similar to #164).
These two panics can't be triggered remotely, so this should be low priority. My last PR to pion/rtp seemed to contain a correctness bug, so I'll refrain from trying to fix this myself. :P
Found with a static analyzer, reproducer is AI generated.
Activity
JoTurk commentedon Oct 14, 2026
Please don't make this block you from sending patches, review and follow up fixes exist for this reason :)
sollniss commentedon Oct 14, 2026
Alright I'll keep that in mind if I find anything else :)
Looks like someone already made a PR for this ❤