]> Cypherpunks repositories - gostls13.git/commitdiff
compress/gzip: return unexpected EOF for certain truncated streams
authorPhil Bracikowski <pbracikowski@influxdata.com>
Wed, 2 Mar 2022 01:51:28 +0000 (01:51 +0000)
committerJoseph Tsai <joetsai@digital-static.net>
Wed, 2 Mar 2022 17:03:04 +0000 (17:03 +0000)
For cases where RFC 1952 requires a field, the code returns the error
io.ErrUnexpectedEOF except in two places: for the FNAME flag or the
FCOMMENT flag. These flags expect a null-terminated string and
readString may return an EOF if the Reader is truncated before a
null byte is found. For consistency with parsing other parts of the
header, this is converted to an unexpected EOF herein.

Follow-up to CL 14832.

Fixes #51417

Change-Id: I173283a6ae309e4a8e52fc15df404ce5db06eff1
GitHub-Last-Rev: 2e573cd961c0b1e4296fbde53097cf5723a2ca29
GitHub-Pull-Request: golang/go#51418
Reviewed-on: https://go-review.googlesource.com/c/go/+/389034
Reviewed-by: Joseph Tsai <joetsai@digital-static.net>
Trust: Joseph Tsai <joetsai@digital-static.net>
Trust: Ian Lance Taylor <iant@golang.org>

src/compress/gzip/gunzip.go
src/compress/gzip/gunzip_test.go

index 924bce10b7c0cb1a901f47255afea99efcfc298a..aa6780f8474989664bfcf6746d36fb83e3e403e8 100644 (file)
@@ -211,14 +211,14 @@ func (z *Reader) readHeader() (hdr Header, err error) {
        var s string
        if flg&flagName != 0 {
                if s, err = z.readString(); err != nil {
-                       return hdr, err
+                       return hdr, noEOF(err)
                }
                hdr.Name = s
        }
 
        if flg&flagComment != 0 {
                if s, err = z.readString(); err != nil {
-                       return hdr, err
+                       return hdr, noEOF(err)
                }
                hdr.Comment = s
        }
index 17c23e8a9be8585e386c97442c07533e3d2677a9..be691854639577f1ce01b948884bfd7ea89c549f 100644 (file)
@@ -359,6 +359,38 @@ var gunzipTests = []gunzipTest{
                },
                io.ErrUnexpectedEOF,
        },
+       {
+               "hello.txt",
+               "gzip header with truncated name",
+               "hello world\n",
+               []byte{
+                       0x1f, 0x8b, 0x08, 0x08, 0xc8, 0x58, 0x13, 0x4a,
+                       0x00, 0x03, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x2e,
+                       0x74, 0x78, 0x74, 0x00, 0xcb, 0x48, 0xcd, 0xc9,
+                       0xc9, 0x57, 0x28, 0xcf, 0x2f, 0xca, 0x49, 0xe1,
+                       0x02, 0x00, 0x2d, 0x3b, 0x08, 0xaf, 0x0c, 0x00,
+                       0x00, 0x00,
+                       0x1f, 0x8b, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0xff, 0x01,
+               },
+               io.ErrUnexpectedEOF,
+       },
+       {
+               "",
+               "gzip header with truncated comment",
+               "hello world\n",
+               []byte{
+                       0x1f, 0x8b, 0x08, 0x10, 0xc8, 0x58, 0x13, 0x4a,
+                       0x00, 0x03, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x2e,
+                       0x74, 0x78, 0x74, 0x00, 0xcb, 0x48, 0xcd, 0xc9,
+                       0xc9, 0x57, 0x28, 0xcf, 0x2f, 0xca, 0x49, 0xe1,
+                       0x02, 0x00, 0x2d, 0x3b, 0x08, 0xaf, 0x0c, 0x00,
+                       0x00, 0x00,
+                       0x1f, 0x8b, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0xff, 0x01,
+               },
+               io.ErrUnexpectedEOF,
+       },
 }
 
 func TestDecompressor(t *testing.T) {
@@ -495,23 +527,45 @@ func TestNilStream(t *testing.T) {
 }
 
 func TestTruncatedStreams(t *testing.T) {
-       const data = "\x1f\x8b\b\x04\x00\tn\x88\x00\xff\a\x00foo bar\xcbH\xcd\xc9\xc9\xd7Q(\xcf/\xcaI\x01\x04:r\xab\xff\f\x00\x00\x00"
+       cases := []struct {
+               name string
+               data []byte
+       }{
+               {
+                       name: "original",
+                       data: []byte("\x1f\x8b\b\x04\x00\tn\x88\x00\xff\a\x00foo bar\xcbH\xcd\xc9\xc9\xd7Q(\xcf/\xcaI\x01\x04:r\xab\xff\f\x00\x00\x00"),
+               },
+               {
+                       name: "truncated name",
+                       data: []byte{
+                               0x1f, 0x8b, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01,
+                       },
+               },
+               {
+                       name: "truncated comment",
+                       data: []byte{
+                               0x1f, 0x8b, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01,
+                       },
+               },
+       }
 
        // Intentionally iterate starting with at least one byte in the stream.
-       for i := 1; i < len(data)-1; i++ {
-               r, err := NewReader(strings.NewReader(data[:i]))
-               if err != nil {
+       for _, tc := range cases {
+               for i := 1; i < len(tc.data); i++ {
+                       r, err := NewReader(strings.NewReader(string(tc.data[:i])))
+                       if err != nil {
+                               if err != io.ErrUnexpectedEOF {
+                                       t.Errorf("NewReader(%s-%d) on truncated stream: got %v, want %v", tc.name, i, err, io.ErrUnexpectedEOF)
+                               }
+                               continue
+                       }
+                       _, err = io.Copy(io.Discard, r)
+                       if ferr, ok := err.(*flate.ReadError); ok {
+                               err = ferr.Err
+                       }
                        if err != io.ErrUnexpectedEOF {
-                               t.Errorf("NewReader(%d) on truncated stream: got %v, want %v", i, err, io.ErrUnexpectedEOF)
+                               t.Errorf("io.Copy(%s-%d) on truncated stream: got %v, want %v", tc.name, i, err, io.ErrUnexpectedEOF)
                        }
-                       continue
-               }
-               _, err = io.Copy(io.Discard, r)
-               if ferr, ok := err.(*flate.ReadError); ok {
-                       err = ferr.Err
-               }
-               if err != io.ErrUnexpectedEOF {
-                       t.Errorf("io.Copy(%d) on truncated stream: got %v, want %v", i, err, io.ErrUnexpectedEOF)
                }
        }
 }