Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fuzzing add seed, new target and remove bloat #592

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .reuse/dep5
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ Files: README.md DESIGN.md **/README.md AUTHORS.txt renovate.json go.mod go.sum
Copyright: 2023 The Pion community <https://pion.ly>
License: MIT

Files: testdata/fuzz/* **/testdata/fuzz/* api/*.txt
Files: testdata/seed/* testdata/fuzz/* **/testdata/fuzz/* api/*.txt
Copyright: 2023 The Pion community <https://pion.ly>
License: CC0-1.0
27 changes: 27 additions & 0 deletions fuzz_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
// SPDX-License-Identifier: MIT
package dtls

import (
"os"
"testing"
)

func FuzzUnmarshalBinary(f *testing.F) {
TestResumeClient, err := os.ReadFile("testdata/seed/TestResumeClient.raw")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please have a look at the Go fuzzing tutorial

The Go fuzzing enging has built-in support for reading files from the testdata directory.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, My bad https://go.dev/security/fuzz/#glos-seed-corpus

and the files in the testdata/fuzz/{FuzzTestName} directory within the package

Copy link
Contributor Author

@0x34d 0x34d Nov 14, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, My bad https://go.dev/security/fuzz/#glos-seed-corpus

and the files in the testdata/fuzz/{FuzzTestName} directory within the package

For a minute, I thought I was wrong.
Anything within testdata/fuzz/{FuzzTestName} is a crash and cannot be accepted as a seed for fuzzing. So, yes, my previous commit was on point.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @0x34d, I am not so sure about it.

According to the Go fuzzing documentation, both f.Add() and the files in testdata are used to seed the corpus:

seed corpus: A user-provided corpus for a fuzz test which can be used to guide the fuzzing engine. It is composed of the corpus entries provided by f.Add calls within the fuzz test, and the files in the testdata/fuzz/{FuzzTestName} directory within the package. These entries are run by default with go test, whether fuzzing or not.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the Go fuzzing documentation, both f.Add() and the files in testdata are used to seed the corpus:

No, it's not. I already tried it. This was the whole reason for this comment #592 (comment)

testdata is for reproducing crashes.

if err != nil {
return
}
f.Add(TestResumeClient)

TestResumeServer, err := os.ReadFile("testdata/seed/TestResumeServer.raw")
if err != nil {
return
}
f.Add(TestResumeServer)

f.Fuzz(func(t *testing.T, data []byte) {
deserialized := &State{}
_ = deserialized.UnmarshalBinary(data)
})
}
19 changes: 19 additions & 0 deletions pkg/protocol/extension/fuzz_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
// SPDX-License-Identifier: MIT

package extension

import "testing"

func FuzzUnmarshal(f *testing.F) {
f.Add([]byte{0x00})
f.Add([]byte{1, 6, 8, 3, 88, 12, 2, 47})
f.Add([]byte{0x0, 0xa, 0x0, 0x4, 0x0, 0x2, 0x0, 0x1d})
f.Add([]byte{0x00, 0x0b, 0x00, 0x02, 0x01, 0x00})
f.Add([]byte{0x00, 0x0d, 0x00, 0x08, 0x00, 0x06, 0x04, 0x03, 0x05, 0x03, 0x06, 0x03})
f.Add([]byte{0x00, 0x0e, 0x00, 0x05, 0x00, 0x02, 0x00, 0x01, 0x00})

f.Fuzz(func(t *testing.T, data []byte) {
_, _ = Unmarshal(data)
})
}
67 changes: 57 additions & 10 deletions pkg/protocol/handshake/fuzz_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,64 @@ import (
)

func FuzzDtlsHandshake(f *testing.F) {
rawCertificateRequest := []byte{
0x02, 0x01, 0x40, 0x00, 0x0C, 0x04, 0x03, 0x04, 0x01, 0x05, 0x03,
0x05, 0x01, 0x06, 0x01, 0x02, 0x01, 0x00, 0x06, 0x00, 0x04, 0x74, 0x65, 0x73, 0x74,
}
rawCertificateVerify := []byte{
0x04, 0x03, 0x00, 0x47, 0x30, 0x45, 0x02, 0x20, 0x6b, 0x63, 0x17, 0xad, 0xbe, 0xb7, 0x7b, 0x0f,
0x86, 0x73, 0x39, 0x1e, 0xba, 0xb3, 0x50, 0x9c, 0xce, 0x9c, 0xe4, 0x8b, 0xe5, 0x13, 0x07, 0x59,
0x18, 0x1f, 0xe5, 0xa0, 0x2b, 0xca, 0xa6, 0xad, 0x02, 0x21, 0x00, 0xd3, 0xb5, 0x01, 0xbe, 0x87,
0x6c, 0x04, 0xa1, 0xdc, 0x28, 0xaa, 0x5f, 0xf7, 0x1e, 0x9c, 0xc0, 0x1e, 0x00, 0x2c, 0xe5, 0x94,
0xbb, 0x03, 0x0e, 0xf1, 0xcb, 0x28, 0x22, 0x33, 0x23, 0x88, 0xad,
}
rawClientHello := []byte{
0xfe, 0xfd, 0xb6, 0x2f, 0xce, 0x5c, 0x42, 0x54, 0xff, 0x86, 0xe1, 0x24, 0x41, 0x91, 0x42,
0x62, 0x15, 0xad, 0x16, 0xc9, 0x15, 0x8d, 0x95, 0x71, 0x8a, 0xbb, 0x22, 0xd7, 0x47, 0xec,
0xd8, 0x3d, 0xdc, 0x4b, 0x00, 0x14, 0xe6, 0x14, 0x3a, 0x1b, 0x04, 0xea, 0x9e, 0x7a, 0x14,
0xd6, 0x6c, 0x57, 0xd0, 0x0e, 0x32, 0x85, 0x76, 0x18, 0xde, 0xd8, 0x00, 0x04, 0xc0, 0x2b,
0xc0, 0x0a, 0x01, 0x00, 0x00, 0x08, 0x00, 0x0a, 0x00, 0x04, 0x00, 0x02, 0x00, 0x1d,
}
rawClientKeyExchange := []byte{
0x20, 0x26, 0x78, 0x4a, 0x78, 0x70, 0xc1, 0xf9, 0x71, 0xea, 0x50, 0x4a, 0xb5, 0xbb, 0x00, 0x76,
0x02, 0x05, 0xda, 0xf7, 0xd0, 0x3f, 0xe3, 0xf7, 0x4e, 0x8a, 0x14, 0x6f, 0xb7, 0xe0, 0xc0, 0xff,
0x54,
}
rawFinished := []byte{
0x01, 0x01, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
}
rawHelloVerifyRequest := []byte{
0xfe, 0xff, 0x14, 0x25, 0xfb, 0xee, 0xb3, 0x7c, 0x95, 0xcf, 0x00,
0xeb, 0xad, 0xe2, 0xef, 0xc7, 0xfd, 0xbb, 0xed, 0xf7, 0x1f, 0x6c, 0xcd,
}
rawServerHello := []byte{
0xfe, 0xfd, 0x21, 0x63, 0x32, 0x21, 0x81, 0x0e, 0x98, 0x6c,
0x85, 0x3d, 0xa4, 0x39, 0xaf, 0x5f, 0xd6, 0x5c, 0xcc, 0x20,
0x7f, 0x7c, 0x78, 0xf1, 0x5f, 0x7e, 0x1c, 0xb7, 0xa1, 0x1e,
0xcf, 0x63, 0x84, 0x28, 0x00, 0xc0, 0x2b, 0x00, 0x00, 0x00,
}
rawServerKeyExchange := []byte{
0x03, 0x00, 0x1d, 0x41, 0x04, 0x0c, 0xb9, 0xa3, 0xb9, 0x90, 0x71, 0x35, 0x4a, 0x08, 0x66, 0xaf,
0xd6, 0x88, 0x58, 0x29, 0x69, 0x98, 0xf1, 0x87, 0x0f, 0xb5, 0xa8, 0xcd, 0x92, 0xf6, 0x2b, 0x08,
0x0c, 0xd4, 0x16, 0x5b, 0xcc, 0x81, 0xf2, 0x58, 0x91, 0x8e, 0x62, 0xdf, 0xc1, 0xec, 0x72, 0xe8,
0x47, 0x24, 0x42, 0x96, 0xb8, 0x7b, 0xee, 0xe7, 0x0d, 0xdc, 0x44, 0xec, 0xf3, 0x97, 0x6b, 0x1b,
0x45, 0x28, 0xac, 0x3f, 0x35, 0x02, 0x03, 0x00, 0x47, 0x30, 0x45, 0x02, 0x21, 0x00, 0xb2, 0x0b,
0x22, 0x95, 0x3d, 0x56, 0x57, 0x6a, 0x3f, 0x85, 0x30, 0x6f, 0x55, 0xc3, 0xf4, 0x24, 0x1b, 0x21,
0x07, 0xe5, 0xdf, 0xba, 0x24, 0x02, 0x68, 0x95, 0x1f, 0x6e, 0x13, 0xbd, 0x9f, 0xaa, 0x02, 0x20,
0x49, 0x9c, 0x9d, 0xdf, 0x84, 0x60, 0x33, 0x27, 0x96, 0x9e, 0x58, 0x6d, 0x72, 0x13, 0xe7, 0x3a,
0xe8, 0xdf, 0x43, 0x75, 0xc7, 0xb9, 0x37, 0x6e, 0x90, 0xe5, 0x3b, 0x81, 0xd4, 0xda, 0x68, 0xcd,
}
f.Add(rawCertificateRequest)
f.Add(rawCertificateVerify)
f.Add(rawClientHello)
f.Add(rawClientKeyExchange)
f.Add(rawFinished)
f.Add(rawHelloVerifyRequest)
f.Add(rawServerHello)
f.Add(rawServerKeyExchange)

f.Fuzz(func(t *testing.T, data []byte) {
h := &Handshake{}
if err := h.Unmarshal(data); err != nil {
return
}
buf, err := h.Marshal()
if err != nil {
t.Fatal(err)
}
if len(buf) == 0 {
t.Fatal("Zero buff")
}
_ = h.Unmarshal(data)
})
}
46 changes: 20 additions & 26 deletions pkg/protocol/recordlayer/fuzz_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,33 @@
package recordlayer

import (
"reflect"
"testing"
)

func headerMismatch(a, b Header) bool {
// Ignoring content length for now.
a.ContentLen = b.ContentLen
return !reflect.DeepEqual(a, b)
}

func FuzzRecordLayer(f *testing.F) {
Data := []byte{
0x14, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x01, 0x01,
}
f.Add(Data)

f.Fuzz(func(t *testing.T, data []byte) {
var r RecordLayer
if err := r.Unmarshal(data); err != nil {
return
}

buf, err := r.Marshal()
if err != nil {
return
}

if len(buf) == 0 {
t.Fatal("Zero buff")
}
_ = r.Unmarshal(data)
})
}

var nr RecordLayer
if err = nr.Unmarshal(data); err != nil {
t.Fatal(err)
}
func FuzzUnpackDatagram(f *testing.F) {
Datasingle := []byte{
0x14, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x01, 0x01,
}
Datamulti := []byte{
0x14, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x01, 0x01,
0x14, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x01, 0x01,
}
f.Add(Datasingle)
f.Add(Datamulti)

if headerMismatch(nr.Header, r.Header) {
t.Fatalf("Header mismatch: %+v != %+v", nr.Header, r.Header)
}
f.Fuzz(func(t *testing.T, data []byte) {
_, _ = UnpackDatagram(data)
})
}
Binary file added testdata/seed/TestResumeClient.raw
Binary file not shown.
1 change: 1 addition & 0 deletions testdata/seed/TestResumeServer.raw
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
þÿserializedStateÿ‚LocalEpochRemoteEpochLocalRandomÿ„RemoteRandomÿ„CipherSuiteIDMasterSecretSequenceNumberSRTPProtectionProfilePeerCertificatesÿ†IdentityHintSessionIDLocalConnectionIDRemoteConnectionIDIsClientÿƒ[32]uint8ÿ„@ÿ…[][]uint8ÿ†ÿÿ‚ e&MÿáÿÄKÿÇ'ÿ®ÿë/ÿ‘kZO6gÿòMPÿúIÿ¾ÿáÿ¡ÿþÿõ} e&MÿáÿÐÿèÿÚÿ…@ÿ¼Cs.=ÿ­5Zÿ£{ÿºÿÛrg:[ÿ¡ÿ˜LeÿÚþÀ+0yçü*’[Š\B GEvê5ìÙ•=’uõCwP9ë rï48rËyâã;k.E
Loading