github.com/mattermosttest/mattermost-server/v5@v5.0.0-20200917143240-9dfa12e121f9/app/extract_plugin_tar_test.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package app 5 6 import ( 7 "archive/tar" 8 "bytes" 9 "compress/gzip" 10 "fmt" 11 "io/ioutil" 12 "os" 13 "path/filepath" 14 "sort" 15 "strings" 16 "testing" 17 18 "github.com/stretchr/testify/assert" 19 "github.com/stretchr/testify/require" 20 ) 21 22 func assertDirectoryContents(t *testing.T, dir string, expectedFiles []string) { 23 var files []string 24 err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { 25 require.NoError(t, err) 26 file := strings.TrimPrefix(path, dir) 27 file = strings.TrimPrefix(file, "/") 28 files = append(files, file) 29 return nil 30 }) 31 require.NoError(t, err) 32 33 sort.Strings(files) 34 sort.Strings(expectedFiles) 35 assert.Equal(t, expectedFiles, files) 36 } 37 38 func TestExtractTarGz(t *testing.T) { 39 makeArchive := func(t *testing.T, files []*tar.Header) bytes.Buffer { 40 // Build an in-memory archive with the specified files, writing the path as each 41 // file's contents when applicable. 42 var archive bytes.Buffer 43 archiveGzWriter := gzip.NewWriter(&archive) 44 archiveWriter := tar.NewWriter(archiveGzWriter) 45 for _, file := range files { 46 if file.Typeflag == tar.TypeReg { 47 contents := []byte(file.Name) 48 file.Size = int64(len(contents)) 49 err := archiveWriter.WriteHeader(file) 50 require.NoError(t, err) 51 52 var written int 53 written, err = archiveWriter.Write(contents) 54 require.NoError(t, err) 55 require.EqualValues(t, len(contents), written) 56 } else { 57 err := archiveWriter.WriteHeader(file) 58 require.NoError(t, err) 59 } 60 } 61 err := archiveWriter.Close() 62 require.NoError(t, err) 63 err = archiveGzWriter.Close() 64 require.NoError(t, err) 65 66 return archive 67 } 68 69 t.Run("empty dst", func(t *testing.T) { 70 archive := makeArchive(t, nil) 71 err := extractTarGz(&archive, "") 72 require.Error(t, err) 73 }) 74 75 testCases := []struct { 76 Files []*tar.Header 77 ExpectedError bool 78 ExpectedFiles []string 79 }{ 80 { 81 []*tar.Header{{Name: "../test/path", Typeflag: tar.TypeDir}}, 82 true, 83 nil, 84 }, 85 { 86 []*tar.Header{{Name: "../../test/path", Typeflag: tar.TypeDir}}, 87 true, 88 nil, 89 }, 90 { 91 []*tar.Header{{Name: "../../test/../path", Typeflag: tar.TypeDir}}, 92 true, 93 nil, 94 }, 95 { 96 []*tar.Header{{Name: "test/../../path", Typeflag: tar.TypeDir}}, 97 true, 98 nil, 99 }, 100 { 101 []*tar.Header{{Name: "test/path/../..", Typeflag: tar.TypeDir}}, 102 false, 103 []string{""}, 104 }, 105 { 106 []*tar.Header{{Name: "test", Typeflag: tar.TypeDir}}, 107 false, 108 []string{"", "test"}, 109 }, 110 { 111 []*tar.Header{ 112 {Name: "test", Typeflag: tar.TypeDir}, 113 {Name: "test/path", Typeflag: tar.TypeDir}, 114 }, 115 false, 116 []string{"", "test", "test/path"}, 117 }, 118 { 119 []*tar.Header{ 120 {Name: "test", Typeflag: tar.TypeDir}, 121 {Name: "test/path/", Typeflag: tar.TypeDir}, 122 }, 123 false, 124 []string{"", "test", "test/path"}, 125 }, 126 { 127 []*tar.Header{ 128 {Name: "test", Typeflag: tar.TypeDir}, 129 {Name: "test/path", Typeflag: tar.TypeDir}, 130 {Name: "test/path/file.ext", Typeflag: tar.TypeReg}, 131 }, 132 false, 133 []string{"", "test", "test/path", "test/path/file.ext"}, 134 }, 135 { 136 []*tar.Header{ 137 {Name: "/../../file.ext", Typeflag: tar.TypeReg}, 138 }, 139 true, 140 nil, 141 }, 142 { 143 []*tar.Header{ 144 {Name: "/../../link", Typeflag: tar.TypeLink}, 145 }, 146 false, 147 []string{""}, 148 }, 149 { 150 []*tar.Header{ 151 {Name: "..file", Typeflag: tar.TypeReg}, 152 }, 153 false, 154 []string{"", "..file"}, 155 }, 156 } 157 158 for i, testCase := range testCases { 159 t.Run(fmt.Sprintf("test-%d", i), func(t *testing.T) { 160 dst, err := ioutil.TempDir("", "TestExtractTarGz") 161 require.NoError(t, err) 162 defer os.RemoveAll(dst) 163 164 archive := makeArchive(t, testCase.Files) 165 err = extractTarGz(&archive, dst) 166 if testCase.ExpectedError { 167 require.Error(t, err) 168 } else { 169 require.NoError(t, err) 170 assertDirectoryContents(t, dst, testCase.ExpectedFiles) 171 } 172 }) 173 } 174 }