From: Alexander Yastrebov Date: Fri, 11 Nov 2022 23:23:19 +0000 (+0000) Subject: archive/zip: don't read directories containing file data X-Git-Tag: go1.20rc1~292 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=40bdcbb483548c0b660503c3ba80f9676b98fd5f;p=gostls13.git archive/zip: don't read directories containing file data Fixes #54801 Change-Id: I3d03516792975ddb09835b2621c57e12e7cbad35 GitHub-Last-Rev: 4faa7e14dcc48c05d707f1e137d915da24133e14 GitHub-Pull-Request: golang/go#56714 Reviewed-on: https://go-review.googlesource.com/c/go/+/449955 Run-TryBot: Ian Lance Taylor TryBot-Result: Gopher Robot Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor Auto-Submit: Ian Lance Taylor Reviewed-by: Joedian Reid --- diff --git a/src/archive/zip/reader.go b/src/archive/zip/reader.go index db118ce854..db9ae3cf36 100644 --- a/src/archive/zip/reader.go +++ b/src/archive/zip/reader.go @@ -197,6 +197,13 @@ func (f *File) Open() (io.ReadCloser, error) { if err != nil { return nil, err } + if strings.HasSuffix(f.Name, "/") { + if f.CompressedSize64 != 0 || f.hasDataDescriptor() { + return &dirReader{ErrFormat}, nil + } else { + return &dirReader{io.EOF}, nil + } + } size := int64(f.CompressedSize64) r := io.NewSectionReader(f.zipr, f.headerOffset+bodyOffset, size) dcomp := f.zip.decompressor(f.Method) @@ -228,6 +235,18 @@ func (f *File) OpenRaw() (io.Reader, error) { return r, nil } +type dirReader struct { + err error +} + +func (r *dirReader) Read([]byte) (int, error) { + return 0, r.err +} + +func (r *dirReader) Close() error { + return nil +} + type checksumReader struct { rc io.ReadCloser hash hash.Hash32 diff --git a/src/archive/zip/reader_test.go b/src/archive/zip/reader_test.go index 84742c7d2a..3123892fb7 100644 --- a/src/archive/zip/reader_test.go +++ b/src/archive/zip/reader_test.go @@ -1554,3 +1554,33 @@ func TestUnderSize(t *testing.T) { }) } } + +func TestIssue54801(t *testing.T) { + for _, input := range []string{"testdata/readme.zip", "testdata/dd.zip"} { + z, err := OpenReader(input) + if err != nil { + t.Fatal(err) + } + defer z.Close() + + for _, f := range z.File { + // Make file a directory + f.Name += "/" + + t.Run(f.Name, func(t *testing.T) { + t.Logf("CompressedSize64: %d, Flags: %#x", f.CompressedSize64, f.Flags) + + rd, err := f.Open() + if err != nil { + t.Fatal(err) + } + defer rd.Close() + + n, got := io.Copy(io.Discard, rd) + if n != 0 || got != ErrFormat { + t.Fatalf("Error mismatch, got: %d, %v, want: %v", n, got, ErrFormat) + } + }) + } + } +}