Skip to content

Commit

Permalink
Fix overflow in RFC8888
Browse files Browse the repository at this point in the history
Use int instead of uint16. We assert that values on the wire can't be
greater then math.MaxUint16, but when iterating we would overflow.

This changes everything to int and adds tests

Co-Authored-By: Juho Nurminen <[email protected]>
  • Loading branch information
Sean-Der and jupenur committed Nov 9, 2023
1 parent 934dd1a commit 236bd76
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 11 deletions.
23 changes: 12 additions & 11 deletions rfc8888.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ func (b CCFeedbackReport) DestinationSSRC() []uint32 {
}

// Len returns the length of the report in bytes
func (b *CCFeedbackReport) Len() uint16 {
n := uint16(0)
func (b *CCFeedbackReport) Len() int {
n := 0
for _, block := range b.ReportBlocks {
n += block.len()
}
Expand All @@ -107,7 +107,7 @@ func (b *CCFeedbackReport) Header() Header {
Padding: false,
Count: FormatCCFB,
Type: TypeTransportSpecificFeedback,
Length: b.Len()/4 - 1,
Length: uint16(b.Len()/4 - 1),
}
}

Expand All @@ -122,7 +122,7 @@ func (b CCFeedbackReport) Marshal() ([]byte, error) {
buf := make([]byte, length)
copy(buf[:headerLength], headerBuf)
binary.BigEndian.PutUint32(buf[headerLength:], b.SenderSSRC)
offset := uint16(reportBlockOffset)
offset := reportBlockOffset
for _, block := range b.ReportBlocks {
b, err := block.marshal()
if err != nil {
Expand Down Expand Up @@ -164,10 +164,10 @@ func (b *CCFeedbackReport) Unmarshal(rawPacket []byte) error {

b.SenderSSRC = binary.BigEndian.Uint32(rawPacket[headerLength:])

reportTimestampOffset := uint16(len(rawPacket) - reportTimestampLength)
reportTimestampOffset := len(rawPacket) - reportTimestampLength
b.ReportTimestamp = binary.BigEndian.Uint32(rawPacket[reportTimestampOffset:])

offset := uint16(reportBlockOffset)
offset := reportBlockOffset
b.ReportBlocks = []CCFeedbackReportBlock{}
for offset < reportTimestampOffset {
var block CCFeedbackReportBlock
Expand Down Expand Up @@ -199,12 +199,12 @@ type CCFeedbackReportBlock struct {
}

// len returns the length of the report block in bytes
func (b *CCFeedbackReportBlock) len() uint16 {
func (b *CCFeedbackReportBlock) len() int {
n := len(b.MetricBlocks)
if n%2 != 0 {
n++
}
return reportsOffset + 2*uint16(n)
return reportsOffset + 2*n
}

func (b CCFeedbackReportBlock) String() string {
Expand Down Expand Up @@ -263,13 +263,14 @@ func (b *CCFeedbackReportBlock) unmarshal(rawPacket []byte) error {
}

endSequence := b.BeginSequence + numReportsField
numReports := endSequence - b.BeginSequence + 1
numReports := int(endSequence - b.BeginSequence + 1)

if len(rawPacket) < reportsOffset+int(numReports)*2 {
if len(rawPacket) < reportsOffset+numReports*2 {
return errIncorrectNumReports
}

b.MetricBlocks = make([]CCFeedbackMetricBlock, numReports)
for i := uint16(0); i < numReports; i++ {
for i := int(0); i < numReports; i++ {
var mb CCFeedbackMetricBlock
offset := reportsOffset + 2*i
if err := mb.unmarshal(rawPacket[offset : offset+2]); err != nil {
Expand Down
27 changes: 27 additions & 0 deletions rfc8888_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package rtcp

import (
"bytes"
"fmt"
"testing"

Expand Down Expand Up @@ -281,6 +282,16 @@ func TestCCFeedbackReportBlockUnmarshalMarshal(t *testing.T) {
assert.Error(t, err)
assert.ErrorIs(t, err, errIncorrectNumReports)
})

t.Run("overflowNumReports", func(t *testing.T) {
var block CCFeedbackReportBlock
data := append([]byte{
0, 0, 0, 0, // SSRC
0, 0, 0x7F, 0xFB, // begin_seq, num_reports
}, bytes.Repeat([]byte{0, 0}, 0x7FFF)...)
err := block.unmarshal(data)
assert.NoError(t, err)
})
}

func TestCCFeedbackReportUnmarshalMarshal(t *testing.T) {
Expand Down Expand Up @@ -396,3 +407,19 @@ func TestCCFeedbackReportUnmarshalMarshal(t *testing.T) {
})
}
}

func TestCCFeedbackOverflow(t *testing.T) {
p := &CCFeedbackReport{}
err := p.Unmarshal(append([]byte{
// Header
0b10000000, // V = 2
205, // h.Type = TypeTransportSpecificFeedback
0, 0, // h.Length (unused)
// SSRC
0, 0, 0, 0,
// CCFeedbackReportBlock
0, 0, 0, 0, 0, 0,
0x7F, 0xFB, // numReportsField
}, bytes.Repeat([]byte{0, 0}, 0x7FFF)...))
assert.ErrorIs(t, err, errReportBlockLength)
}

0 comments on commit 236bd76

Please sign in to comment.