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: remove tar operations in alpine fuzzer #1322

Merged
merged 1 commit into from
Feb 3, 2023
Merged
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 go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -143,4 +143,4 @@ require (
gopkg.in/yaml.v3 v3.0.1 // indirect
)

replace github.com/AdaLogics/go-fuzz-headers => github.com/AdamKorcz/go-fuzz-headers-1 v0.0.0-20230111232327-1f10f66a31bf
replace github.com/AdaLogics/go-fuzz-headers => github.com/AdamKorcz/go-fuzz-headers-1 v0.0.0-20230201144411-22e92b796899
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ contrib.go.opencensus.io/integrations/ocsql v0.1.7/go.mod h1:8DsSdjz3F+APR+0z0Wk
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek=
filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
github.com/AdamKorcz/go-fuzz-headers-1 v0.0.0-20230111232327-1f10f66a31bf h1:EamsQRRH14elXDAofrOK5Ja6fDTJSrbKstpr1grrGX4=
github.com/AdamKorcz/go-fuzz-headers-1 v0.0.0-20230111232327-1f10f66a31bf/go.mod h1:0vOOKsOMKPThRu9lQMAxcQ8D60f8U+wHXl07SyUw0+U=
github.com/AdamKorcz/go-fuzz-headers-1 v0.0.0-20230201144411-22e92b796899 h1:tkR1HRX5M+lhVP9WOioyxEYDyXeV0I2oBAOugCW87xY=
github.com/AdamKorcz/go-fuzz-headers-1 v0.0.0-20230201144411-22e92b796899/go.mod h1:0vOOKsOMKPThRu9lQMAxcQ8D60f8U+wHXl07SyUw0+U=
github.com/Azure/azure-amqp-common-go/v3 v3.2.1/go.mod h1:O6X1iYHP7s2x7NjUKsXVhkwWrQhxrd+d8/3rRadj4CI=
github.com/Azure/azure-amqp-common-go/v3 v3.2.2/go.mod h1:O6X1iYHP7s2x7NjUKsXVhkwWrQhxrd+d8/3rRadj4CI=
github.com/Azure/azure-pipeline-go v0.2.3 h1:7U9HBg1JFK3jHl5qmo4CTZKFTVgMwdFHMVtCdfBE21U=
Expand Down
174 changes: 66 additions & 108 deletions pkg/types/alpine/fuzz_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ package alpine

