From 7471b36f3ec4c8e17d129498f9e2892cb2455ad3 Mon Sep 17 00:00:00 2001 From: Adam Magued Date: Wed, 14 Oct 2026 12:19:44 +0300 Subject: [PATCH] Fix CCFB length overflow Reported-by: sollniss Signed-off-by: Adam Magued --- errors.go | 1 + rfc8888.go | 7 ++++++- rfc8888_test.go | 18 ++++++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/errors.go b/errors.go index 9f6e4b7..14ce7d9 100644 --- a/errors.go +++ b/errors.go @@ -39,4 +39,5 @@ var ( errAppDefinedInvalidLength = errors.New("rtcp: application defined type invalid length") errAppDefinedDataTooLarge = errors.New("rtcp: application defined data is too large") errAppDefinedInvalidName = errors.New("rtcp: application defined name must be 4 ASCII chars") + errPacketTooLarge = errors.New("rtcp: packet is too large to fit in RTCP length field") ) diff --git a/rfc8888.go b/rfc8888.go index 69959a6..aafac24 100644 --- a/rfc8888.go +++ b/rfc8888.go @@ -140,12 +140,17 @@ func (b *CCFeedbackReport) Header() Header { // Marshal encodes the Congestion Control Feedback Report in binary. func (b CCFeedbackReport) Marshal() ([]byte, error) { + marshalSize := b.MarshalSize() + if (marshalSize/4-1) > math.MaxUint16 || marshalSize < headerLength { + return nil, errPacketTooLarge + } + header := b.Header() headerBuf, err := header.Marshal() if err != nil { return nil, err } - length := 4 * (int(header.Length) + 1) + length := marshalSize buf := make([]byte, length) copy(buf[:headerLength], headerBuf) binary.BigEndian.PutUint32(buf[headerLength:], b.SenderSSRC) diff --git a/rfc8888_test.go b/rfc8888_test.go index 08f6a7c..5e51a04 100644 --- a/rfc8888_test.go +++ b/rfc8888_test.go @@ -465,3 +465,21 @@ func TestCCFeedbackReportMarshalMaxLength(t *testing.T) { assert.Equal(t, []byte{0x8b, 0xcd, 0xff, 0xff}, buf[:4]) assert.Equal(t, []byte{0x00, 0x00, 0x00, 0x02}, buf[len(buf)-4:]) } + +func TestCCFeedbackReport_MarshalTooLarge(t *testing.T) { + report := CCFeedbackReport{ + SenderSSRC: 1, + ReportTimestamp: 2, + ReportBlocks: make([]CCFeedbackReportBlock, 8), + } + for i := range 8 { + report.ReportBlocks[i] = CCFeedbackReportBlock{ + MediaSSRC: uint32(i + 1), + MetricBlocks: make([]CCFeedbackMetricBlock, maxMetricBlocks), + } + } + + bin, err := report.Marshal() + assert.ErrorIs(t, err, errPacketTooLarge) + assert.Nil(t, bin) +}