@@ -35,6 +35,7 @@ type untarTestCase struct {
3535 content []byte
3636 wantErr string
3737 maxUntarSize int
38+ fileMode int64
3839}
3940
4041func TestUntar (t * testing.T ) {
@@ -178,6 +179,40 @@ func TestUntar(t *testing.T) {
178179 }
179180}
180181
182+ func TestUntarDirectoryPermissions (t * testing.T ) {
183+ testDirName := "test-dir"
184+
185+ f , err := createTestTar (untarTestCase {
186+ fileName : testDirName + "/" , // from tar.Header: a trailing slash makes the entry a TypeDir
187+ fileMode : 0o555 ,
188+ content : nil ,
189+ })
190+ if err != nil {
191+ t .Fatalf ("creating test tar: %v" , err )
192+ }
193+
194+ targetDir := t .TempDir ()
195+
196+ if err := Untar (f , targetDir ); err != nil {
197+ t .Fatalf ("untar: %v" , err )
198+ }
199+
200+ fullPath := filepath .Join (targetDir , testDirName )
201+ fi , err := os .Lstat (fullPath )
202+ if err != nil {
203+ t .Errorf ("stat %q: %v" , fullPath , err )
204+ }
205+
206+ if ! fi .Mode ().IsDir () {
207+ t .Fatalf ("%q: not a directory" , fullPath )
208+ }
209+
210+ ownerPerm := fi .Mode ().Perm () & 0o700
211+ if ownerPerm != 0o700 {
212+ t .Errorf ("the owner must always be able to traverse, read, and write extracted directories" )
213+ }
214+ }
215+
181216func Fuzz_Untar (f * testing.F ) {
182217 tf , err := createTestTar (untarTestCase {
183218 name : "file at root" ,
@@ -211,10 +246,15 @@ func createTestTar(tt untarTestCase) (*os.File, error) {
211246 gzw := gzip .NewWriter (f )
212247 writer := tar .NewWriter (gzw )
213248
249+ fileMode := tt .fileMode
250+ if fileMode == 0 {
251+ fileMode = 0o777
252+ }
253+
214254 writer .WriteHeader (& tar.Header {
215255 Name : tt .fileName ,
216256 Size : int64 (len (tt .content )),
217- Mode : 0o777 ,
257+ Mode : fileMode ,
218258 })
219259
220260 writer .Write (tt .content )
0 commit comments