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) + } + }) + } + } +}