From 363ac206f7cb6231626801baaad7125af852b105 Mon Sep 17 00:00:00 2001 From: Alessandro Ros Date: Sun, 19 Jul 2026 12:13:45 +0200 Subject: [PATCH] moq: fix several panics and OOM errors (#5964) Check for limits before allocating memory by using sizes passed from the remote peer. Also add fuzzing to all MoQ primitives. --- .../moq/controlmessage/message_test.go | 15 +++++++++ .../protocols/moq/controlmessage/publish.go | 24 +++++++++++--- .../moq/controlmessage/request_error.go | 7 ++-- .../protocols/moq/controlmessage/subscribe.go | 17 +++++++--- .../moq/controlmessage/subscribe_ok.go | 3 +- .../fuzz/FuzzUnmarshal/04dc5e127f88e4a0 | 2 ++ .../fuzz/FuzzUnmarshal/0a4e2c8af3eab5cc | 2 ++ .../fuzz/FuzzUnmarshal/0be17f6a336dc723 | 2 ++ .../fuzz/FuzzUnmarshal/0c23fc515adfd463 | 2 ++ .../fuzz/FuzzUnmarshal/283cdc309b409f6e | 2 ++ .../fuzz/FuzzUnmarshal/3344e1baba05b8af | 2 ++ .../fuzz/FuzzUnmarshal/4742960320bb5cf4 | 2 ++ .../fuzz/FuzzUnmarshal/8c02d6d4791df7c7 | 2 ++ .../fuzz/FuzzUnmarshal/8eff4bc3e4c19ff0 | 2 ++ .../fuzz/FuzzUnmarshal/90ed9ff994ee1365 | 2 ++ .../fuzz/FuzzUnmarshal/99e20f546da05418 | 2 ++ .../fuzz/FuzzUnmarshal/9b0a8a587ff5987f | 2 ++ .../fuzz/FuzzUnmarshal/ad79520646055dda | 2 ++ .../fuzz/FuzzUnmarshal/bb4be6daa388e10f | 2 ++ .../fuzz/FuzzUnmarshal/c6277ab31bacf0f0 | 2 ++ .../fuzz/FuzzUnmarshal/cfac1bcfcd2aaed7 | 2 ++ .../moq/parameter/authorization_token.go | 16 +++++++--- internal/protocols/moq/parameter/parameter.go | 4 +-- .../protocols/moq/parameter/parameter_test.go | 17 ++++++++++ .../fuzz/FuzzUnmarshal/012f7197e6ddf1ab | 3 ++ .../fuzz/FuzzUnmarshal/4672cf7e303acb7c | 3 ++ .../fuzz/FuzzUnmarshal/e4a7f91c59e36722 | 3 ++ internal/protocols/moq/property/property.go | 6 ++-- .../protocols/moq/property/property_test.go | 17 ++++++++++ .../fuzz/FuzzUnmarshal/582528ddfad69eb5 | 2 ++ .../fuzz/FuzzUnmarshal/fbab04f43516aa5e | 2 ++ internal/protocols/moq/subgroup/object.go | 9 +++++- .../protocols/moq/subgroup/subgroup_test.go | 16 ++++++++++ .../fuzz/FuzzUnmarshal/1e14487eae37d7de | 2 ++ .../fuzz/FuzzUnmarshal/4aaa2cceaff6c94c | 2 ++ .../fuzz/FuzzUnmarshal/56fe3cb486379cde | 2 ++ .../fuzz/FuzzUnmarshal/f44ebae6b8fa8577 | 2 ++ .../testdata/fuzz/FuzzRead/752f6aefa94a7185 | 2 ++ .../testdata/fuzz/FuzzRead/caf81e9797b19c76 | 2 ++ .../testdata/fuzz/FuzzRead/e3443030b91d09bb | 2 ++ .../fuzz/FuzzUnmarshal/1df43ba150bdbac1 | 2 ++ .../fuzz/FuzzUnmarshal/1e10b9f0074a42d0 | 2 ++ .../fuzz/FuzzUnmarshal/744d0cfe7e9fe6df | 2 ++ .../fuzz/FuzzUnmarshal/96712476d3ab2517 | 2 ++ .../fuzz/FuzzUnmarshal/caf81e9797b19c76 | 2 ++ internal/protocols/moq/varint/varint_test.go | 32 +++++++++++++++++++ 46 files changed, 230 insertions(+), 22 deletions(-) create mode 100644 internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/04dc5e127f88e4a0 create mode 100644 internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/0a4e2c8af3eab5cc create mode 100644 internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/0be17f6a336dc723 create mode 100644 internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/0c23fc515adfd463 create mode 100644 internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/283cdc309b409f6e create mode 100644 internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/3344e1baba05b8af create mode 100644 internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/4742960320bb5cf4 create mode 100644 internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/8c02d6d4791df7c7 create mode 100644 internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/8eff4bc3e4c19ff0 create mode 100644 internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/90ed9ff994ee1365 create mode 100644 internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/99e20f546da05418 create mode 100644 internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/9b0a8a587ff5987f create mode 100644 internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/ad79520646055dda create mode 100644 internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/bb4be6daa388e10f create mode 100644 internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/c6277ab31bacf0f0 create mode 100644 internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/cfac1bcfcd2aaed7 create mode 100644 internal/protocols/moq/parameter/testdata/fuzz/FuzzUnmarshal/012f7197e6ddf1ab create mode 100644 internal/protocols/moq/parameter/testdata/fuzz/FuzzUnmarshal/4672cf7e303acb7c create mode 100644 internal/protocols/moq/parameter/testdata/fuzz/FuzzUnmarshal/e4a7f91c59e36722 create mode 100644 internal/protocols/moq/property/testdata/fuzz/FuzzUnmarshal/582528ddfad69eb5 create mode 100644 internal/protocols/moq/property/testdata/fuzz/FuzzUnmarshal/fbab04f43516aa5e create mode 100644 internal/protocols/moq/subgroup/testdata/fuzz/FuzzUnmarshal/1e14487eae37d7de create mode 100644 internal/protocols/moq/subgroup/testdata/fuzz/FuzzUnmarshal/4aaa2cceaff6c94c create mode 100644 internal/protocols/moq/subgroup/testdata/fuzz/FuzzUnmarshal/56fe3cb486379cde create mode 100644 internal/protocols/moq/subgroup/testdata/fuzz/FuzzUnmarshal/f44ebae6b8fa8577 create mode 100644 internal/protocols/moq/varint/testdata/fuzz/FuzzRead/752f6aefa94a7185 create mode 100644 internal/protocols/moq/varint/testdata/fuzz/FuzzRead/caf81e9797b19c76 create mode 100644 internal/protocols/moq/varint/testdata/fuzz/FuzzRead/e3443030b91d09bb create mode 100644 internal/protocols/moq/varint/testdata/fuzz/FuzzUnmarshal/1df43ba150bdbac1 create mode 100644 internal/protocols/moq/varint/testdata/fuzz/FuzzUnmarshal/1e10b9f0074a42d0 create mode 100644 internal/protocols/moq/varint/testdata/fuzz/FuzzUnmarshal/744d0cfe7e9fe6df create mode 100644 internal/protocols/moq/varint/testdata/fuzz/FuzzUnmarshal/96712476d3ab2517 create mode 100644 internal/protocols/moq/varint/testdata/fuzz/FuzzUnmarshal/caf81e9797b19c76 diff --git a/internal/protocols/moq/controlmessage/message_test.go b/internal/protocols/moq/controlmessage/message_test.go index 5d0a2066..7c8aae5a 100644 --- a/internal/protocols/moq/controlmessage/message_test.go +++ b/internal/protocols/moq/controlmessage/message_test.go @@ -172,3 +172,18 @@ func TestMarshal(t *testing.T) { }) } } + +func FuzzUnmarshal(f *testing.F) { + for _, ca := range cases { + f.Add(ca.enc) + } + + f.Fuzz(func(_ *testing.T, buf []byte) { + m, err := Read(bytes.NewReader(buf)) + if err != nil { + return + } + + m.Marshal() + }) +} diff --git a/internal/protocols/moq/controlmessage/publish.go b/internal/protocols/moq/controlmessage/publish.go index 070029ce..554fa318 100644 --- a/internal/protocols/moq/controlmessage/publish.go +++ b/internal/protocols/moq/controlmessage/publish.go @@ -10,6 +10,10 @@ import ( const typePublish varint.Varint = 0x1d +const ( + maxNamespaceFieldCount = 16 +) + // Publish is the PUBLISH control message. // spec: draft-18, section 10.10 type Publish struct { @@ -29,9 +33,10 @@ func (m *Publish) unmarshal(buf []byte) error { if err != nil { return err } - m.RequestID = uint64(requestID) buf = buf[n:] + m.RequestID = uint64(requestID) + var nsCount varint.Varint n, err = nsCount.Unmarshal(buf) if err != nil { @@ -39,6 +44,10 @@ func (m *Publish) unmarshal(buf []byte) error { } buf = buf[n:] + if nsCount > maxNamespaceFieldCount { + return fmt.Errorf("too many namespace fields: %d", nsCount) + } + m.Namespace = make([]string, nsCount) for i := range m.Namespace { var l varint.Varint @@ -47,9 +56,11 @@ func (m *Publish) unmarshal(buf []byte) error { return err } buf = buf[n:] - if len(buf) < int(l) { + + if uint64(len(buf)) < uint64(l) { return fmt.Errorf("not enough bytes for namespace part") } + m.Namespace[i] = string(buf[:l]) buf = buf[int(l):] } @@ -60,9 +71,11 @@ func (m *Publish) unmarshal(buf []byte) error { return err } buf = buf[n:] - if len(buf) < int(tnLen) { - return fmt.Errorf("not enough bytes for track name") + + if uint64(len(buf)) < uint64(tnLen) { + return fmt.Errorf("invalid track name length: %d", tnLen) } + m.TrackName = string(buf[:tnLen]) buf = buf[int(tnLen):] @@ -71,9 +84,10 @@ func (m *Publish) unmarshal(buf []byte) error { if err != nil { return err } - m.TrackAlias = uint64(trackAlias) buf = buf[n:] + m.TrackAlias = uint64(trackAlias) + var paramCount varint.Varint n, err = paramCount.Unmarshal(buf) if err != nil { diff --git a/internal/protocols/moq/controlmessage/request_error.go b/internal/protocols/moq/controlmessage/request_error.go index f4e285e7..b31208eb 100644 --- a/internal/protocols/moq/controlmessage/request_error.go +++ b/internal/protocols/moq/controlmessage/request_error.go @@ -34,9 +34,10 @@ func (m *RequestError) unmarshal(buf []byte) error { if err != nil { return err } - m.Code = RequestErrorCode(code) buf = buf[n:] + m.Code = RequestErrorCode(code) + var retry varint.Varint n, err = retry.Unmarshal(buf) if err != nil { @@ -50,9 +51,11 @@ func (m *RequestError) unmarshal(buf []byte) error { return err } buf = buf[n:] - if len(buf) < int(l) { + + if uint64(len(buf)) < uint64(l) { return fmt.Errorf("not enough bytes") } + m.Reason = string(buf[:l]) return nil diff --git a/internal/protocols/moq/controlmessage/subscribe.go b/internal/protocols/moq/controlmessage/subscribe.go index 6a7c3524..50f9a7d8 100644 --- a/internal/protocols/moq/controlmessage/subscribe.go +++ b/internal/protocols/moq/controlmessage/subscribe.go @@ -26,9 +26,10 @@ func (m *Subscribe) unmarshal(buf []byte) error { if err != nil { return err } - m.RequestID = uint64(requestID) buf = buf[n:] + m.RequestID = uint64(requestID) + var nsCount varint.Varint n, err = nsCount.Unmarshal(buf) if err != nil { @@ -36,6 +37,10 @@ func (m *Subscribe) unmarshal(buf []byte) error { } buf = buf[n:] + if nsCount > maxNamespaceFieldCount { + return fmt.Errorf("too many namespace fields: %d", nsCount) + } + m.Namespace = make([]string, nsCount) for i := range m.Namespace { var l varint.Varint @@ -44,9 +49,11 @@ func (m *Subscribe) unmarshal(buf []byte) error { return err } buf = buf[n:] - if len(buf) < int(l) { + + if uint64(len(buf)) < uint64(l) { return fmt.Errorf("not enough bytes for namespace part") } + m.Namespace[i] = string(buf[:l]) buf = buf[int(l):] } @@ -57,9 +64,11 @@ func (m *Subscribe) unmarshal(buf []byte) error { return err } buf = buf[n:] - if len(buf) < int(tnLen) { - return fmt.Errorf("not enough bytes for track name") + + if uint64(len(buf)) < uint64(tnLen) { + return fmt.Errorf("invalid track name length: %d", tnLen) } + m.TrackName = string(buf[:tnLen]) buf = buf[int(tnLen):] diff --git a/internal/protocols/moq/controlmessage/subscribe_ok.go b/internal/protocols/moq/controlmessage/subscribe_ok.go index 3deb67ed..818fc564 100644 --- a/internal/protocols/moq/controlmessage/subscribe_ok.go +++ b/internal/protocols/moq/controlmessage/subscribe_ok.go @@ -24,9 +24,10 @@ func (m *SubscribeOk) unmarshal(buf []byte) error { if err != nil { return err } - m.TrackAlias = uint64(v) buf = buf[n:] + m.TrackAlias = uint64(v) + var numParams varint.Varint n, err = numParams.Unmarshal(buf) if err != nil { diff --git a/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/04dc5e127f88e4a0 b/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/04dc5e127f88e4a0 new file mode 100644 index 00000000..c235400b --- /dev/null +++ b/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/04dc5e127f88e4a0 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x04\x00\x060\x000010") diff --git a/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/0a4e2c8af3eab5cc b/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/0a4e2c8af3eab5cc new file mode 100644 index 00000000..dc76b823 --- /dev/null +++ b/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/0a4e2c8af3eab5cc @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x1d\x00\f0\x01\xff\xff00000000") diff --git a/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/0be17f6a336dc723 b/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/0be17f6a336dc723 new file mode 100644 index 00000000..3594d409 --- /dev/null +++ b/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/0be17f6a336dc723 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\a\x00\x010") diff --git a/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/0c23fc515adfd463 b/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/0c23fc515adfd463 new file mode 100644 index 00000000..8de7073e --- /dev/null +++ b/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/0c23fc515adfd463 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x04\x00\x06000000") diff --git a/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/283cdc309b409f6e b/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/283cdc309b409f6e new file mode 100644 index 00000000..ee4a363b --- /dev/null +++ b/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/283cdc309b409f6e @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\a\x000\x0000000000000000000000000000000000000000000000000") diff --git a/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/3344e1baba05b8af b/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/3344e1baba05b8af new file mode 100644 index 00000000..d99fa0cf --- /dev/null +++ b/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/3344e1baba05b8af @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x1d\x00\x160\x01\x03000\x030000\x001\xff\xff0000000") diff --git a/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/4742960320bb5cf4 b/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/4742960320bb5cf4 new file mode 100644 index 00000000..2338076f --- /dev/null +++ b/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/4742960320bb5cf4 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x03\x00\v0\x01\xff\xff0000000") diff --git a/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/8c02d6d4791df7c7 b/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/8c02d6d4791df7c7 new file mode 100644 index 00000000..62755276 --- /dev/null +++ b/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/8c02d6d4791df7c7 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0\x00\x00") diff --git a/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/8eff4bc3e4c19ff0 b/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/8eff4bc3e4c19ff0 new file mode 100644 index 00000000..ebc71ac3 --- /dev/null +++ b/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/8eff4bc3e4c19ff0 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x03\x00\x150\x01\x03000\x030000\x03\xff\xff0000000") diff --git a/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/90ed9ff994ee1365 b/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/90ed9ff994ee1365 new file mode 100644 index 00000000..8cfcbbff --- /dev/null +++ b/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/90ed9ff994ee1365 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x1d\x00\x160\x00\x01000\x03\xff\xff\xff\xff\xff\xff\xff\xff\xff000000") diff --git a/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/99e20f546da05418 b/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/99e20f546da05418 new file mode 100644 index 00000000..cea114f6 --- /dev/null +++ b/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/99e20f546da05418 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x05\x00\x15\x9700\xff\xff0000000000000000") diff --git a/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/9b0a8a587ff5987f b/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/9b0a8a587ff5987f new file mode 100644 index 00000000..08164a60 --- /dev/null +++ b/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/9b0a8a587ff5987f @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x03\x00\x15000000000000000000000") diff --git a/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/ad79520646055dda b/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/ad79520646055dda new file mode 100644 index 00000000..3d38b49c --- /dev/null +++ b/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/ad79520646055dda @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x1d\x00\f0\x01\x00\xff\xff0000000") diff --git a/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/bb4be6daa388e10f b/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/bb4be6daa388e10f new file mode 100644 index 00000000..506ee003 --- /dev/null +++ b/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/bb4be6daa388e10f @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x1d\x00\x03000") diff --git a/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/c6277ab31bacf0f0 b/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/c6277ab31bacf0f0 new file mode 100644 index 00000000..04ff2832 --- /dev/null +++ b/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/c6277ab31bacf0f0 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x1d\x00\x160\x01\x03000\x0300000\x03\b\x03\xf2000000") diff --git a/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/cfac1bcfcd2aaed7 b/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/cfac1bcfcd2aaed7 new file mode 100644 index 00000000..1ebf4d3e --- /dev/null +++ b/internal/protocols/moq/controlmessage/testdata/fuzz/FuzzUnmarshal/cfac1bcfcd2aaed7 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x03\x00\x15\x970\x00\xff\xff0000000000000000") diff --git a/internal/protocols/moq/parameter/authorization_token.go b/internal/protocols/moq/parameter/authorization_token.go index f8f4caf6..b4b81549 100644 --- a/internal/protocols/moq/parameter/authorization_token.go +++ b/internal/protocols/moq/parameter/authorization_token.go @@ -33,35 +33,41 @@ func (*AuthorizationToken) paramType() uint64 { func (t *AuthorizationToken) unmarshal(buf []byte) (int, error) { var le varint.Varint - llen, err := le.Unmarshal(buf) + n1, err := le.Unmarshal(buf) if err != nil { return 0, err } - if len(buf)-llen < int(le) { + buf = buf[n1:] + + if uint64(len(buf)) < uint64(le) { return 0, fmt.Errorf("not enough bytes for parameter value") } - buf = buf[llen : llen+int(le)] + + buf = buf[:le] var aliasType varint.Varint n, err := aliasType.Unmarshal(buf) if err != nil { return 0, err } + buf = buf[n:] + t.AliasType = AuthorizationTokenAliasType(aliasType) if t.AliasType != AuthorizationTokenAliasTypeUseValue { return 0, fmt.Errorf("unsupported token alias type: %d", aliasType) } - buf = buf[n:] var tokenType varint.Varint n, err = tokenType.Unmarshal(buf) if err != nil { return 0, err } + t.TokenType = uint64(tokenType) t.TokenValue = buf[n:] - return llen + int(le), nil + + return n1 + int(le), nil } func (t AuthorizationToken) marshalSize() int { diff --git a/internal/protocols/moq/parameter/parameter.go b/internal/protocols/moq/parameter/parameter.go index 1ec5bfb0..91caa782 100644 --- a/internal/protocols/moq/parameter/parameter.go +++ b/internal/protocols/moq/parameter/parameter.go @@ -31,8 +31,8 @@ func (p *Parameters) Unmarshal(count int, buf []byte) (int, error) { if err != nil { return 0, err } - buf = buf[n:] + total += n currentType += uint64(typeDelta) @@ -50,9 +50,9 @@ func (p *Parameters) Unmarshal(count int, buf []byte) (int, error) { if err != nil { return 0, fmt.Errorf("failed to unmarshal authorization token: %w", err) } + buf = buf[n:] *p = append(*p, param) - buf = buf[n:] total += n } diff --git a/internal/protocols/moq/parameter/parameter_test.go b/internal/protocols/moq/parameter/parameter_test.go index 022024ba..c33b50b0 100644 --- a/internal/protocols/moq/parameter/parameter_test.go +++ b/internal/protocols/moq/parameter/parameter_test.go @@ -58,3 +58,20 @@ func TestMarshal(t *testing.T) { }) } } + +func FuzzUnmarshal(f *testing.F) { + for _, ca := range cases { + f.Add(ca.count, ca.enc) + } + + f.Fuzz(func(_ *testing.T, count int, buf []byte) { + var params Parameters + _, err := params.Unmarshal(count, buf) + if err != nil { + return + } + + buf = make([]byte, params.MarshalSize()) + params.MarshalTo(buf) + }) +} diff --git a/internal/protocols/moq/parameter/testdata/fuzz/FuzzUnmarshal/012f7197e6ddf1ab b/internal/protocols/moq/parameter/testdata/fuzz/FuzzUnmarshal/012f7197e6ddf1ab new file mode 100644 index 00000000..80187acf --- /dev/null +++ b/internal/protocols/moq/parameter/testdata/fuzz/FuzzUnmarshal/012f7197e6ddf1ab @@ -0,0 +1,3 @@ +go test fuzz v1 +int(23) +[]byte("\x03\x03000") diff --git a/internal/protocols/moq/parameter/testdata/fuzz/FuzzUnmarshal/4672cf7e303acb7c b/internal/protocols/moq/parameter/testdata/fuzz/FuzzUnmarshal/4672cf7e303acb7c new file mode 100644 index 00000000..11139be1 --- /dev/null +++ b/internal/protocols/moq/parameter/testdata/fuzz/FuzzUnmarshal/4672cf7e303acb7c @@ -0,0 +1,3 @@ +go test fuzz v1 +int(68) +[]byte("\x030") diff --git a/internal/protocols/moq/parameter/testdata/fuzz/FuzzUnmarshal/e4a7f91c59e36722 b/internal/protocols/moq/parameter/testdata/fuzz/FuzzUnmarshal/e4a7f91c59e36722 new file mode 100644 index 00000000..f6a7656f --- /dev/null +++ b/internal/protocols/moq/parameter/testdata/fuzz/FuzzUnmarshal/e4a7f91c59e36722 @@ -0,0 +1,3 @@ +go test fuzz v1 +int(-17) +[]byte("00") diff --git a/internal/protocols/moq/property/property.go b/internal/protocols/moq/property/property.go index b1c99ab4..fbb74942 100644 --- a/internal/protocols/moq/property/property.go +++ b/internal/protocols/moq/property/property.go @@ -31,8 +31,8 @@ func (p *Properties) Unmarshal(buf []byte) error { if err != nil { return err } - buf = buf[n:] + currentType += uint64(delta) switch currentType { @@ -54,9 +54,11 @@ func (p *Properties) Unmarshal(buf []byte) error { if err != nil { return err } - if len(buf)-n2 < int(length) { + + if uint64(len(buf))-uint64(n2) < uint64(length) { return fmt.Errorf("not enough bytes for unknown property") } + buf = buf[n2+int(length):] } else { var skip varint.Varint diff --git a/internal/protocols/moq/property/property_test.go b/internal/protocols/moq/property/property_test.go index c4ea7f51..041edd3d 100644 --- a/internal/protocols/moq/property/property_test.go +++ b/internal/protocols/moq/property/property_test.go @@ -48,3 +48,20 @@ func TestMarshal(t *testing.T) { }) } } + +func FuzzUnmarshal(f *testing.F) { + for _, ca := range cases { + f.Add(ca.enc) + } + + f.Fuzz(func(_ *testing.T, buf []byte) { + var props Properties + err := props.Unmarshal(buf) + if err != nil { + return + } + + buf = make([]byte, props.MarshalSize()) + props.MarshalTo(buf) + }) +} diff --git a/internal/protocols/moq/property/testdata/fuzz/FuzzUnmarshal/582528ddfad69eb5 b/internal/protocols/moq/property/testdata/fuzz/FuzzUnmarshal/582528ddfad69eb5 new file mode 100644 index 00000000..a96f5599 --- /dev/null +++ b/internal/protocols/moq/property/testdata/fuzz/FuzzUnmarshal/582528ddfad69eb5 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0") diff --git a/internal/protocols/moq/property/testdata/fuzz/FuzzUnmarshal/fbab04f43516aa5e b/internal/protocols/moq/property/testdata/fuzz/FuzzUnmarshal/fbab04f43516aa5e new file mode 100644 index 00000000..8fd0d6f8 --- /dev/null +++ b/internal/protocols/moq/property/testdata/fuzz/FuzzUnmarshal/fbab04f43516aa5e @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("10") diff --git a/internal/protocols/moq/subgroup/object.go b/internal/protocols/moq/subgroup/object.go index cfdd00e9..d579203f 100644 --- a/internal/protocols/moq/subgroup/object.go +++ b/internal/protocols/moq/subgroup/object.go @@ -8,7 +8,10 @@ import ( "github.com/bluenviron/mediamtx/internal/protocols/moq/varint" ) -const maxPayloadSize = 10 * 1024 * 1024 +const ( + maxPropsLen = 128 * 1024 + maxPayloadSize = 10 * 1024 * 1024 +) // Object is an object of a subgroup stream. // spec: draft-18, section 11.4.2 @@ -34,6 +37,10 @@ func (o *Object) read(r io.Reader, header *Header) error { } if propsLen > 0 { + if propsLen > maxPropsLen { + return fmt.Errorf("properties too large: %d", propsLen) + } + props := make([]byte, propsLen) _, err = io.ReadFull(r, props) if err != nil { diff --git a/internal/protocols/moq/subgroup/subgroup_test.go b/internal/protocols/moq/subgroup/subgroup_test.go index 494a0bef..995a5d16 100644 --- a/internal/protocols/moq/subgroup/subgroup_test.go +++ b/internal/protocols/moq/subgroup/subgroup_test.go @@ -90,3 +90,19 @@ func TestMarshal(t *testing.T) { }) } } + +func FuzzUnmarshal(f *testing.F) { + for _, ca := range cases { + f.Add(ca.enc) + } + + f.Fuzz(func(_ *testing.T, buf []byte) { + var s SubGroup + err := s.Read(bytes.NewReader(buf)) + if err != nil { + return + } + + s.Marshal() + }) +} diff --git a/internal/protocols/moq/subgroup/testdata/fuzz/FuzzUnmarshal/1e14487eae37d7de b/internal/protocols/moq/subgroup/testdata/fuzz/FuzzUnmarshal/1e14487eae37d7de new file mode 100644 index 00000000..a37f84ee --- /dev/null +++ b/internal/protocols/moq/subgroup/testdata/fuzz/FuzzUnmarshal/1e14487eae37d7de @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000\xff00000000") diff --git a/internal/protocols/moq/subgroup/testdata/fuzz/FuzzUnmarshal/4aaa2cceaff6c94c b/internal/protocols/moq/subgroup/testdata/fuzz/FuzzUnmarshal/4aaa2cceaff6c94c new file mode 100644 index 00000000..7d905211 --- /dev/null +++ b/internal/protocols/moq/subgroup/testdata/fuzz/FuzzUnmarshal/4aaa2cceaff6c94c @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000\x0100\x0500000") diff --git a/internal/protocols/moq/subgroup/testdata/fuzz/FuzzUnmarshal/56fe3cb486379cde b/internal/protocols/moq/subgroup/testdata/fuzz/FuzzUnmarshal/56fe3cb486379cde new file mode 100644 index 00000000..110e69dd --- /dev/null +++ b/internal/protocols/moq/subgroup/testdata/fuzz/FuzzUnmarshal/56fe3cb486379cde @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("1000\xd000") diff --git a/internal/protocols/moq/subgroup/testdata/fuzz/FuzzUnmarshal/f44ebae6b8fa8577 b/internal/protocols/moq/subgroup/testdata/fuzz/FuzzUnmarshal/f44ebae6b8fa8577 new file mode 100644 index 00000000..8e367205 --- /dev/null +++ b/internal/protocols/moq/subgroup/testdata/fuzz/FuzzUnmarshal/f44ebae6b8fa8577 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000\x000") diff --git a/internal/protocols/moq/varint/testdata/fuzz/FuzzRead/752f6aefa94a7185 b/internal/protocols/moq/varint/testdata/fuzz/FuzzRead/752f6aefa94a7185 new file mode 100644 index 00000000..d0b5a489 --- /dev/null +++ b/internal/protocols/moq/varint/testdata/fuzz/FuzzRead/752f6aefa94a7185 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\xff0") diff --git a/internal/protocols/moq/varint/testdata/fuzz/FuzzRead/caf81e9797b19c76 b/internal/protocols/moq/varint/testdata/fuzz/FuzzRead/caf81e9797b19c76 new file mode 100644 index 00000000..67322c70 --- /dev/null +++ b/internal/protocols/moq/varint/testdata/fuzz/FuzzRead/caf81e9797b19c76 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("") diff --git a/internal/protocols/moq/varint/testdata/fuzz/FuzzRead/e3443030b91d09bb b/internal/protocols/moq/varint/testdata/fuzz/FuzzRead/e3443030b91d09bb new file mode 100644 index 00000000..910cd468 --- /dev/null +++ b/internal/protocols/moq/varint/testdata/fuzz/FuzzRead/e3443030b91d09bb @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\xff") diff --git a/internal/protocols/moq/varint/testdata/fuzz/FuzzUnmarshal/1df43ba150bdbac1 b/internal/protocols/moq/varint/testdata/fuzz/FuzzUnmarshal/1df43ba150bdbac1 new file mode 100644 index 00000000..31d5558d --- /dev/null +++ b/internal/protocols/moq/varint/testdata/fuzz/FuzzUnmarshal/1df43ba150bdbac1 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\xf8\x000000") diff --git a/internal/protocols/moq/varint/testdata/fuzz/FuzzUnmarshal/1e10b9f0074a42d0 b/internal/protocols/moq/varint/testdata/fuzz/FuzzUnmarshal/1e10b9f0074a42d0 new file mode 100644 index 00000000..9c99c9f5 --- /dev/null +++ b/internal/protocols/moq/varint/testdata/fuzz/FuzzUnmarshal/1e10b9f0074a42d0 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\xfe\x00\x00\x00\x00\x0200") diff --git a/internal/protocols/moq/varint/testdata/fuzz/FuzzUnmarshal/744d0cfe7e9fe6df b/internal/protocols/moq/varint/testdata/fuzz/FuzzUnmarshal/744d0cfe7e9fe6df new file mode 100644 index 00000000..b4ed59fc --- /dev/null +++ b/internal/protocols/moq/varint/testdata/fuzz/FuzzUnmarshal/744d0cfe7e9fe6df @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\xff\x000000000") diff --git a/internal/protocols/moq/varint/testdata/fuzz/FuzzUnmarshal/96712476d3ab2517 b/internal/protocols/moq/varint/testdata/fuzz/FuzzUnmarshal/96712476d3ab2517 new file mode 100644 index 00000000..f37206d0 --- /dev/null +++ b/internal/protocols/moq/varint/testdata/fuzz/FuzzUnmarshal/96712476d3ab2517 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\xc0") diff --git a/internal/protocols/moq/varint/testdata/fuzz/FuzzUnmarshal/caf81e9797b19c76 b/internal/protocols/moq/varint/testdata/fuzz/FuzzUnmarshal/caf81e9797b19c76 new file mode 100644 index 00000000..67322c70 --- /dev/null +++ b/internal/protocols/moq/varint/testdata/fuzz/FuzzUnmarshal/caf81e9797b19c76 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("") diff --git a/internal/protocols/moq/varint/varint_test.go b/internal/protocols/moq/varint/varint_test.go index 75b8af81..5c349853 100644 --- a/internal/protocols/moq/varint/varint_test.go +++ b/internal/protocols/moq/varint/varint_test.go @@ -89,3 +89,35 @@ func TestMarshal(t *testing.T) { }) } } + +func FuzzUnmarshal(f *testing.F) { + for _, ca := range cases { + f.Add(ca.enc) + } + + f.Fuzz(func(_ *testing.T, buf []byte) { + var v Varint + _, err := v.Unmarshal(buf) + if err != nil { + return + } + + v.Marshal() + }) +} + +func FuzzRead(f *testing.F) { + for _, ca := range cases { + f.Add(ca.enc) + } + + f.Fuzz(func(_ *testing.T, buf []byte) { + var v Varint + err := v.Read(bytes.NewReader(buf)) + if err != nil { + return + } + + v.Marshal() + }) +}