Skip to content

Commit

Permalink
reader: Fix missing buffers (#35)
Browse files Browse the repository at this point in the history
When resetting before reading all content temporary buffers were lost.

Make sure to re-add temporary buffers.

Fixes #34
  • Loading branch information
klauspost committed Sep 2, 2020
1 parent 82f3a65 commit 52335df
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 8 deletions.
17 changes: 10 additions & 7 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
language: go

sudo: false

os:
- linux
- osx

go:
- 1.9.x
- 1.10.x
- 1.13.x
- 1.14.x
- 1.15.x
- master

script:
- go test -v -cpu=1,2,4 .
- go test -v -cpu=2 -race -short .
env:
- GO111MODULE=off

script:
- diff <(gofmt -d .) <(printf "")
- go test -v -cpu=1,2,4 .
- go test -v -cpu=2 -race -short .

matrix:
allow_failures:
Expand Down
11 changes: 11 additions & 0 deletions gunzip.go
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,16 @@ func (z *Reader) killReadAhead() error {
// Wait for decompressor to be closed and return error, if any.
e, ok := <-z.closeErr
z.activeRA = false

for blk := range z.readAhead {
if blk.b != nil {
z.blockPool <- blk.b
}
}
if cap(z.current) > 0 {
z.blockPool <- z.current
z.current = nil
}
if !ok {
// Channel is closed, so if there was any error it has already been returned.
return nil
Expand Down Expand Up @@ -418,6 +428,7 @@ func (z *Reader) doReadAhead() {
case z.readAhead <- read{b: buf, err: err}:
case <-closeReader:
// Sent on close, we don't care about the next results
z.blockPool <- buf
return
}
if err != nil {
Expand Down
95 changes: 94 additions & 1 deletion gunzip_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"io"
"io/ioutil"
"os"
"runtime/pprof"
"strings"
"testing"
"time"
Expand Down Expand Up @@ -331,6 +332,98 @@ func TestDecompressor(t *testing.T) {
}
}

func TestDecompressorReset(t *testing.T) {
b := new(bytes.Buffer)
var gzip *Reader

for _, tt := range gunzipTests {
in := bytes.NewReader(tt.gzip)
if gzip == nil {
var err error
gzip, err = NewReader(in)
if err != nil {
t.Fatalf("NewReader: %s", err)
}
defer gzip.Close()
} else {
err := gzip.Reset(in)
if err != nil {
t.Errorf("%s: Reset: %s", tt.name, err)
continue
}
}
if tt.name != gzip.Name {
t.Errorf("%s: got name %s", tt.name, gzip.Name)
}
b.Reset()

n, err := io.Copy(b, gzip)
if err != tt.err {
t.Errorf("%s: io.Copy: %v want %v", tt.name, err, tt.err)
}
s := b.String()
if s != tt.raw {
t.Errorf("%s: got %d-byte %q want %d-byte %q", tt.name, n, s, len(tt.raw), tt.raw)
}

// Test Reader Reset.
in = bytes.NewReader(tt.gzip)
err = gzip.Reset(in)
if err != nil {
t.Errorf("%s: Reset: %s", tt.name, err)
continue
}
if tt.name != gzip.Name {
t.Errorf("%s: got name %s", tt.name, gzip.Name)
}
b.Reset()
n, err = io.Copy(b, gzip)
if err != tt.err {
t.Errorf("%s: io.Copy: %v want %v", tt.name, err, tt.err)
}
s = b.String()
if s != tt.raw {
t.Errorf("%s: got %d-byte %q want %d-byte %q", tt.name, n, s, len(tt.raw), tt.raw)
}
}
}

func TestDecompressorResetNoRead(t *testing.T) {
done := make(chan struct{})
defer close(done)
go func() {
select {
// Typical runtime is 2-3s, so we add an order of magnitude.
case <-time.After(30 * time.Second):
pprof.Lookup("goroutine").WriteTo(os.Stdout, 1)
case <-done:
}
}()
in, err := ioutil.ReadFile("testdata/bigempty.gz")
if err != nil {
t.Fatal(err)
}
gz, err := NewReader(bytes.NewBuffer(in))
if err != nil {
t.Fatal(err)
}
for i := 0; i < 100; i++ {
if testing.Short() && i > 10 {
break
}
err := gz.Reset(bytes.NewBuffer(in))
if err != nil {
t.Fatal(i, err)
}
// Read 100KB, ignore the rest
lr := io.LimitedReader{N: 100 << 10, R: gz}
_, err = io.Copy(ioutil.Discard, &lr)
if err != nil {
t.Fatal(i, err)
}
}
}

func TestIssue6550(t *testing.T) {
f, err := os.Open("testdata/issue6550.gz")
if err != nil {
Expand Down Expand Up @@ -637,7 +730,7 @@ func TestTruncatedGunzipBlocks(t *testing.T) {
rand.Read(in)
var buf bytes.Buffer
for i := 0; i < len(in); i += 512 {
enc,_ := kpgzip.NewWriterLevel(&buf, 0)
enc, _ := kpgzip.NewWriterLevel(&buf, 0)
_, err := enc.Write(in[:i])
if err != nil {
t.Fatal(err)
Expand Down
Binary file added testdata/bigempty.gz
Binary file not shown.

0 comments on commit 52335df

Please sign in to comment.