import (
"archive/tar"

"bytes"
"compress/gzip"
"io"
"strings"
"testing"

Expand Down Expand Up @@ -98,180 +98,121 @@ func createPkgInfoFileContents(ff *fuzz.ConsumeFuzzer) ([]byte, error) {
return []byte(b.String()), nil
}

// Copies files from structured tarBytes to the tw
// This is used when adding files to tarBytes
func copyTarFiles(tw *tar.Writer, tarBytes []byte) error {
tr := tar.NewReader(bytes.NewReader(tarBytes))
for {
hdr, err := tr.Next()
if err == io.EOF {
break
}
if err != nil {
return err
}
fileContents, err := io.ReadAll(tr)
if err != nil {
return err
}
tw.WriteHeader(hdr)
tw.Write(fileContents)
}
return nil
}

// Adds a .SIGN file to tarBytes
func addSignFile(tw *tar.Writer, ff *fuzz.ConsumeFuzzer, tarBytes []byte) error {
err := copyTarFiles(tw, tarBytes)
if err != nil {
return err
}
func addSignFile(ff *fuzz.ConsumeFuzzer, tarFiles []*fuzz.TarFile) ([]*fuzz.TarFile, error) {
SIGNFileContents, err := ff.GetBytes()
if err != nil {
return err
return tarFiles, err
}

SIGNFileName, err := getSignFilename(ff)
if err != nil {
return err
return tarFiles, err
}
tw.WriteHeader(&tar.Header{
Name: SIGNFileName,
Mode: 0644,
Size: int64(len(SIGNFileContents)),
Typeflag: tar.TypeReg,
Gid: 0,
Uid: 0,
})
tw.Write(SIGNFileContents)
return nil
signFile := &fuzz.TarFile{
Body: SIGNFileContents,
Hdr: &tar.Header{
Name: SIGNFileName,
Mode: 0644,
Size: int64(len(SIGNFileContents)),
Typeflag: tar.TypeReg,
Gid: 0,
Uid: 0,
},
}
tarFiles = append(tarFiles, signFile)

return tarFiles, nil
}

// Allows the fuzzer to randomize whether a .SIGN file should
// be added to tarBytes
func shouldAddSignFile(ff *fuzz.ConsumeFuzzer, tarBytes []byte) bool {
func shouldAddSignFile(ff *fuzz.ConsumeFuzzer, tarFiles []*fuzz.TarFile) bool {
shouldRequireSIGNFile, err := ff.GetBool()
if err != nil {
return false
}
if shouldRequireSIGNFile {
tr := tar.NewReader(bytes.NewReader(tarBytes))
for {
hdr, err := tr.Next()
if err == io.EOF {
return false
}
if err != nil {
for _, tarFile := range tarFiles {
if strings.HasPrefix(tarFile.Hdr.Name, ".SIGN") {
return false
}
if strings.HasPrefix(hdr.Name, ".SIGN") {
return true
}
}
return true
}
return false
}

// Allows the fuzzer to randomize whether a .PKGINFO file should
// be added to tarBytes
func shouldAddPkgInfoFile(ff *fuzz.ConsumeFuzzer, tarBytes []byte) bool {
func shouldAddPkgInfoFile(ff *fuzz.ConsumeFuzzer, tarFiles []*fuzz.TarFile) bool {
shouldRequirePKGINFOFile, err := ff.GetBool()
if err != nil {
return false
}
if shouldRequirePKGINFOFile {
tr := tar.NewReader(bytes.NewReader(tarBytes))
for {
hdr, err := tr.Next()
if err == io.EOF {
return false
}
if err != nil {
for _, tarFile := range tarFiles {
if strings.HasPrefix(tarFile.Hdr.Name, ".PKGINFO") {
return false
}
if hdr.Name == ".PKGINFO" {
return true
}
}
return true
}
return false
}

// Adds the .PKGINFO file to tarBytes
func addPkgInfoFile(tw *tar.Writer, ff *fuzz.ConsumeFuzzer, tarBytes []byte) error {
tr := tar.NewReader(bytes.NewReader(tarBytes))
for {
hdr, err := tr.Next()
if err == io.EOF {
break
}
if err != nil {
return err
}
fileContents, err := io.ReadAll(tr)
if err != nil {
return err
}
tw.WriteHeader(hdr)
tw.Write(fileContents)
}
PKGINFOFileContents, err := createPkgInfoFileContents(ff) //nolint:all
// Adds the .PKGINFO file to the tar files
func addPkgInfoFile(ff *fuzz.ConsumeFuzzer, tarFiles []*fuzz.TarFile) ([]*fuzz.TarFile, error) {
tarFile := &fuzz.TarFile{}
PKGINFOFileContents, err := createPkgInfoFileContents(ff)
if err != nil {
return err
return tarFiles, err
}
tw.WriteHeader(&tar.Header{
tarFile.Body = PKGINFOFileContents
tarFile.Hdr = &tar.Header{
Name: ".PKGINFO",
Mode: 0644,
Size: int64(len(PKGINFOFileContents)),
Typeflag: tar.TypeReg,
Gid: 0,
Uid: 0,
})
tw.Write(PKGINFOFileContents)
return nil
}

return tarFiles, nil
}

// FuzzPackageUnmarshal implements the fuzz test
func FuzzPackageUnmarshal(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
var tarFiles, tarFiles2 []*fuzz.TarFile
var err error

ff := fuzz.NewConsumer(data)

// signature segment
tarBytes, err := ff.TarBytes()
tarFiles, err = ff.TarFiles()
if err != nil {
return
}

if shouldAddSignFile(ff, tarBytes) {
var buf bytes.Buffer
tw := tar.NewWriter(&buf)
err := addSignFile(tw, ff, tarBytes)
if shouldAddSignFile(ff, tarFiles) {
tarFiles, err = addSignFile(ff, tarFiles)
if err != nil {
tw.Close()
t.Skip()
}
tw.Close()
tarBytes = buf.Bytes()
}

// control segment
tarBytes2, err := ff.TarBytes()
tarFiles2, err = ff.TarFiles()
if err != nil {
t.Skip()
}

if shouldAddPkgInfoFile(ff, tarBytes2) {
var buf bytes.Buffer
tw := tar.NewWriter(&buf)
err := addPkgInfoFile(tw, ff, tarBytes)
if shouldAddPkgInfoFile(ff, tarFiles2) {
tarFiles2, err = addPkgInfoFile(ff, tarFiles2)
if err != nil {
tw.Close()
t.Skip()
}
tw.Close()
tarBytes2 = buf.Bytes()
}

concatenated, err := concatenateTarBytes(tarBytes, tarBytes2)
concatenated, err := concatenateTarArchives(tarFiles, tarFiles2)
if err != nil {
t.Skip()
}
Expand All @@ -281,8 +222,25 @@ func FuzzPackageUnmarshal(f *testing.F) {
})
}

// Concatenates two tar archives.
func concatenateTarBytes(tarBytes []byte, tarBytes2 []byte) ([]byte, error) {
func concatenateTarArchives(tarFiles1 []*fuzz.TarFile, tarFiles2 []*fuzz.TarFile) ([]byte, error) {
var buf1, buf2 bytes.Buffer

tw1 := tar.NewWriter(&buf1)
for _, tf := range tarFiles1 {
tw1.WriteHeader(tf.Hdr)
tw1.Write(tf.Body)
}
tw1.Close()
tarBytes := buf1.Bytes()

tw2 := tar.NewWriter(&buf2)
for _, tf := range tarFiles2 {
tw2.WriteHeader(tf.Hdr)
tw2.Write(tf.Body)
}
tw2.Close()
tarBytes2 := buf2.Bytes()

var b1 bytes.Buffer
w1 := gzip.NewWriter(&b1)
defer w1.Close()
Expand Down
3 changes: 3 additions & 0 deletions tests/fuzz-testdata/FuzzPackageUnmarshal.options
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[libfuzzer]
max_len = 300000
len_control = 0