func/pkg/tar/tar_errors_test.go

317 lines
5.6 KiB
Go

package tar_test
import (
"archive/tar"
"bytes"
"io"
"testing"
tarutil "knative.dev/func/pkg/tar"
)
func TestExtractErrors(t *testing.T) {
tests := []struct {
name string
createReader func(*testing.T) io.Reader
wantErr bool
}{
{
name: "non escaping link",
createReader: nonEscapingSymlink,
wantErr: false,
},
{
name: "missing parent of regular file",
createReader: missingParentRegular,
wantErr: false,
},
{
name: "missing parent of link",
createReader: missingParentLink,
wantErr: false,
},
{
name: "absolute symlink",
createReader: absoluteSymlink,
wantErr: true,
},
{
name: "direct escape",
createReader: directEscape,
wantErr: true,
},
{
name: "indirect link escape",
createReader: indirectLinkEscape,
wantErr: true,
},
{
name: "indirect link escape with overwrite",
createReader: indirectLinkEscapeWithOverwrites,
wantErr: true,
},
{
name: "double dot in name",
createReader: doubleDotInName,
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
d := t.TempDir()
if err := tarutil.Extract(tt.createReader(t), d); (err != nil) != tt.wantErr {
t.Errorf("Extract() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
func nonEscapingSymlink(t *testing.T) io.Reader {
t.Helper()
var err error
var buff bytes.Buffer
w := tar.NewWriter(&buff)
defer func(w *tar.Writer) {
_ = w.Close()
}(w)
err = w.WriteHeader(&tar.Header{
Name: "subdir",
Typeflag: tar.TypeDir,
Mode: 0777,
})
if err != nil {
t.Fatal(err)
}
err = w.WriteHeader(&tar.Header{
Name: "subdir/parent",
Linkname: "..",
Typeflag: tar.TypeSymlink,
Mode: 0777,
})
if err != nil {
t.Fatal(err)
}
return &buff
}
func absoluteSymlink(t *testing.T) io.Reader {
var err error
var buff bytes.Buffer
w := tar.NewWriter(&buff)
defer func(w *tar.Writer) {
_ = w.Close()
}(w)
err = w.WriteHeader(&tar.Header{
Name: "a.lnk",
Linkname: "/etc/shadow",
Typeflag: tar.TypeSymlink,
Mode: 0777,
})
if err != nil {
t.Fatal(err)
}
return &buff
}
func directEscape(t *testing.T) io.Reader {
t.Helper()
var err error
var buff bytes.Buffer
var msg = "I am free!!!"
w := tar.NewWriter(&buff)
defer func(w *tar.Writer) {
_ = w.Close()
}(w)
err = w.WriteHeader(&tar.Header{
Name: "../escaped.txt",
Typeflag: tar.TypeReg,
Mode: 0644,
Size: int64(len(msg)),
})
if err != nil {
t.Fatal(err)
}
_, err = w.Write([]byte(msg))
if err != nil {
t.Fatal(err)
}
return &buff
}
func indirectLinkEscape(t *testing.T) io.Reader {
t.Helper()
t.Skip("we are not checking for this since the core utils tar does not too")
var err error
var buff bytes.Buffer
w := tar.NewWriter(&buff)
defer func(w *tar.Writer) {
_ = w.Close()
}(w)
err = w.WriteHeader(&tar.Header{
Name: "subdir",
Typeflag: tar.TypeDir,
Mode: 0777,
})
if err != nil {
t.Fatal(err)
}
err = w.WriteHeader(&tar.Header{
Name: "subdir/parent",
Linkname: "..",
Typeflag: tar.TypeSymlink,
Mode: 0777,
})
if err != nil {
t.Fatal(err)
}
err = w.WriteHeader(&tar.Header{
Name: "escape",
Linkname: "subdir/parent/..",
Typeflag: tar.TypeSymlink,
Mode: 0777,
})
if err != nil {
t.Fatal(err)
}
return &buff
}
func indirectLinkEscapeWithOverwrites(t *testing.T) io.Reader {
t.Helper()
t.Skip("we are not checking for this since the core utils tar does not too")
var err error
var buff bytes.Buffer
w := tar.NewWriter(&buff)
defer func(w *tar.Writer) {
_ = w.Close()
}(w)
err = w.WriteHeader(&tar.Header{
Name: "subdir",
Typeflag: tar.TypeDir,
Mode: 0777,
})
if err != nil {
t.Fatal(err)
}
err = w.WriteHeader(&tar.Header{
Name: "subdir/parent",
Typeflag: tar.TypeDir,
Mode: 0777,
})
if err != nil {
t.Fatal(err)
}
err = w.WriteHeader(&tar.Header{
Name: "escape",
Linkname: "subdir/parent/..",
Typeflag: tar.TypeSymlink,
Mode: 0777,
})
if err != nil {
t.Fatal(err)
}
err = w.WriteHeader(&tar.Header{
Name: "subdir/parent",
Linkname: "..",
Typeflag: tar.TypeSymlink,
Mode: 0777,
})
if err != nil {
t.Fatal(err)
}
return &buff
}
func doubleDotInName(t *testing.T) io.Reader {
t.Helper()
var err error
var buff bytes.Buffer
w := tar.NewWriter(&buff)
defer func(w *tar.Writer) {
_ = w.Close()
}(w)
err = w.WriteHeader(&tar.Header{
Name: "subdir",
Typeflag: tar.TypeDir,
Mode: 0777,
})
if err != nil {
t.Fatal(err)
}
err = w.WriteHeader(&tar.Header{
Name: "subdir/parent",
Typeflag: tar.TypeDir,
Mode: 0777,
})
if err != nil {
t.Fatal(err)
}
err = w.WriteHeader(&tar.Header{
Name: "subdir/parent/../../a.txt",
Typeflag: tar.TypeReg,
Mode: 0644,
Size: 0,
})
if err != nil {
t.Fatal(err)
}
return &buff
}
func missingParentRegular(t *testing.T) io.Reader {
var err error
var buff bytes.Buffer
w := tar.NewWriter(&buff)
defer func(w *tar.Writer) {
_ = w.Close()
}(w)
err = w.WriteHeader(&tar.Header{
Name: "missing/a.txt",
Typeflag: tar.TypeReg,
Size: 0,
Mode: 0644,
})
if err != nil {
t.Fatal(err)
}
return &buff
}
func missingParentLink(t *testing.T) io.Reader {
var err error
var buff bytes.Buffer
w := tar.NewWriter(&buff)
defer func(w *tar.Writer) {
_ = w.Close()
}(w)
err = w.WriteHeader(&tar.Header{
Name: "missing/a.lnk",
Linkname: "a.txt",
Typeflag: tar.TypeSymlink,
Mode: 0777,
})
if err != nil {
t.Fatal(err)
}
return &buff
}