Skip to content

Commit

Permalink
Merge pull request #14 from klauspost/fix-truncated-gzip-input
Browse files Browse the repository at this point in the history
Fix truncated gzip input
  • Loading branch information
klauspost authored Apr 2, 2017
2 parents 136f77a + c0e4ca7 commit 0bf5dca
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 1 deletion.
11 changes: 10 additions & 1 deletion gunzip.go
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,16 @@ func (z *Reader) doReadAhead() {
// Try to fill the buffer
n, err := io.ReadFull(decomp, buf)
if err == io.ErrUnexpectedEOF {
err = nil
if n > 0 {
err = nil
} else {
// If we got zero bytes, we need to establish if
// we reached end of stream or truncated stream.
_, err = decomp.Read([]byte{})
if err == io.EOF {
err = nil
}
}
}
if n < len(buf) {
buf = buf[0:n]
Expand Down
71 changes: 71 additions & 0 deletions gunzip_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -596,3 +596,74 @@ func BenchmarkGunzipFlate(b *testing.B) {
}
}
}

func TestTruncatedGunzip(t *testing.T) {
in := []byte(strings.Repeat("ASDFASDFASDFASDFASDF", 1000))
var buf bytes.Buffer
enc := kpgzip.NewWriter(&buf)
_, err := enc.Write(in)
if err != nil {
t.Fatal(err)
}
enc.Close()
testdata := buf.Bytes()
for i := 5; i < len(testdata); i += 10 {
timer := time.NewTimer(time.Second)
done := make(chan struct{})
fail := make(chan struct{})
go func() {
r, err := NewReader(bytes.NewBuffer(testdata[:i]))
if err == nil {
b, err := ioutil.ReadAll(r)
if err == nil && !bytes.Equal(testdata[:i], b) {
close(fail)
}
}
close(done)
}()
select {
case <-timer.C:
t.Fatal("Timeout decoding")
case <-fail:
t.Fatal("No error, but mismatch")
case <-done:
timer.Stop()
}
}
}

func TestTruncatedGunzipBlocks(t *testing.T) {
var in = make([]byte, 512*10)
rand.Read(in)
var buf bytes.Buffer
for i := 0; i < len(in); i += 512 {
enc,_ := kpgzip.NewWriterLevel(&buf, 0)
_, err := enc.Write(in[:i])
if err != nil {
t.Fatal(err)
}
enc.Close()

timer := time.NewTimer(time.Second)
done := make(chan struct{})
fail := make(chan struct{})
go func() {
r, err := NewReaderN(&buf, 512, 10)
if err == nil {
b, err := ioutil.ReadAll(r)
if err == nil && !bytes.Equal(b, in[:i]) {
close(fail)
}
}
close(done)
}()
select {
case <-timer.C:
t.Fatal("Timeout decoding")
case <-fail:
t.Fatal("No error, but mismatch")
case <-done:
timer.Stop()
}
}
}

0 comments on commit 0bf5dca

Please sign in to comment.