diff options
author | Joe Tsai <joetsai@digital-static.net> | 2016-08-30 16:08:06 -0700 |
---|---|---|
committer | Joe Tsai <thebrokentoaster@gmail.com> | 2016-08-31 01:12:02 +0000 |
commit | d3092464624f1f0ad29fa0ac4c4069fdd0697155 (patch) | |
tree | c155e1fedfc3247cf0436604686ea6861107e34e | |
parent | 6ebacf18a5769d071f467fae455a142a964a43da (diff) | |
download | go-d3092464624f1f0ad29fa0ac4c4069fdd0697155.tar.gz go-d3092464624f1f0ad29fa0ac4c4069fdd0697155.zip |
compress/flate: always return uncompressed data in the event of error
In the event of an unexpected error, we should always flush available
decompressed data to the user.
Fixes #16924
Change-Id: I0bc0824c3201f3149e84e6a26e3dbcba72a1aae5
Reviewed-on: https://go-review.googlesource.com/28216
Run-TryBot: Joe Tsai <thebrokentoaster@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
-rw-r--r-- | src/compress/flate/inflate.go | 3 | ||||
-rw-r--r-- | src/compress/flate/inflate_test.go | 29 | ||||
-rw-r--r-- | src/compress/gzip/gunzip_test.go | 20 | ||||
-rw-r--r-- | src/compress/zlib/reader_test.go | 18 |
4 files changed, 70 insertions, 0 deletions
diff --git a/src/compress/flate/inflate.go b/src/compress/flate/inflate.go index 68cc232052..9a8c4fc455 100644 --- a/src/compress/flate/inflate.go +++ b/src/compress/flate/inflate.go @@ -344,6 +344,9 @@ func (f *decompressor) Read(b []byte) (int, error) { return 0, f.err } f.step(f) + if f.err != nil && len(f.toRead) == 0 { + f.toRead = f.dict.readFlush() // Flush what's left in case of error + } } } diff --git a/src/compress/flate/inflate_test.go b/src/compress/flate/inflate_test.go index e0bce71d6f..951decd775 100644 --- a/src/compress/flate/inflate_test.go +++ b/src/compress/flate/inflate_test.go @@ -7,6 +7,8 @@ package flate import ( "bytes" "io" + "io/ioutil" + "strings" "testing" ) @@ -38,6 +40,33 @@ func TestReset(t *testing.T) { } } +func TestReaderTruncated(t *testing.T) { + vectors := []struct{ input, output string }{ + {"\x00", ""}, + {"\x00\f", ""}, + {"\x00\f\x00", ""}, + {"\x00\f\x00\xf3\xff", ""}, + {"\x00\f\x00\xf3\xffhello", "hello"}, + {"\x00\f\x00\xf3\xffhello, world", "hello, world"}, + {"\x02", ""}, + {"\xf2H\xcd", "He"}, + {"\xf2H͙0a\u0084\t", "Hel\x90\x90\x90\x90\x90"}, + {"\xf2H͙0a\u0084\t\x00", "Hel\x90\x90\x90\x90\x90"}, + } + + for i, v := range vectors { + r := strings.NewReader(v.input) + zr := NewReader(r) + b, err := ioutil.ReadAll(zr) + if err != io.ErrUnexpectedEOF { + t.Errorf("test %d, error mismatch: got %v, want io.ErrUnexpectedEOF", i, err) + } + if string(b) != v.output { + t.Errorf("test %d, output mismatch: got %q, want %q", i, b, v.output) + } + } +} + func TestResetDict(t *testing.T) { dict := []byte("the lorem fox") ss := []string{ diff --git a/src/compress/gzip/gunzip_test.go b/src/compress/gzip/gunzip_test.go index fdce91989a..fdea0c5d5f 100644 --- a/src/compress/gzip/gunzip_test.go +++ b/src/compress/gzip/gunzip_test.go @@ -339,6 +339,26 @@ var gunzipTests = []gunzipTest{ }, nil, }, + { + "", + "truncated gzip file amid raw-block", + "hello", + []byte{ + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x0c, 0x00, 0xf3, 0xff, 0x68, 0x65, 0x6c, 0x6c, 0x6f, + }, + io.ErrUnexpectedEOF, + }, + { + "", + "truncated gzip file amid fixed-block", + "He", + []byte{ + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xf2, 0x48, 0xcd, + }, + io.ErrUnexpectedEOF, + }, } func TestDecompressor(t *testing.T) { diff --git a/src/compress/zlib/reader_test.go b/src/compress/zlib/reader_test.go index f74bff1f3c..7e27aecb47 100644 --- a/src/compress/zlib/reader_test.go +++ b/src/compress/zlib/reader_test.go @@ -121,6 +121,24 @@ var zlibTests = []zlibTest{ }, ErrDictionary, }, + { + "truncated zlib stream amid raw-block", + "hello", + []byte{ + 0x78, 0x9c, 0x00, 0x0c, 0x00, 0xf3, 0xff, 0x68, 0x65, 0x6c, 0x6c, 0x6f, + }, + nil, + io.ErrUnexpectedEOF, + }, + { + "truncated zlib stream amid fixed-block", + "He", + []byte{ + 0x78, 0x9c, 0xf2, 0x48, 0xcd, + }, + nil, + io.ErrUnexpectedEOF, + }, } func TestDecompressor(t *testing.T) { |