]> Cypherpunks.ru repositories - gostls13.git/commitdiff
archive/zip: fail fast if UncompressedSize64 < nread
authorMeng Zhuo <mzh@golangcn.org>
Wed, 24 Nov 2021 08:33:14 +0000 (16:33 +0800)
committermzh <mzh@golangcn.org>
Mon, 11 Apr 2022 01:24:31 +0000 (01:24 +0000)
The zip reader checks that the uncompressed file size is valid
after all compressed files read until EOF.
However in between reading each file, there could have already
been an overflow where nread > UncompressedSize64 hence this
change will now return ErrFormat in such situations.

Fixes #49791

Change-Id: If3584a57d173de6a97bf35c07d2a99ff6972f820
Reviewed-on: https://go-review.googlesource.com/c/go/+/366854
Trust: mzh <mzh@golangcn.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Emmanuel Odeke <emmanuel@orijtech.com>
Trust: Emmanuel Odeke <emmanuel@orijtech.com>

src/archive/zip/reader.go
src/archive/zip/reader_test.go

index 92fd6f6a9252525fb392e982952cfed66ce33e13..b4f6a8d7149013311efbda2ab06241584e2512bc 100644 (file)
@@ -229,6 +229,9 @@ func (r *checksumReader) Read(b []byte) (n int, err error) {
        n, err = r.rc.Read(b)
        r.hash.Write(b[:n])
        r.nread += uint64(n)
+       if r.nread > r.f.UncompressedSize64 {
+               return 0, ErrFormat
+       }
        if err == nil {
                return
        }
index 9bc23642c0e66f7e05eeb2565f0215654106b8fc..fd0a171304ce14a47e2528d9d89edd9432b8a61e 100644 (file)
@@ -1407,3 +1407,30 @@ func TestCVE202141772(t *testing.T) {
                t.Errorf("Inconsistent name in info entry: %v", name)
        }
 }
+
+func TestUnderSize(t *testing.T) {
+       z, err := OpenReader("testdata/readme.zip")
+       if err != nil {
+               t.Fatal(err)
+       }
+       defer z.Close()
+
+       for _, f := range z.File {
+               f.UncompressedSize64 = 1
+       }
+
+       for _, f := range z.File {
+               t.Run(f.Name, func(t *testing.T) {
+                       rd, err := f.Open()
+                       if err != nil {
+                               t.Fatal(err)
+                       }
+                       defer rd.Close()
+
+                       _, err = io.Copy(io.Discard, rd)
+                       if err != ErrFormat {
+                               t.Fatalf("Error mismatch\n\tGot:  %v\n\tWant: %v", err, ErrFormat)
+                       }
+               })
+       }
+}